add leading and trailing slash sanitization for params (#8276)
* add leading and trailing slash sanitization for params * chore: fix lint * refactor: use shared trimSlashes util --------- Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com> Co-authored-by: Nate Moore <nate@astro.build>
This commit is contained in:
parent
84427f33c1
commit
d3a6f9f836
3 changed files with 75 additions and 1 deletions
5
.changeset/chilled-hornets-press.md
Normal file
5
.changeset/chilled-hornets-press.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Sanitize route params for leading and trailing slashes
|
|
@ -1,5 +1,6 @@
|
||||||
import type { GetStaticPathsItem, Params, RouteData } from '../../@types/astro';
|
import type { GetStaticPathsItem, Params, RouteData } from '../../@types/astro';
|
||||||
import { validateGetStaticPathsParameter } from './validation.js';
|
import { validateGetStaticPathsParameter } from './validation.js';
|
||||||
|
import { trimSlashes } from '../path.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* given an array of params like `['x', 'y', 'z']` for
|
* given an array of params like `['x', 'y', 'z']` for
|
||||||
|
@ -32,7 +33,9 @@ export function stringifyParams(params: GetStaticPathsItem['params'], route: Rou
|
||||||
const validatedParams = Object.entries(params).reduce((acc, next) => {
|
const validatedParams = Object.entries(params).reduce((acc, next) => {
|
||||||
validateGetStaticPathsParameter(next, route.component);
|
validateGetStaticPathsParameter(next, route.component);
|
||||||
const [key, value] = next;
|
const [key, value] = next;
|
||||||
acc[key] = value?.toString();
|
if (value !== undefined) {
|
||||||
|
acc[key] = typeof value === 'string' ? trimSlashes(value) : value.toString()
|
||||||
|
}
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as Params);
|
}, {} as Params);
|
||||||
|
|
||||||
|
|
66
packages/astro/test/units/routing/route-sanitization.test.js
Normal file
66
packages/astro/test/units/routing/route-sanitization.test.js
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import {
|
||||||
|
createBasicSettings,
|
||||||
|
createFs,
|
||||||
|
createRequestAndResponse,
|
||||||
|
defaultLogger,
|
||||||
|
} from '../test-utils.js';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import { createContainer } from '../../../dist/core/dev/container.js';
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
import testAdapter from '../../test-adapter.js';
|
||||||
|
|
||||||
|
const root = new URL('../../fixtures/alias/', import.meta.url);
|
||||||
|
const fileSystem = {
|
||||||
|
'/src/pages/[...testSlashTrim].astro': `
|
||||||
|
---
|
||||||
|
export function getStaticPaths() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
testSlashTrim: "/a-route-param-with-leading-trailing-slash/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
---
|
||||||
|
<p>Success!</p>
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Route sanitization', () => {
|
||||||
|
let container;
|
||||||
|
let settings;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
const fs = createFs(fileSystem, root);
|
||||||
|
settings = await createBasicSettings({
|
||||||
|
root: fileURLToPath(root),
|
||||||
|
trailingSlash: 'never',
|
||||||
|
output: 'hybrid',
|
||||||
|
adapter: testAdapter(),
|
||||||
|
});
|
||||||
|
container = await createContainer({
|
||||||
|
fs,
|
||||||
|
settings,
|
||||||
|
logger: defaultLogger,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await container.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Request', () => {
|
||||||
|
it('should correctly match a route param with a trailing slash', async () => {
|
||||||
|
const { req, res, text } = createRequestAndResponse({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/a-route-param-with-leading-trailing-slash',
|
||||||
|
});
|
||||||
|
container.handle(req, res);
|
||||||
|
const html = await text();
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
expect($('p').text()).to.equal('Success!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue