sveltejs / sveltejs/kit

Endpoint fallback broken when Accept header includes lower-priority text/html

Open
#13,834 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
20.8k
Forks
2.3k
Avg merge
1d 16h
Merged PRs (30d)
156

Description

Describe the bug

In is_endpoint_request(), the code checks:

negotiate(accept, ['*', 'text/html']) !== 'text/html'

to determine if a request should be treated as an endpoint request (i.e. not a page/navigation). The intention appears to be to treat any request that does not prefer text/html as an endpoint call.

However, the underlying negotiate() implementation:

  1. Does not treat '*' as a wildcard to return the highest-priority MIME type.
  2. Always returns text/html if text/html appears anywhere in the Accept header, regardless of its relative quality factor (priority).

As a result, any request with an Accept header containing text/html (even if it has a lower quality than another MIME type) will be considered a "page" request, preventing the endpoint fallback from firing as documented.

Reproduction
  1. Create an /feed route containing both:
    • +page.svelte (HTML subscription prompt)
    • +server.ts (actual Atom XML feed)
  2. Send a request with a mixed Accept header, for example(mimicking FreshRSS's: DEFAULT_HTTP_ACCEPT_HEADER):
curl -H "Accept: application/atom+xml, text/html; q=0.1" http://localhost:5173/feed
  1. Because text/html appears (even with a lower quality), the request is negotiated as a page request, and the endpoint’s Atom XML is never returned.
Logs

System Info
System:
    OS: Windows 11 10.0.26100
    CPU: (16) x64 AMD Ryzen 7 7840HS w/ Radeon 780M Graphics     
    Memory: 17.17 GB / 31.28 GB
  Binaries:
    Node: 23.10.0 - C:\Program Files\nodejs\node.EXE
    npm: 11.4.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (134.0.3124.68)
  npmPackages:
    @sveltejs/adapter-node: ^5.2.12 => 5.2.12
    @sveltejs/kit: ^2.21.1 => 2.21.1
    @sveltejs/vite-plugin-svelte: ^5.0.3 => 5.0.3
    svelte: ^5.31.1 => 5.31.1
    vite: ^6.3.5 => 6.3.5
Severity

serious, but I can work around it

Additional Information

I understand that mixing +page.svelte and +server.ts on the same route /feed is somewhat unconventional, but it’s a valid pattern for serving both human-friendly and machine-readable representations of the same resource.

Some feed readers may include text/html with low priority but expect the server to honor the higher-priority XML types.

Thank you for looking into this! Let me know if any further details or tests would help.

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 by reading packages/kit/src/runtime/server/endpoint.js, especially is_endpoint_request(), and packages/kit/src/utils/http.js, then reproduce the behavior with the mixed Accept header from the issue. Verify the finished change by confirming that a higher-priority non-HTML type reaches the endpoint fallback while HTML remains preferred when appropriate.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.