Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring back support for content negotiation (allow +page.svelte & +server.ts to co-exist) #5896

Closed
CaptainCodeman opened this issue Aug 15, 2022 · 3 comments · Fixed by #6773
Milestone

Comments

@CaptainCodeman
Copy link
Contributor

CaptainCodeman commented Aug 15, 2022

Describe the problem

Previous versions of SvelteKit supported content negotiation where a route could serve HTML to browsers or JSON data if an accept header was used for a data request (as well as supporting data being posted to the same route).

Existing sites may already use this, it's been part of HTTP since forever. You might want to replace such a site with SvelteKit (or previously relied on SvelteKit supporting this) but changing the existing URL structure would be problematic and impactful (other systems using endpoints, pages already indexed and publicized etc...)

I think a router should be flexible enough to support existing URL structures, even if they are not the favoured default for the framework.

Describe the proposed solution

Support the accept header in the routing and allow application/json requests to an endpoint at the same route. Pages should only be concerned with GET requests with no accept header (or one for html content).

Alternatives considered

Adding a load function to +page.server.ts allows a GET request for data, but makes it difficult to control the response and would limit things to JSON (maybe you want CSV, PDF, or XML). It also appears limited in terms of what control you have over the response (http headers etc...) and still leaves you unable to use other HTTP methods.

Update: it appears that I should be treating load as GET and the other methods are supported. However they are inconsistent in terms of signature and what response is returned.

Importance

i cannot use SvelteKit without it

Additional Information

No response

@Rich-Harris
Copy link
Member

I'm not sure the proposed logic is quite right — there's nothing special about application/json. What about rendering the page if text/html is accepted, and falling back to +server.js in all other cases?

Pending the outcome of #5875, what happens if +page.server.js specifies POST (or PUT/PATCH/DELETE) and these methods are also defined in +server.js? Is it the same — use the +page.server.js if text/html is accepted, and +server.js otherwise? (A fetch request is populated with */* by default, under which text/html is accepted, so this would use +page.server.js before +server.js.)

@CaptainCodeman
Copy link
Contributor Author

CaptainCodeman commented Aug 15, 2022

Yes, the negotiation part is more about the request not coming from a regular web browser page request, so only being limited to a particular type. I used application/json as it's likely going to be the most common / 90-99% use-case.

The overlap between +page.server.js and +server.js POST / PUT etc... methods is a little confusing, I'm still going through the docs and trying things out but the initial feel is that things overlap and it's not entirely clear why I would want to use one vs the other. But I take it this might already be subject to change with the form / action stuff.

Taking that into account, I would prefer that +server.js be the fallback and it would make more sense if the +page.actions.js / +server.actions.js (?) is really going to map to a different hidden URL anyway so there wouldn't be any conflict at that point.

@lkj4
Copy link

lkj4 commented Sep 8, 2022

Just learned from @s3812497 in discussion that we can't do GET application/json requests against +page.server.ts (former shadow endpoints) anymore.

My use case: I have bigger content properties but send only smaller, requested chunks via REST. With the initial pageload the user gets the first part and then, within the client the user can request further parts without the need to reload the page. Both use the exact same API and DB call.

It'd be nice to just use the same +page.server.ts for this, e.g. with a { headers: { accept: 'application/json' } }. I get super fast initial loads because the API request is preloaded and my code stays clean.

Why not +server.ts? Then, I'd need another dedicated +page.ts with a load function. Before, shadow endpoints gave you the highest flexibility with the least LOC and redundancy.

Not sure if I miss something and/or this would align well with #5875

Rich-Harris added a commit that referenced this issue Sep 19, 2022
* [feat] allow +server.js files next to +page files

Closes #5896

* Update packages/kit/src/runtime/server/endpoint.js

Co-authored-by: Rich Harris <richard.a.harris@gmail.com>

* simplify rules and document them

* adjust builder type

* Update documentation/docs/06-form-actions.md

Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>

* link

* remove unused type

* move docs to +server.js section

Co-authored-by: Rich Harris <richard.a.harris@gmail.com>
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Co-authored-by: Rich Harris <hello@rich-harris.dev>
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 a pull request may close this issue.

4 participants