Replies: 5 comments 15 replies
-
This was discussed in Roadmap #5, around 20'55 The workaround is to implement a |
Beta Was this translation helpful? Give feedback.
-
Building on this topic, the Form Validation docs show this: export const action = async ({ request }: ActionArgs) => {
const formData = await request.formData();
const [errors, project] = await createProject(formData);
if (errors) {
const values = Object.fromEntries(formData);
return json({ errors, values });
}
return redirect(`/projects/${project.id}`);
}; That absolutely works, but it delivers a pretty lousy experience for non-JS browsers. Who wants to see a page with nothing but a JSON-encoded error message? Adapting the Rails pattern mentioned above, this might become return respondTo(request.headers, {
json: () => json({ errors, values }),
html: () => {
return redirectBackOrDefault('/', {
headers: { 'set-cookie': flash(errors) }
}
},
}) |
Beta Was this translation helpful? Give feedback.
-
FYI, SvelteKit supports content-negotiation by using two different files formats under the same route :
|
Beta Was this translation helpful? Give feedback.
-
👋 Another vote in support of this. My usecase is pretty similar to how deno.land supports a page like this: https://deno.land/std@0.199.0/bytes/bytes_list.ts - which renders HTML for browsers but returns TypeScript for Deno and other clients. The options for this kind of problem - content negotiation - in Remix are lackluster. I can't implement a system where you add |
Beta Was this translation helpful? Give feedback.
-
TIL that the behavior of an The Let people handle caching in their own way. It would still be possible to use other methods to fix the caching problem even if you did support Also, even just having a way to make an |
Beta Was this translation helpful? Give feedback.
-
Proposal
Make Remix respect the HTTP Accept header and if it's not text/html send the loader data instead, even if the route is a UI route.
Background
The Accept header let clients (like browsers or another app) let the server know what type of responses it can handle. Then the server can send a different response type based on that.
Right now, you can use it in a resource route quite simple:
If a UI route (a route with a
export default
) wants to support this it's not possible, Remix will always attempt to render the app, the only way to skip it is with the special_data
search param.Use Case
API/Examples
The idea would be for Remix to detect the header and if the Accept is not
text/html
treat the request as a resource route request.This would mean that Remix will call any leaf route matching the request and it will send the loader response, if the developer wants to support more than JSON it should manually check the Accept header to return something different based on that.
If the request comes with the
text/html
inside Accept Remix should treat the request a document one and call all matching routes.Remix must still use the
_data
search param to ensure the URL for JSON and the URL for document made by Remix itself are different and avoid any issue with CDNs not respecting Accept header.For requests with the Accept not being
text/html
it should be documented somewhere that CDNs may cache the responses so developers can take care of that and avoid setting Cache-Control or use a CDN which correctly handle Accept and Vary.Prior Art
Rails works this way, you can use a single controller to send different response types like HTML or JSON, they even give you a function to do the conditions easier
This could either be implemented by Remix or left to devs to do it, maybe Remix Utils could provide a helper
Beta Was this translation helpful? Give feedback.
All reactions