Skip to content

Commit

Permalink
[fix] handle paths consistently between dev and various production ad…
Browse files Browse the repository at this point in the history
…apters
  • Loading branch information
benmccann committed Aug 11, 2021
1 parent c3ca3fb commit 35836a0
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 11 deletions.
6 changes: 6 additions & 0 deletions .changeset/brave-seas-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@sveltejs/adapter-node': patch
'@sveltejs/kit': patch
---

[fix] handle paths consistently between dev and various production adapters
1 change: 1 addition & 0 deletions packages/adapter-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"tiny-glob": "^0.2.9"
},
"devDependencies": {
"@polka/url": "^1.0.0-next.15",
"@rollup/plugin-json": "^4.1.0",
"@sveltejs/kit": "workspace:*",
"c8": "^7.7.2",
Expand Down
10 changes: 9 additions & 1 deletion packages/adapter-node/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import compression from 'compression';
import fs from 'fs';
import { dirname, join } from 'path';
import polka from 'polka';
import { parse } from '@polka/url';
import sirv from 'sirv';
import { fileURLToPath } from 'url';

Expand Down Expand Up @@ -38,7 +39,14 @@ export function createServer({ render }) {
})
: noop_handler;

const server = polka().use(
const server = polka();
// Polka has a non-standard behavior of decoding the request path
// Disable it so that adapter-node works just like the rest
// SvelteKit will handle decoding URI components into req.params
server.parse = (req) => {
return parse(req, false);
};
server.use(
compression({ threshold: 0 }),
assets_handler,
prerendered_handler,
Expand Down
14 changes: 14 additions & 0 deletions packages/adapter-node/tests/smoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,18 @@ test('responses with the rendered status code', async () => {
server.server.close();
});

test('passes through umlaut as encoded path', async () => {
const server = await startServer({
render: (incoming) => {
return {
status: 200,
body: incoming.path
};
}
});
const res = await fetch(`http://localhost:${PORT}/%C3%BCber-uns`);
assert.equal(await res.text(), '/%C3%BCber-uns');
server.server.close();
});

test.run();
2 changes: 1 addition & 1 deletion packages/kit/src/core/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ async function create_handler(vite, config, dir, cwd, manifest) {
headers: /** @type {import('types/helper').Headers} */ (req.headers),
method: req.method,
host,
path: decodeURI(parsed.pathname),
path: parsed.pathname,
query: parsed.searchParams,
rawBody: body
},
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/core/preview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export async function preview({
req.headers[config.kit.hostHeader || 'host']),
method: req.method,
headers: /** @type {import('types/helper').Headers} */ (req.headers),
path: parsed.pathname ? decodeURIComponent(parsed.pathname) : '',
path: parsed.pathname ? parsed.pathname : '',
query: new URLSearchParams(parsed.query || ''),
rawBody: body
});
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/src/runtime/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function respond(incoming, options, state = {}) {
return {
status: 301,
headers: {
location: encodeURI(path + (q ? `?${q}` : ''))
location: path + (q ? `?${q}` : '')
}
};
}
Expand Down Expand Up @@ -57,7 +57,7 @@ export async function respond(incoming, options, state = {}) {
}

for (const route of options.manifest.routes) {
if (!route.pattern.test(request.path)) continue;
if (!route.pattern.test(decodeURI(request.path))) continue;

const response =
route.type === 'endpoint'
Expand Down
12 changes: 6 additions & 6 deletions packages/kit/test/apps/basics/src/routes/encoded/_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ export default function (test) {
test('visits a route with non-ASCII character', '/encoded', async ({ page, clicknav }) => {
await clicknav('[href="/encoded/苗条"]');
assert.equal(await page.innerHTML('h1'), 'static');
assert.equal(await page.innerHTML('h2'), '/encoded/苗条');
assert.equal(await page.innerHTML('h3'), '/encoded/苗条');
assert.equal(decodeURI(await page.innerHTML('h2')), '/encoded/苗条');
assert.equal(decodeURI(await page.innerHTML('h3')), '/encoded/苗条');
});

test(
Expand All @@ -15,17 +15,17 @@ export default function (test) {
async ({ page, clicknav }) => {
await clicknav('[href="/encoded/土豆"]');
assert.equal(await page.innerHTML('h1'), 'dynamic');
assert.equal(await page.innerHTML('h2'), '/encoded/土豆: 土豆');
assert.equal(await page.innerHTML('h3'), '/encoded/土豆: 土豆');
assert.equal(decodeURI(await page.innerHTML('h2')), '/encoded/土豆: 土豆');
assert.equal(decodeURI(await page.innerHTML('h3')), '/encoded/土豆: 土豆');
}
);

test('redirects correctly with non-ASCII location', '/encoded', async ({ page, clicknav }) => {
await clicknav('[href="/encoded/反应"]');

assert.equal(await page.innerHTML('h1'), 'static');
assert.equal(await page.innerHTML('h2'), '/encoded/苗条');
assert.equal(await page.innerHTML('h3'), '/encoded/苗条');
assert.equal(decodeURI(await page.innerHTML('h2')), '/encoded/苗条');
assert.equal(decodeURI(await page.innerHTML('h3')), '/encoded/苗条');
});

test('sets charset on JSON Content-Type', null, async ({ fetch }) => {
Expand Down
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 35836a0

Please sign in to comment.