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:
Fred K. Schott 2023-08-31 11:05:39 -07:00 committed by GitHub
parent 84427f33c1
commit d3a6f9f836
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Sanitize route params for leading and trailing slashes

View file

@ -1,5 +1,6 @@
import type { GetStaticPathsItem, Params, RouteData } from '../../@types/astro';
import { validateGetStaticPathsParameter } from './validation.js';
import { trimSlashes } from '../path.js';
/**
* 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) => {
validateGetStaticPathsParameter(next, route.component);
const [key, value] = next;
acc[key] = value?.toString();
if (value !== undefined) {
acc[key] = typeof value === 'string' ? trimSlashes(value) : value.toString()
}
return acc;
}, {} as Params);

View 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!');
});
});
});