mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Create MetadataHandler
This commit is contained in:
38
test/unit/ldp/http/metadata/BasicMetadataExtractor.test.ts
Normal file
38
test/unit/ldp/http/metadata/BasicMetadataExtractor.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { BasicMetadataExtractor } from '../../../../../src/ldp/http/metadata/BasicMetadataExtractor';
|
||||
import type { MetadataParser } from '../../../../../src/ldp/http/metadata/MetadataParser';
|
||||
import type { RepresentationMetadata } from '../../../../../src/ldp/representation/RepresentationMetadata';
|
||||
import type { HttpRequest } from '../../../../../src/server/HttpRequest';
|
||||
import { RDF } from '../../../../../src/util/UriConstants';
|
||||
|
||||
class BasicParser implements MetadataParser {
|
||||
private readonly header: string;
|
||||
|
||||
public constructor(header: string) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public async parse(input: HttpRequest, metadata: RepresentationMetadata): Promise<void> {
|
||||
const header = input.headers[this.header];
|
||||
if (header) {
|
||||
if (typeof header === 'string') {
|
||||
metadata.add(RDF.type, header);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe(' A BasicMetadataExtractor', (): void => {
|
||||
const handler = new BasicMetadataExtractor([
|
||||
new BasicParser('aa'),
|
||||
new BasicParser('bb'),
|
||||
]);
|
||||
|
||||
it('can handle all requests.', async(): Promise<void> => {
|
||||
await expect(handler.canHandle()).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('will add metadata from the parsers.', async(): Promise<void> => {
|
||||
const metadata = await handler.handle({ headers: { aa: 'valA', bb: 'valB' } as any } as HttpRequest);
|
||||
expect(metadata.getAll(RDF.type).map((term): any => term.value)).toEqual([ 'valA', 'valB' ]);
|
||||
});
|
||||
});
|
||||
26
test/unit/ldp/http/metadata/ContentTypeParser.test.ts
Normal file
26
test/unit/ldp/http/metadata/ContentTypeParser.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { ContentTypeParser } from '../../../../../src/ldp/http/metadata/ContentTypeParser';
|
||||
import { RepresentationMetadata } from '../../../../../src/ldp/representation/RepresentationMetadata';
|
||||
import type { HttpRequest } from '../../../../../src/server/HttpRequest';
|
||||
|
||||
describe('A ContentTypeParser', (): void => {
|
||||
const parser = new ContentTypeParser();
|
||||
let request: HttpRequest;
|
||||
let metadata: RepresentationMetadata;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
request = { headers: {}} as HttpRequest;
|
||||
metadata = new RepresentationMetadata();
|
||||
});
|
||||
|
||||
it('does nothing if there is no content-type header.', async(): Promise<void> => {
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('sets the given content-type as metadata.', async(): Promise<void> => {
|
||||
request.headers['content-type'] = 'text/plain;charset=UTF-8';
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(1);
|
||||
expect(metadata.contentType).toBe('text/plain');
|
||||
});
|
||||
});
|
||||
61
test/unit/ldp/http/metadata/LinkTypeParser.test.ts
Normal file
61
test/unit/ldp/http/metadata/LinkTypeParser.test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { LinkTypeParser } from '../../../../../src/ldp/http/metadata/LinkTypeParser';
|
||||
import { RepresentationMetadata } from '../../../../../src/ldp/representation/RepresentationMetadata';
|
||||
import { setGlobalLoggerFactory } from '../../../../../src/logging/LogUtil';
|
||||
import { VoidLoggerFactory } from '../../../../../src/logging/VoidLoggerFactory';
|
||||
import type { HttpRequest } from '../../../../../src/server/HttpRequest';
|
||||
import { RDF } from '../../../../../src/util/UriConstants';
|
||||
|
||||
describe('A LinkTypeParser', (): void => {
|
||||
const parser = new LinkTypeParser();
|
||||
let request: HttpRequest;
|
||||
let metadata: RepresentationMetadata;
|
||||
|
||||
beforeAll(async(): Promise<void> => {
|
||||
setGlobalLoggerFactory(new VoidLoggerFactory());
|
||||
});
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
request = { headers: {}} as HttpRequest;
|
||||
metadata = new RepresentationMetadata();
|
||||
});
|
||||
|
||||
it('does nothing if there are no type headers.', async(): Promise<void> => {
|
||||
await parser.parse(request, metadata);
|
||||
expect(metadata.quads()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('stores link headers with rel = type as metadata.', async(): Promise<void> => {
|
||||
request.headers.link = '<http://test.com/type>;rel="type"';
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(1);
|
||||
expect(metadata.get(RDF.type)?.value).toBe('http://test.com/type');
|
||||
});
|
||||
|
||||
it('supports multiple link headers.', async(): Promise<void> => {
|
||||
request.headers.link = [ '<http://test.com/typeA>;rel="type"', '<http://test.com/typeB>;rel=type' ];
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(2);
|
||||
expect(metadata.getAll(RDF.type).map((term): any => term.value))
|
||||
.toEqual([ 'http://test.com/typeA', 'http://test.com/typeB' ]);
|
||||
});
|
||||
|
||||
it('supports multiple link header values in the same entry.', async(): Promise<void> => {
|
||||
request.headers.link = '<http://test.com/typeA>;rel="type" , <http://test.com/typeB>;rel=type';
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(2);
|
||||
expect(metadata.getAll(RDF.type).map((term): any => term.value))
|
||||
.toEqual([ 'http://test.com/typeA', 'http://test.com/typeB' ]);
|
||||
});
|
||||
|
||||
it('ignores invalid link headers.', async(): Promise<void> => {
|
||||
request.headers.link = 'http://test.com/type;rel="type"';
|
||||
await parser.parse(request, metadata);
|
||||
expect(metadata.quads()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('ignores non-type link headers.', async(): Promise<void> => {
|
||||
request.headers.link = '<http://test.com/typeA>;rel="notype" , <http://test.com/typeB>';
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
34
test/unit/ldp/http/metadata/SlugParser.test.ts
Normal file
34
test/unit/ldp/http/metadata/SlugParser.test.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { SlugParser } from '../../../../../src/ldp/http/metadata/SlugParser';
|
||||
import { RepresentationMetadata } from '../../../../../src/ldp/representation/RepresentationMetadata';
|
||||
import type { HttpRequest } from '../../../../../src/server/HttpRequest';
|
||||
import { UnsupportedHttpError } from '../../../../../src/util/errors/UnsupportedHttpError';
|
||||
import { HTTP } from '../../../../../src/util/UriConstants';
|
||||
|
||||
describe('A SlugParser', (): void => {
|
||||
const parser = new SlugParser();
|
||||
let request: HttpRequest;
|
||||
let metadata: RepresentationMetadata;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
request = { headers: {}} as HttpRequest;
|
||||
metadata = new RepresentationMetadata();
|
||||
});
|
||||
|
||||
it('does nothing if there is no slug header.', async(): Promise<void> => {
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('errors if there are multiple slug headers.', async(): Promise<void> => {
|
||||
request.headers.slug = [ 'slugA', 'slugB' ];
|
||||
await expect(parser.parse(request, metadata))
|
||||
.rejects.toThrow(new UnsupportedHttpError('At most 1 slug header is allowed.'));
|
||||
});
|
||||
|
||||
it('stores the slug metadata.', async(): Promise<void> => {
|
||||
request.headers.slug = 'slugA';
|
||||
await expect(parser.parse(request, metadata)).resolves.toBeUndefined();
|
||||
expect(metadata.quads()).toHaveLength(1);
|
||||
expect(metadata.get(HTTP.slug)?.value).toBe('slugA');
|
||||
});
|
||||
});
|
||||
@@ -3,9 +3,9 @@ import {
|
||||
parseAcceptCharset,
|
||||
parseAcceptEncoding,
|
||||
parseAcceptLanguage,
|
||||
} from '../../../src/util/AcceptParser';
|
||||
} from '../../../src/util/HeaderUtil';
|
||||
|
||||
describe('AcceptParser', (): void => {
|
||||
describe('HeaderUtil', (): void => {
|
||||
describe('parseAccept function', (): void => {
|
||||
it('parses empty Accept headers.', async(): Promise<void> => {
|
||||
expect(parseAccept('')).toEqual([]);
|
||||
@@ -39,7 +39,7 @@ describe('AcceptParser', (): void => {
|
||||
expect(parseAccept('audio/basic; param1="val" ; q=0.5 ;param2="\\\\\\"valid"')).toEqual([
|
||||
{ range: 'audio/basic',
|
||||
weight: 0.5,
|
||||
parameters: { mediaType: { param1: '"val"' }, extension: { param2: '"\\\\\\"valid"' }}},
|
||||
parameters: { mediaType: { param1: 'val' }, extension: { param2: '\\\\\\"valid' }}},
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -59,15 +59,15 @@ describe('AcceptParser', (): void => {
|
||||
});
|
||||
|
||||
it('rejects Accept Headers with invalid parameters.', async(): Promise<void> => {
|
||||
expect((): any => parseAccept('a/b; a')).toThrow('Invalid Accept parameter:');
|
||||
expect((): any => parseAccept('a/b; a=\\')).toThrow('Invalid Accept parameter:');
|
||||
expect((): any => parseAccept('a/b; q=1 ; a=\\')).toThrow('Invalid Accept parameter:');
|
||||
expect((): any => parseAccept('a/b; q=1 ; a')).not.toThrow('Invalid Accept parameter:');
|
||||
expect((): any => parseAccept('a/b; a')).toThrow('Invalid Accept parameter');
|
||||
expect((): any => parseAccept('a/b; a=\\')).toThrow('Invalid parameter value');
|
||||
expect((): any => parseAccept('a/b; q=1 ; a=\\')).toThrow('Invalid parameter value');
|
||||
expect((): any => parseAccept('a/b; q=1 ; a')).not.toThrow('Invalid Accept parameter');
|
||||
});
|
||||
|
||||
it('rejects Accept Headers with quoted parameters.', async(): Promise<void> => {
|
||||
expect((): any => parseAccept('a/b; a="\\""')).not.toThrow();
|
||||
expect((): any => parseAccept('a/b; a="\\\u007F"')).toThrow('Invalid quoted string in Accept header:');
|
||||
expect((): any => parseAccept('a/b; a="\\\u007F"')).toThrow('Invalid quoted string in header:');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -82,6 +82,7 @@ describe('AcceptParser', (): void => {
|
||||
it('rejects invalid Accept-Charset Headers.', async(): Promise<void> => {
|
||||
expect((): any => parseAcceptCharset('a/b')).toThrow('Invalid Accept-Charset range:');
|
||||
expect((): any => parseAcceptCharset('a; q=text')).toThrow('Invalid q value:');
|
||||
expect((): any => parseAcceptCharset('a; c=d')).toThrow('Only q parameters are allowed');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -101,6 +102,7 @@ describe('AcceptParser', (): void => {
|
||||
it('rejects invalid Accept-Encoding Headers.', async(): Promise<void> => {
|
||||
expect((): any => parseAcceptEncoding('a/b')).toThrow('Invalid Accept-Encoding range:');
|
||||
expect((): any => parseAcceptEncoding('a; q=text')).toThrow('Invalid q value:');
|
||||
expect((): any => parseAcceptCharset('a; c=d')).toThrow('Only q parameters are allowed');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -122,6 +124,7 @@ describe('AcceptParser', (): void => {
|
||||
expect((): any => parseAcceptLanguage('a-b-c-d')).not.toThrow('Invalid Accept-Language range:');
|
||||
|
||||
expect((): any => parseAcceptLanguage('a; q=text')).toThrow('Invalid q value:');
|
||||
expect((): any => parseAcceptCharset('a; c=d')).toThrow('Only q parameters are allowed');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user