sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.52k stars 1.9k forks source link

Access route result in Not Found during dev when the route is encoded URI #7075

Open kwchang0831 opened 2 years ago

kwchang0831 commented 2 years ago

Describe the bug

Routing result is Not Found if the route is encoded URI during dev server. eg: With route src/routes/%E5%88%9D%E3%82%81/+page.svelte when navigating to http://localhost:5173/%E5%88%9D%E3%82%81

Not found: /src/routes/%E5%88%9D%E3%82%81/+page.svelte
Error: Not found: /src/routes/%E5%88%9D%E3%82%81/+page.svelte

However, preview works as expected. After pnpm build && pnpm preview, the route http://localhost:4173/%E5%88%9D%E3%82%81 is accessible.

For the reference:

encodeURI('初め') => '%E5%88%9D%E3%82%81'

Reproduction

https://github.com/kwchang0831/issue-sveltekit-already-encoded-route

To Reproduce:

  1. Create a route with encoded URI. eg: src/routes/%E5%88%9D%E3%82%81/+page.svelte.
  2. Set export const prerender = true; in +layout.ts.
  3. Run pnpm dev.
  4. In browser, navigate to the route http://localhost:5173/%E5%88%9D%E3%82%81.

Logs

No response

System Info

System:
    OS: Linux 5.15 Ubuntu 22.04.1 LTS 22.04.1 LTS (Jammy Jellyfish)
    CPU: (12) x64 Intel(R) Xeon(R) CPU D-1541 @ 2.10GHz
    Memory: 22.60 GB / 31.35 GB
    Container: Yes
    Shell: 3.5.1 - /usr/bin/fish
  Binaries:
    Node: 18.7.0 - ~/.asdf/installs/nodejs/18.7.0/bin/node
    Yarn: 1.22.19 - ~/.asdf/shims/yarn
    npm: 8.15.0 - ~/.asdf/plugins/nodejs/shims/npm
  Browsers:
    Firefox: 105.0.1
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.80 
    @sveltejs/kit: next => 1.0.0-next.505 
    svelte: ^3.44.0 => 3.50.1 
    vite: ^3.1.0 => 3.1.4

Severity

serious, but I can work around it

Additional Information

If the route name is %E5%88 which is not a valid encoded URI, just a arbitrary string, it will result in URIError: URI malformed when access the route.

So, it seems like when handing route name, it assumes that the name is previously encoded or just to make sure the name is not encoded.

benmccann commented 2 years ago

Name your folder 初め instead of %E5%88%9D%E3%82%81 and I expect it will work

Conduitry commented 2 years ago

If dev and preview are behaving differently from one another, this does sound like a bug of some sort to me.

kwchang0831 commented 2 years ago

I understand that a normal user probably wouldn't even use encoded URI as route name. That's counter-intuitive.

I found out this issue because I had problem when the folder is naming 初め. That will only work in dev but NOT preview which describes in #7074. I was trying to see if there is another way to bypass the issue that prerender fails when routes contains unicode characters.

dummdidumm commented 2 years ago

It renders correctly on the server, but something then happens on the client that makes it fail.

kwchang0831 commented 2 years ago

Yes, the first request is /%E5%88%9D%E3%82%81, it renders correctly. Then, it immediately request /src/routes/%E5%88%9D%E3%82%81/+page.svelte which fails with Not Found as end result.

dummdidumm commented 2 years ago

The culprit is somewhere at https://github.com/sveltejs/kit/blob/5161241d523d47376525d73d1bb04a2d0b250972/packages/kit/src/exports/vite/dev/index.js#L257-L270 or https://github.com/sveltejs/kit/blob/5161241d523d47376525d73d1bb04a2d0b250972/packages/kit/src/exports/vite/dev/index.js#L294-L305 I believe - although it still doesn't work when I remove the decode there (which is probably there for good reason and shouldn't be removed anyway)

georgecrawford commented 1 year ago

I wonder if https://github.com/sveltejs/kit/issues/7570 relates to this. I'm intrigued that a test with a route containing %40 (i.e. @) works fine in dev mode - Vite is able to load the source for /routes/%40/+page.svelte - but that a test with a route containing %5F (i.e. _) does not work in dev mode - the source code isn't returned, and instead SvelteKit attempts to do a route fallthrough and serve +page.svelte in some other way. (You can see this in my failing test).

Is the difference all about how encodeUriComponent and decodeUriComponent work?

decodeURIComponent('%40'); // gives '@'
decodeURIComponent('%5F'); // gives '_'

encodeURIComponent('@'); //  gives '%40'
encodeURIComponent('_'); // gives '_'    <<<<<<<<<<<