mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
refactor: Make request related handle calls consistent
This commit is contained in:
parent
995a2dc74d
commit
f17054c647
@ -34,7 +34,7 @@ export class DPoPWebIdExtractor extends CredentialsExtractor {
|
||||
if (!dpop) {
|
||||
throw new BadRequestHttpError('No DPoP header specified.');
|
||||
}
|
||||
const resource = await this.targetExtractor.handleSafe(request);
|
||||
const resource = await this.targetExtractor.handleSafe({ request });
|
||||
|
||||
try {
|
||||
const { webid: webId } = await this.verify(
|
||||
|
@ -27,7 +27,7 @@ const parsers: {
|
||||
* Supports Accept, Accept-Charset, Accept-Encoding, Accept-Language and Accept-DateTime.
|
||||
*/
|
||||
export class AcceptPreferenceParser extends PreferenceParser {
|
||||
public async handle({ headers }: HttpRequest): Promise<RepresentationPreferences> {
|
||||
public async handle({ request: { headers }}: { request: HttpRequest }): Promise<RepresentationPreferences> {
|
||||
const preferences: RepresentationPreferences = {};
|
||||
for (const { name, header, parse } of parsers) {
|
||||
const value = headers[header];
|
||||
|
@ -36,9 +36,9 @@ export class BasicRequestParser extends RequestParser {
|
||||
if (!method) {
|
||||
throw new Error('No method specified on the HTTP request');
|
||||
}
|
||||
const target = await this.targetExtractor.handleSafe(request);
|
||||
const preferences = await this.preferenceParser.handleSafe(request);
|
||||
const metadata = await this.metadataExtractor.handleSafe(request);
|
||||
const target = await this.targetExtractor.handleSafe({ request });
|
||||
const preferences = await this.preferenceParser.handleSafe({ request });
|
||||
const metadata = await this.metadataExtractor.handleSafe({ request });
|
||||
const body = await this.bodyParser.handleSafe({ request, metadata });
|
||||
|
||||
return { method, target, preferences, body };
|
||||
|
@ -11,7 +11,7 @@ import { TargetExtractor } from './TargetExtractor';
|
||||
* TODO: input requires more extensive cleaning/parsing based on headers (see #22).
|
||||
*/
|
||||
export class BasicTargetExtractor extends TargetExtractor {
|
||||
public async handle({ url, connection, headers }: HttpRequest): Promise<ResourceIdentifier> {
|
||||
public async handle({ request: { url, connection, headers }}: { request: HttpRequest }): Promise<ResourceIdentifier> {
|
||||
if (!url) {
|
||||
throw new Error('Missing URL');
|
||||
}
|
||||
|
@ -5,4 +5,4 @@ import type { RepresentationPreferences } from '../representation/Representation
|
||||
/**
|
||||
* Creates {@link RepresentationPreferences} based on the incoming HTTP headers in a {@link HttpRequest}.
|
||||
*/
|
||||
export abstract class PreferenceParser extends AsyncHandler<HttpRequest, RepresentationPreferences> {}
|
||||
export abstract class PreferenceParser extends AsyncHandler<{ request: HttpRequest }, RepresentationPreferences> {}
|
||||
|
@ -5,4 +5,4 @@ import type { ResourceIdentifier } from '../representation/ResourceIdentifier';
|
||||
/**
|
||||
* Extracts a {@link ResourceIdentifier} from an incoming {@link HttpRequest}.
|
||||
*/
|
||||
export abstract class TargetExtractor extends AsyncHandler<HttpRequest, ResourceIdentifier> {}
|
||||
export abstract class TargetExtractor extends AsyncHandler<{ request: HttpRequest }, ResourceIdentifier> {}
|
||||
|
@ -14,7 +14,7 @@ export class BasicMetadataExtractor extends MetadataExtractor {
|
||||
this.parsers = parsers;
|
||||
}
|
||||
|
||||
public async handle(request: HttpRequest):
|
||||
public async handle({ request }: { request: HttpRequest }):
|
||||
Promise<RepresentationMetadata> {
|
||||
const metadata = new RepresentationMetadata();
|
||||
for (const parser of this.parsers) {
|
||||
|
@ -6,4 +6,4 @@ import type { RepresentationMetadata } from '../../representation/Representation
|
||||
* Parses the metadata of a {@link HttpRequest} into a {@link RepresentationMetadata}.
|
||||
*/
|
||||
export abstract class MetadataExtractor extends
|
||||
AsyncHandler<HttpRequest, RepresentationMetadata> {}
|
||||
AsyncHandler<{ request: HttpRequest }, RepresentationMetadata> {}
|
||||
|
@ -74,7 +74,7 @@ describe('A DPoPWebIdExtractor', (): void => {
|
||||
it('calls the target extractor with the correct parameters.', async(): Promise<void> => {
|
||||
await webIdExtractor.handleSafe(request);
|
||||
expect(targetExtractor.handle).toHaveBeenCalledTimes(1);
|
||||
expect(targetExtractor.handle).toHaveBeenCalledWith(request);
|
||||
expect(targetExtractor.handle).toHaveBeenCalledWith({ request });
|
||||
});
|
||||
|
||||
it('calls the DPoP verifier with the correct parameters.', async(): Promise<void> => {
|
||||
|
@ -3,41 +3,47 @@ import type { HttpRequest } from '../../../../src/server/HttpRequest';
|
||||
|
||||
describe('An AcceptPreferenceParser', (): void => {
|
||||
const preferenceParser = new AcceptPreferenceParser();
|
||||
let request: HttpRequest;
|
||||
beforeEach(async(): Promise<void> => {
|
||||
request = { headers: {}} as HttpRequest;
|
||||
});
|
||||
|
||||
it('can handle all input.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.canHandle({} as HttpRequest)).resolves.toBeUndefined();
|
||||
await expect(preferenceParser.canHandle({ request })).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns an empty result if there is no relevant input.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle({ headers: {}} as HttpRequest)).resolves.toEqual({});
|
||||
await expect(preferenceParser.handle({ request })).resolves.toEqual({});
|
||||
});
|
||||
|
||||
it('parses accept headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle({ headers: { accept: 'audio/*; q=0.2, audio/basic' }} as HttpRequest))
|
||||
request.headers = { accept: 'audio/*; q=0.2, audio/basic' };
|
||||
await expect(preferenceParser.handle({ request }))
|
||||
.resolves.toEqual({ type: { 'audio/basic': 1, 'audio/*': 0.2 }});
|
||||
});
|
||||
|
||||
it('parses accept-charset headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle(
|
||||
{ headers: { 'accept-charset': 'iso-8859-5, unicode-1-1;q=0.8' }} as unknown as HttpRequest,
|
||||
)).resolves.toEqual({ charset: { 'iso-8859-5': 1, 'unicode-1-1': 0.8 }});
|
||||
request.headers = { 'accept-charset': 'iso-8859-5, unicode-1-1;q=0.8' };
|
||||
await expect(preferenceParser.handle({ request }))
|
||||
.resolves.toEqual({ charset: { 'iso-8859-5': 1, 'unicode-1-1': 0.8 }});
|
||||
});
|
||||
|
||||
it('parses accept-datetime headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle(
|
||||
{ headers: { 'accept-datetime': 'Tue, 20 Mar 2001 20:35:00 GMT' }} as unknown as HttpRequest,
|
||||
request.headers = { 'accept-datetime': 'Tue, 20 Mar 2001 20:35:00 GMT' };
|
||||
await expect(preferenceParser.handle({ request }))
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
)).resolves.toEqual({ datetime: { 'Tue, 20 Mar 2001 20:35:00 GMT': 1 }});
|
||||
.resolves.toEqual({ datetime: { 'Tue, 20 Mar 2001 20:35:00 GMT': 1 }});
|
||||
});
|
||||
|
||||
it('parses accept-encoding headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle(
|
||||
{ headers: { 'accept-encoding': 'gzip;q=1.0, identity; q=0.5, *;q=0' }} as unknown as HttpRequest,
|
||||
)).resolves.toEqual({ encoding: { gzip: 1, identity: 0.5, '*': 0 }});
|
||||
request.headers = { 'accept-encoding': 'gzip;q=1.0, identity; q=0.5, *;q=0' };
|
||||
await expect(preferenceParser.handle({ request }))
|
||||
.resolves.toEqual({ encoding: { gzip: 1, identity: 0.5, '*': 0 }});
|
||||
});
|
||||
|
||||
it('parses accept-language headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle({ headers: { 'accept-language': 'da, en-gb;q=0.8, en;q=0.7' }} as HttpRequest))
|
||||
request.headers = { 'accept-language': 'da, en-gb;q=0.8, en;q=0.7' };
|
||||
await expect(preferenceParser.handle({ request }))
|
||||
.resolves.toEqual({ language: { da: 1, 'en-gb': 0.8, en: 0.7 }});
|
||||
});
|
||||
});
|
||||
|
@ -8,47 +8,48 @@ describe('A BasicTargetExtractor', (): void => {
|
||||
});
|
||||
|
||||
it('errors if there is no URL.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ headers: { host: 'test.com' }} as any)).rejects.toThrow('Missing URL');
|
||||
await expect(extractor.handle({ request: { headers: { host: 'test.com' }} as any })).rejects.toThrow('Missing URL');
|
||||
});
|
||||
|
||||
it('errors if there is no host.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ url: 'url', headers: {}} as any)).rejects.toThrow('Missing Host header');
|
||||
await expect(extractor.handle({ request: { url: 'url', headers: {}} as any }))
|
||||
.rejects.toThrow('Missing Host header');
|
||||
});
|
||||
|
||||
it('errors if the host is invalid.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ url: 'url', headers: { host: 'test.com/forbidden' }} as any))
|
||||
await expect(extractor.handle({ request: { url: 'url', headers: { host: 'test.com/forbidden' }} as any }))
|
||||
.rejects.toThrow('The request has an invalid Host header: test.com/forbidden');
|
||||
});
|
||||
|
||||
it('returns the input URL.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ url: 'url', headers: { host: 'test.com' }} as any))
|
||||
await expect(extractor.handle({ request: { url: 'url', headers: { host: 'test.com' }} as any }))
|
||||
.resolves.toEqual({ path: 'http://test.com/url' });
|
||||
});
|
||||
|
||||
it('supports host:port combinations.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ url: 'url', headers: { host: 'localhost:3000' }} as any))
|
||||
await expect(extractor.handle({ request: { url: 'url', headers: { host: 'localhost:3000' }} as any }))
|
||||
.resolves.toEqual({ path: 'http://localhost:3000/url' });
|
||||
});
|
||||
|
||||
it('uses https protocol if the connection is secure.', async(): Promise<void> => {
|
||||
await expect(extractor.handle(
|
||||
{ url: 'url', headers: { host: 'test.com' }, connection: { encrypted: true } as any } as any,
|
||||
{ request: { url: 'url', headers: { host: 'test.com' }, connection: { encrypted: true } as any } as any },
|
||||
)).resolves.toEqual({ path: 'https://test.com/url' });
|
||||
});
|
||||
|
||||
it('encodes paths.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ url: '/a%20path%26/name', headers: { host: 'test.com' }} as any))
|
||||
await expect(extractor.handle({ request: { url: '/a%20path%26/name', headers: { host: 'test.com' }} as any }))
|
||||
.resolves.toEqual({ path: 'http://test.com/a%20path%26/name' });
|
||||
|
||||
await expect(extractor.handle({ url: '/a path%26/name', headers: { host: 'test.com' }} as any))
|
||||
await expect(extractor.handle({ request: { url: '/a path%26/name', headers: { host: 'test.com' }} as any }))
|
||||
.resolves.toEqual({ path: 'http://test.com/a%20path%26/name' });
|
||||
|
||||
await expect(extractor.handle({ url: '/path&%26/name', headers: { host: 'test.com' }} as any))
|
||||
await expect(extractor.handle({ request: { url: '/path&%26/name', headers: { host: 'test.com' }} as any }))
|
||||
.resolves.toEqual({ path: 'http://test.com/path%26%26/name' });
|
||||
});
|
||||
|
||||
it('encodes hosts.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ url: '/', headers: { host: '點看' }} as any))
|
||||
await expect(extractor.handle({ request: { url: '/', headers: { host: '點看' }} as any }))
|
||||
.resolves.toEqual({ path: 'http://xn--c1yn36f/' });
|
||||
});
|
||||
|
||||
@ -57,7 +58,7 @@ describe('A BasicTargetExtractor', (): void => {
|
||||
host: 'test.com',
|
||||
forwarded: 'by=203.0.113.60',
|
||||
};
|
||||
await expect(extractor.handle({ url: '/foo/bar', headers } as any))
|
||||
await expect(extractor.handle({ request: { url: '/foo/bar', headers } as any }))
|
||||
.resolves.toEqual({ path: 'http://test.com/foo/bar' });
|
||||
});
|
||||
|
||||
@ -66,7 +67,7 @@ describe('A BasicTargetExtractor', (): void => {
|
||||
host: 'test.com',
|
||||
forwarded: 'proto=https;host=pod.example',
|
||||
};
|
||||
await expect(extractor.handle({ url: '/foo/bar', headers } as any))
|
||||
await expect(extractor.handle({ request: { url: '/foo/bar', headers } as any }))
|
||||
.resolves.toEqual({ path: 'https://pod.example/foo/bar' });
|
||||
});
|
||||
});
|
||||
|
@ -32,7 +32,7 @@ describe('A BasicMetadataExtractor', (): void => {
|
||||
});
|
||||
|
||||
it('will add metadata from the parsers.', async(): Promise<void> => {
|
||||
const metadata = await handler.handle({ headers: { aa: 'valA', bb: 'valB' } as any } as HttpRequest);
|
||||
const metadata = await handler.handle({ request: { headers: { aa: 'valA', bb: 'valB' } as any } as HttpRequest });
|
||||
expect(metadata.getAll(RDF.type).map((term): any => term.value)).toEqual([ 'valA', 'valB' ]);
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user