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

[fix] decode path only once to fix loading unicode routes #2167

Closed
wants to merge 5 commits into from

Conversation

noahsalvi
Copy link

@noahsalvi noahsalvi commented Aug 11, 2021

Fixes #2166

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check
    running check returns this.. but i don't think thats due to my changes
Scope: all 12 workspace projects
packages/kit check$ tsc && svelte-check --ignore "src/core/make_package/test"
[3 lines collapsed]
│ Error while loading config
│ TypeError: Cannot read property 'compilerOptions' of undefined
│     at ConfigLoader.loadConfig (/Users/noahsalvi/workspace/kit/node_modules/.pnpm/[email protected][email protected]/node_m
│     at async ConfigLoader.loadAndCacheConfig (/Users/noahsalvi/workspace/kit/node_modules/.pnpm/[email protected]_svelte
│     at async /Users/noahsalvi/workspace/kit/node_modules/.pnpm/[email protected][email protected]/node_modules/svelte-check
│     at async Promise.all (index 2)
│     at async ConfigLoader.loadConfigs (/Users/noahsalvi/workspace/kit/node_modules/.pnpm/[email protected][email protected]
│     at async createLanguageService (/Users/noahsalvi/workspace/kit/node_modules/.pnpm/[email protected][email protected]/no
│ ====================================
│ svelte-check found 0 errors, 0 warnings, and 0 hints
└─ Done in 11.1s
packages/adapter-static check$ tsc
└─ Done in 1.7s
packages/create-svelte check$ tsc
└─ Done in 2.6s

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpx changeset and following the prompts. All changesets should be patch until SvelteKit 1.0

@changeset-bot
Copy link

changeset-bot bot commented Aug 11, 2021

🦋 Changeset detected

Latest commit: 50dfe21

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@sveltejs/adapter-node Patch
@sveltejs/adapter-vercel Patch
@sveltejs/adapter-cloudflare-workers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the changes in pnpm-lock.yaml should be removed in this PR.

@noahsalvi
Copy link
Author

done.

@benmccann benmccann added the bug Something isn't working label Aug 11, 2021
@benmccann benmccann changed the title remove url parsing in server.js [fix] remove url parsing from adapter-node Aug 11, 2021
@benmccann
Copy link
Member

benmccann commented Aug 11, 2021

It looks like this is handled inconsistently today. adapter-vercel, adapter-cloudflare-workers would also need to be updated as they're currently decoding the path. (adapter-netlify and architect/sveltekit-adapter do not while it's not relevant for adapter-static)

CC @pluvial for svelte-adapter-deno and @jthegedus for svelte-adapter-firebase which also parse the URL today

We should also figure out how this interacts with handle. I think we are returning the decoded version there today and perhaps we should not be to be consistent with the change you are making here. Express does not decode the path so returning the un-decoded path would make it more consistent and easier to interact with existing middlewares expressjs/expressjs.com#1281.

I think we should not decode the path in the adapters for the reasons mentioned at expressjs/expressjs.com#1281 (comment). And clearly we don't want to do it twice as we are now. Plus it would be more consistent with Express. Most important is probably that we do it consistently and test and document the expectations.

@benmccann
Copy link
Member

@noahsalvi would you be able to update adapter-vercel and adapter-cloudflare-workers as you have here?

@noahsalvi
Copy link
Author

@noahsalvi would you be able to update adapter-vercel and adapter-cloudflare-workers as you have here?

Sure 👍

@noahsalvi
Copy link
Author

btw i thought that the node adapter is using polka. Shouldn't that be the place to look? Or does it not matter due to express and polka sharing the same api?
@benmccann

@benmccann
Copy link
Member

Yeah, I just mentioned Express because it is more popular. But I just tested and confirmed that Polka works the same as Express in this manner

@benmccann benmccann changed the title [fix] remove url parsing from adapter-node [fix] decode path only once to fix loading unicode routes Aug 11, 2021
// fall back to an app route
const request = event.request;
const request_url = new URL(request.url);
const parsedURL = new URL(request.url);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CFW request doesn't expose the usual props. That's why I did it differently for this adapter. Doc

path: parsed.pathname,
query: parsed.searchParams,
rawBody: body
path: req.path,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me that this PR is actually changing anything

I just created an index.js with the source code:
console.log(new URL('http://localhost/über-uns').pathname)

It printed:

/%C3%BCber-uns

If I change the code to console.log(new URL('http://localhost/%C3%BCber-uns').pathname) it still prints the same thing

So it's actually not clear to me that this PR is changing anything. Am I missing something? Or can you explain what was happening before vs what's happening now?

Copy link
Author

@noahsalvi noahsalvi Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well at the moment the render function is receiving, as the path value, the encoded string /%C3%BCber-uns.

And now after changing it to take the original path from the req object without transforming and encoding it with URL class, the value that it receives is /über-uns

I think that the thing you're missing is, that my change for the adapter node, does not wrap the path in a url object, that encodes the string.

Edit:
To observe this, you can clone my repro and modify the server.js file in node_modules to print out req.path and parsed.pathname

@benmccann
Copy link
Member

Gahhh!!! This is Polka. I tested with @latest but it changed behavior in @next. I sent #2171 as a better fix. I think this should only fix adapter-node after all. It was a bit of a round-about path to figuring out what was going on. Thanks for the hlpe with this one

@benmccann benmccann closed this Aug 11, 2021
@noahsalvi
Copy link
Author

are you sure that your fix works?
Maybe we aren't talking about the same problem, because I tried your fix and it did not work for my repro project.

Just to clarify, routes with unicode characters work on my computer only when the render function gets a none URI encoded path. Using the polka parser or the URL class to get pathname leads to it not working.

await render({
	method: req.method,
	headers: req.headers, // TODO: what about repeated headers, i.e. string[]
	path: '/über-uns' works but '/%C3%BCber-uns' doesn't,
	query: parsed.searchParams,
	rawBody: body
});

@benmccann
Copy link
Member

Thanks for testing @noahsalvi. I updated the PR and added a new test for adapter-node. Can you test again?

@noahsalvi
Copy link
Author

noahsalvi commented Aug 12, 2021

Thanks for testing @noahsalvi. I updated the PR and added a new test for adapter-node. Can you test again?

I just tested it and the test you wrote works, but it does not test the problem that i'm facing. I also tried linking the package to my repro repo and it did not change the outcome.

test('route with umlaut returns page', async () => {
	const server = await startServer({
		render: (incoming) => {
			if (incoming.path === '/über-uns') {
				return {
					status: 200,
					body: incoming.path
				};
			}
		}
	});
	const res = await fetch(`http://localhost:${PORT}/über-uns`);
	assert.ok(res.ok);
	server.server.close();
});

^ This would be testing this problem.

(Edit: I've added the test to this branch)

@benmccann
Copy link
Member

I just tried linking my PR against your repo and it did work

You unit test isn't correct. The browser will send an encoded path so you can't check the encoded incoming.path against a decoded path. But the router will decode the path when looking for a matching rout and will find the correct path and so I don't get a 404 when running against the full server

@noahsalvi
Copy link
Author

hmmm weird....

image

Just to confirm, what was the result you got from running my test?

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

Successfully merging this pull request may close these issues.

Routes with umlauts are not found in node builds
3 participants