Skip to content

Commit

Permalink
Update single fetch headers approach to use response stub API (#9142)
Browse files Browse the repository at this point in the history
Co-authored-by: Jacob Ebey <jacob.ebey@live.com>
  • Loading branch information
brophdawg11 and jacob-ebey authored Mar 27, 2024
1 parent 1fa128c commit 23e6c0c
Show file tree
Hide file tree
Showing 17 changed files with 1,178 additions and 217 deletions.
25 changes: 25 additions & 0 deletions .changeset/response-stub.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
"@remix-run/server-runtime": patch
---

Add `ResponseStub` header interface for single fetch and deprecate the `headers` export

- The `headers` export is no longer used when single fetch is enabled
- `loader`/`action` functions now receive a mutable `response` parameter
- `type ResponseStub = { status: numbers | undefined, headers: Headers }`
- To alter the status of a response, set the `status` field directly
- `response.status = 201`
- To set headers on the Response, you may use:
- `response.headers.set`
- `response.headers.append`
- `response.headers.delete`
- Each `loader`/`action`receives it's own unique `response` instance so you cannot see what other `loader`/`action` functions have set (which would be subject to race conditions)
- If all status codes are unset or have values <200, the deepest status code will be used for the HTTP response
- If any status codes are set to a value >=300, the highest >=300 value will be used for the HTTP Response
- Remix tracks header operations and will replay them in order (action if present, then loaders top-down) after all handlers have completed on a fresh `Headers` instance that will be applied to the HTTP Response
- `headers.set` on any child handler will overwrite values from parent handlers
- `headers.append` can be used to set the same header from both a parent and child handler
- `headers.delete` can be used to delete a value set by a parent handler, but not a value set from a child handler
- Because single fetch supports naked object returns, and you no longer need to return a `Response` instance to set status/headers, the `json`/`redirect`/`redirectDocument`/`defer` utilities are considered deprecated when using Single Fetch
- You may still continue returning normal `Response` instances and they'll apply status codes in the same way, and will apply all headers via `headers.set` - overwriting any same-named header values from parents
- If you need to append, you will need to switch from returning a `Response` instance to using the new `response` parameter
16 changes: 13 additions & 3 deletions integration/error-boundary-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2229,9 +2229,19 @@ test.describe("single fetch", () => {
expect(await app.getHtml("#parent-error")).toEqual(
'<p id="parent-error">Broken!</p>'
);
expect(await app.getHtml("#parent-matches-data")).toEqual(
'<p id="parent-matches-data"></p>'
);
if (javaScriptEnabled) {
// This data remains in single fetch with JS because we don't revalidate
// due to the 500 action response
expect(await app.getHtml("#parent-matches-data")).toEqual(
'<p id="parent-matches-data">PARENT</p>'
);
} else {
// But without JS document requests call all loaders up to the
// boundary route so parent's data clears out
expect(await app.getHtml("#parent-matches-data")).toEqual(
'<p id="parent-matches-data"></p>'
);
}
expect(await app.getHtml("#parent-data")).toEqual(
'<p id="parent-data"></p>'
);
Expand Down
2 changes: 1 addition & 1 deletion integration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@remix-run/dev": "workspace:*",
"@remix-run/express": "workspace:*",
"@remix-run/node": "workspace:*",
"@remix-run/router": "0.0.0-experimental-c7dd3d3a",
"@remix-run/router": "0.0.0-experimental-0f302655",
"@remix-run/server-runtime": "workspace:*",
"@types/express": "^4.17.9",
"@vanilla-extract/css": "^1.10.0",
Expand Down
6 changes: 3 additions & 3 deletions integration/revalidate-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,9 @@ test.describe("single fetch", () => {
<li><Link to="/">/</Link></li>
<li><Link to="/parent">/parent</Link></li>
<li><Link to="/parent/child">/parent/child</Link></li>
<li><Link to="/parent/child?revalidate=parent">/parent/child</Link></li>
<li><Link to="/parent/child?revalidate=child">/parent/child</Link></li>
<li><Link to="/parent/child?revalidate=parent,child">/parent/child</Link></li>
<li><Link to="/parent/child?revalidate=parent">/parent/child?revalidate=parent</Link></li>
<li><Link to="/parent/child?revalidate=child">/parent/child?revalidate=child</Link></li>
<li><Link to="/parent/child?revalidate=parent,child">/parent/child?revalidate=parent,child</Link></li>
</ul>
</nav>
<Outlet />
Expand Down
Loading

0 comments on commit 23e6c0c

Please sign in to comment.