change: Query string does not influence identifier.

This commit is contained in:
Ruben Verborgh 2021-01-28 22:36:26 +01:00 committed by Joachim Van Herwegen
parent 6e50443a39
commit a57105be8e
6 changed files with 42 additions and 6 deletions

View File

@ -27,7 +27,8 @@
},
{
"@id": "urn:solid-server:default:TargetExtractor",
"@type": "OriginalUrlExtractor"
"@type": "OriginalUrlExtractor",
"OriginalUrlExtractor:_options_includeQueryString": false
}
]
}

View File

@ -9,6 +9,13 @@ import { TargetExtractor } from './TargetExtractor';
* Reconstructs the original URL of an incoming {@link HttpRequest}.
*/
export class OriginalUrlExtractor extends TargetExtractor {
private readonly includeQueryString: boolean;
public constructor(options: { includeQueryString?: boolean } = {}) {
super();
this.includeQueryString = options.includeQueryString ?? true;
}
public async handle({ request: { url, connection, headers }}: { request: HttpRequest }): Promise<ResourceIdentifier> {
if (!url) {
throw new Error('Missing URL');
@ -37,7 +44,13 @@ export class OriginalUrlExtractor extends TargetExtractor {
// URL object applies punycode encoding to domain
const base = `${protocol}://${host}`;
const path = new URL(toCanonicalUriPath(url), base).href;
return { path };
const originalUrl = new URL(toCanonicalUriPath(url), base);
// Drop the query string if requested
if (!this.includeQueryString) {
originalUrl.search = '';
}
return { path: originalUrl.href };
}
}

View File

@ -69,6 +69,18 @@ describe.each(stores)('An LDP handler without auth using %s', (name, { storeUrn,
expect(response.getHeaders().link).toContain(`<${BASE}/.acl>; rel="acl"`);
});
it('can read a folder listing with a query string.', async():
Promise<void> => {
const response = await resourceHelper.getResource(`${BASE}/?abc=def&xyz`);
expect(response.statusCode).toBe(200);
expect(response.getHeaders()).toHaveProperty('content-type', 'text/turtle');
const data = response._getData().toString();
expect(data).toContain(`<> a ldp:Container`);
expect(response.getHeaders().link).toContain(`<${LDP.Container}>; rel="type"`);
expect(response.getHeaders().link).toContain(`<${BASE}/.acl>; rel="acl"`);
});
it('can add a file to the store, read it and delete it.', async():
Promise<void> => {
// POST

View File

@ -26,6 +26,17 @@ describe('A OriginalUrlExtractor', (): void => {
.resolves.toEqual({ path: 'http://test.com/url' });
});
it('returns an input URL with query string.', async(): Promise<void> => {
const noQuery = new OriginalUrlExtractor({ includeQueryString: false });
await expect(noQuery.handle({ request: { url: '/url?abc=def&xyz', headers: { host: 'test.com' }} as any }))
.resolves.toEqual({ path: 'http://test.com/url' });
});
it('drops the query string when includeQueryString is set to false.', async(): Promise<void> => {
await expect(extractor.handle({ request: { url: '/url?abc=def&xyz', headers: { host: 'test.com' }} as any }))
.resolves.toEqual({ path: 'http://test.com/url?abc=def&xyz' });
});
it('supports host:port combinations.', async(): Promise<void> => {
await expect(extractor.handle({ request: { url: 'url', headers: { host: 'localhost:3000' }} as any }))
.resolves.toEqual({ path: 'http://localhost:3000/url' });

View File

@ -73,8 +73,7 @@ export class ResourceHelper {
data: Buffer,
): Promise<MockResponse<any>> {
const request = Readable.from([ data ]) as HttpRequest;
request.url = requestUrl.pathname;
request.url = `${requestUrl.pathname}${requestUrl.search}`;
request.method = method;
request.headers = headers;
request.headers.host = requestUrl.host;

View File

@ -17,7 +17,7 @@ export async function performRequest(
data: string[],
): Promise<MockResponse<any>> {
const request = streamifyArray(data) as HttpRequest;
request.url = requestUrl.pathname;
request.url = `${requestUrl.pathname}${requestUrl.search}`;
request.method = method;
request.headers = headers;
request.headers.host = requestUrl.host;