Skip to content

Unify the web Response binding into Fetch.Response#26

Merged
reebalazs merged 1 commit into
mainfrom
web-response-binding
Jun 25, 2026
Merged

Unify the web Response binding into Fetch.Response#26
reebalazs merged 1 commit into
mainfrom
web-response-binding

Conversation

@reebalazs

@reebalazs reebalazs commented Jun 24, 2026

Copy link
Copy Markdown
Member

App Router route handlers return a web Response, but the bindings had no way to construct one — only the read side (FetchResponse, what fetch resolves to). Since it's one Web API type, this folds the construct side into the existing record module rather than adding a second type.

What

  • Rename FetchResponseResponse, kept as a deprecated module FetchResponse = Response alias so existing consumers keep compiling.
  • Add make(body, init) (new Response; body Nullable.t<string>, init = {status?, statusText?, headers?: Headers.t}) and the static redirect(url, status).
  • Add a headers: Headers.t read field — response headers weren't readable at all before.
  • fetch now returns Response.t.

Headers are typed Headers.t (consistent with NextServer.NextResponse.options), not a dict.

Breaking-change analysis

The record stays a record, so read access is unchanged (res.status, res.json()), and FetchResponse survives as an alias — so:

Breaks?
Read access res.status / res.json() No (record unchanged)
FetchResponse name / fetch return type No (alias = same type)
Adding the headers field Only breaks constructing a FetchResponse.t record literal

The one theoretical break (record-literal construction) has zero occurrences across rescript-next, njc, and vialab (checked: vialab consumes only Fetch.Headers + fetchJson, never FetchResponse).

Tested against the runtime (status + headers round-trip for make and redirect). No version bump (left for the release).

App Router route handlers return a web `Response`, but the bindings had no way
to construct one — only the read side (`FetchResponse`, what `fetch` resolves
to). It's one Web API type, so rather than add a second type for it, fold the
construct side into the existing record module:

- Rename `FetchResponse` -> `Response`, kept as a deprecated
  `module FetchResponse = Response` alias so existing consumers keep compiling.
- Add `make(body, init)` (`new Response`, nullable body, init
  status/statusText/headers) and the static `redirect(url, status)`.
- Add a `headers: Headers.t` read field (response headers weren't readable).
- `fetch` now returns `Response.t`.

Headers are typed `Headers.t` (consistent with NextServer.NextResponse.options),
not a dict. Read access (`res.status`, `res.json()`) is unchanged, so this is
non-breaking for read consumers; the only theoretical break — constructing a
`FetchResponse.t` record literal — occurs nowhere in rescript-next, njc, or
vialab. Tested against the runtime.
@reebalazs
reebalazs force-pushed the web-response-binding branch from 6f8caa3 to 7fb7e52 Compare June 25, 2026 08:38
@reebalazs reebalazs changed the title Add a web Response binding (Fetch.Response) for route handlers Unify the web Response binding into Fetch.Response Jun 25, 2026
@reebalazs
reebalazs merged commit b0b5f04 into main Jun 25, 2026
2 checks passed
@reebalazs
reebalazs deleted the web-response-binding branch June 25, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant