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

fetch() does not work properly on the server when base path is set #11078

Open
thet0ast3r opened this issue Nov 19, 2023 · 2 comments
Open

fetch() does not work properly on the server when base path is set #11078

thet0ast3r opened this issue Nov 19, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@thet0ast3r
Copy link

thet0ast3r commented Nov 19, 2023

Describe the bug

When using sveltekit on the same host as an external api, fetching like this in load functions works -
(using sveltekit's fetch)
fetch('/products/...')
that is, when in svelte.config.js paths.base is not set or set to ''.

If however the base path is set to something other than '', all server side requests (in load functions) to an 'external' path fail, making it impossible to ssr pages with calls to e.g. /api/... from /base/ .

Reproduction

https://github.com/thet0ast3r/kit-fetch-bug

Here is a minimal example.
Please note that this repo proxies requests to /products to dummyjson, to simulate an external api that has the same domain.

run npm run dev

click on 'navigate to someroute'
click on 'navigate to home/base'
reload home '/test' to prompt ssr

in svelte.config.js, change base to '', and repeat the last 3 steps.
Notice how ssr now works correctly.

Logs

No relevant logs. Request returns "Not Found" and 404 on the server side.

This is the response object:

Response {
  [Symbol(realm)]: { settingsObject: {} },
  [Symbol(state)]: {
    aborted: false,
    rangeRequested: false,
    timingAllowPassed: false,
    requestIncludesCredentials: false,
    type: 'default',
    status: 404,
    timingInfo: null,
    cacheState: '',
    statusText: '',
    headersList: HeadersList {
      cookies: null,
      [Symbol(headers map)]: [Map],
      [Symbol(headers map sorted)]: null
    },
    urlList: [],
    body: { stream: undefined, source: [Uint8Array], length: 9 }
  },
  [Symbol(headers)]: HeadersList {
    cookies: null,
    [Symbol(headers map)]: Map(1) { 'content-length' => [Object] },
    [Symbol(headers map sorted)]: null
  }
}

System Info

System:
    OS: macOS 14.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 56.72 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.8.0 - /usr/local/bin/node
    npm: 8.18.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 119.0.6045.159
    Safari: 17.1
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.1.1 
    @sveltejs/kit: ^1.27.4 => 1.27.6 
    svelte: ^4.0.5 => 4.2.5 
    vite: ^4.4.2 => 4.5.0

Severity

blocking all usage of SvelteKit

Additional Information

No response

@thet0ast3r
Copy link
Author

thet0ast3r commented Nov 20, 2023

Update:
I think i found where the problem occurs.

In /src/runtime/server/respond.js, line 91:

changing this snippet

	if (base && !state.prerendering?.fallback) {
		if (!decoded.startsWith(base)) {
			return text('Not found', { status: 404 });
		}
		decoded = decoded.slice(base.length) || '/';
	}

to this:

	if (base && !state.prerendering?.fallback) {
		/*
		if (!decoded.startsWith(base)) {
			return text('Not found', { status: 404 });
		}*/
		decoded = decoded.slice(base.length) || '/';
	}

solves the issue.
Ofc, this is not a fix, but the root cause of the problem.
A request lands here, it has a base, but then the request does not start with 'base' so just 'Not found' is returned, even though there might be another app living on that route.

This also explains why this works when base is the empty string: this part is never executed. So the only thing i see that this code accomplishes is it doesn't allow access to routes lower than 'base', which conflicts with the browser behavior.
A sveltekit fetch() in the browser will happily respond with whatever is at a route other than 'base', whereas the server's fetch replication will just respond with 404 'Not found'.

edit:
it probably should look something more like this:

	if (base && !state.prerendering?.fallback) {
		
		if (decoded.startsWith(base)) {
			decoded = decoded.slice(base.length) || '/';
		}
		
	}

@rlopez4

This comment was marked as duplicate.

@eltigerchino eltigerchino added the bug Something isn't working label Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants