diff --git a/src/ldp/http/SimplePreferenceParser.ts b/src/ldp/http/SimplePreferenceParser.ts new file mode 100644 index 000000000..0f4cda8fc --- /dev/null +++ b/src/ldp/http/SimplePreferenceParser.ts @@ -0,0 +1,42 @@ +import { HttpRequest } from '../../server/HttpRequest'; +import { PreferenceParser } from './PreferenceParser'; +import { RepresentationPreference } from '../representation/RepresentationPreference'; +import { RepresentationPreferences } from '../representation/RepresentationPreferences'; + +export class SimplePreferenceParser extends PreferenceParser { + public constructor() { + super(); + } + + public async canHandle(): Promise { + return undefined; + } + + public async handle(input: HttpRequest): Promise { + const type = this.parseHeader(input.headers.accept); + const charset = this.parseHeader(input.headers['accept-charset'] as string); + const language = this.parseHeader(input.headers['accept-language']); + + // Datetime can have commas so requires separate rules + let datetime; + if (input.headers['accept-datetime']) { + datetime = [{ value: input.headers['accept-datetime'] as string }]; + } + + return { type, charset, datetime, language }; + } + + private parseHeader(header: string): RepresentationPreference[] { + if (!header) { + return undefined; + } + + return header.split(',').map((preference): RepresentationPreference => { + const parts = preference.split(';'); + if (parts.length === 1) { + return { value: parts[0].trim() }; + } + return { value: parts[0].trim(), weight: parseFloat(parts[1].trim().slice('q='.length)) }; + }); + } +} diff --git a/test/unit/ldp/http/SimplePreferenceParser.test.ts b/test/unit/ldp/http/SimplePreferenceParser.test.ts new file mode 100644 index 000000000..8ee8602a3 --- /dev/null +++ b/test/unit/ldp/http/SimplePreferenceParser.test.ts @@ -0,0 +1,34 @@ +import { HttpRequest } from '../../../../src/server/HttpRequest'; +import { SimplePreferenceParser } from '../../../../src/ldp/http/SimplePreferenceParser'; + +describe('A SimplePreferenceParser', (): void => { + const preferenceParser = new SimplePreferenceParser(); + + it('can handle all input.', async(): Promise => { + await expect(preferenceParser.canHandle()).resolves.toBeUndefined(); + }); + + it('returns an empty result if there is no relevant input.', async(): Promise => { + await expect(preferenceParser.handle({ headers: {}} as HttpRequest)).resolves.toEqual({}); + }); + + it('parses accept headers.', async(): Promise => { + await expect(preferenceParser.handle({ headers: { accept: 'audio/*; q=0.2, audio/basic' }} as HttpRequest)) + .resolves.toEqual({ type: [{ value: 'audio/*', weight: 0.2 }, { value: 'audio/basic' }]}); + }); + + it('parses accept-charset headers.', async(): Promise => { + await expect(preferenceParser.handle({ headers: { 'accept-charset': 'iso-8859-5, unicode-1-1;q=0.8' }} as unknown as HttpRequest)) + .resolves.toEqual({ charset: [{ value: 'iso-8859-5' }, { value: 'unicode-1-1', weight: 0.8 }]}); + }); + + it('parses accept-datetime headers.', async(): Promise => { + await expect(preferenceParser.handle({ headers: { 'accept-datetime': 'Tue, 20 Mar 2001 20:35:00 GMT' }} as unknown as HttpRequest)) + .resolves.toEqual({ datetime: [{ value: 'Tue, 20 Mar 2001 20:35:00 GMT' }]}); + }); + + it('parses accept-language headers.', async(): Promise => { + await expect(preferenceParser.handle({ headers: { 'accept-language': 'da, en-gb;q=0.8, en;q=0.7' }} as HttpRequest)) + .resolves.toEqual({ language: [{ value: 'da' }, { value: 'en-gb', weight: 0.8 }, { value: 'en', weight: 0.7 }]}); + }); +});