maragudk / maragudk/gomponents

Investigate setting Content-Type in http.Adapt

Open
#351 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
1.9k
Forks
59
Avg merge
1d 12h
Merged PRs (30d)
17

Description

`http.Adapt` doesn't set a `Content-Type` header, so `net/http` sniffs one from the first bytes of the response. Documents and fragments starting with a few tags come out as `text/html`, but fragments starting with most other tags come out as `text/plain`.

```go
h := ghttp.Adapt(func(http.ResponseWriter, *http.Request) (g.Node, error) {
return html.Tr(html.Td(g.Text("hat"))), nil
})
srv := httptest.NewServer(h)
res, _ := http.Get(srv.URL)
fmt.Println(res.Header.Get("Content-Type")) // text/plain; charset=utf-8
```

Observed on main (df71cfa), rendering each node through `Adapt`:

| Node | Real server (`httptest.NewServer`) | `httptest.NewRecorder` |
|---|---|---|
| `HTML5(...)` document | `text/html; charset=utf-8` | `text/html; charset=utf-8` |
| `

` fragment | `text/html; charset=utf-8` | `text/plain; charset=utf-8` |
| `

` fragment | `text/html; charset=utf-8` | `text/plain; charset=utf-8` |
| ``, `

  • `, ``, ``, `` fragment | `text/plain; charset=utf-8` | `text/plain; charset=utf-8` |

    Two things are going on:

    - The real server buffers up to 2 KB before writing headers, then sniffs with `http.DetectContentType`. That only recognises a handful of tags (`` in one call, which is why documents come out right.

    This matters for fragment responses. htmx swaps a `text/plain` response anyway, but Datastar picks what to do with a response from its `Content-Type`, so a `text/plain` fragment isn't patched.

    Options to consider:

    1. Have `Adapt` set `Content-Type: text/html; charset=utf-8` when the handler hasn't set one, before any `WriteHeader` call.
    2. Leave `Adapt` as is and document that fragment handlers should set the header.

    Option 1 looks like the smaller surprise. It does change behaviour for a handler that returns `Raw` plain text and relies on sniffing to get `text/plain`, so it's worth checking whether that happens in practice.

  • Contributor guide

    Open the contributing guide

    First steps

    1. Read the whole issue, then the project's contributing guide.
    2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
    3. Fork the repository and make your change on a branch.
    4. Open a pull request that references the issue number.

    Research direction

    Start at the http.Adapt entry point and reproduce the Content-Type difference with httptest.NewServer and httptest.NewRecorder using the element and document examples. Check how handlers returning Raw plain text currently behave, then add focused coverage for fragment responses and any intended plain-text exception. Done means the chosen behavior is consistent for real servers and recorders and the tests document it.

    Written by the indexing model from the issue text.

    Assessment

    Tech stack
    go
    Domain
    api, backend
    Issue type
    Bug
    Difficulty
    3/5
    Estimated time
    1-2 days
    Activity status
    Active
    Clarity
    Mostly clear
    Newbie friendliness
    68/100

    Get new issues in your inbox

    A short digest of beginner-friendly GitHub issues.