feat: add simple request parser

This commit is contained in:
Joachim Van Herwegen
2020-06-10 11:47:43 +02:00
parent 09eb665c12
commit cf258d0317
16 changed files with 166 additions and 27 deletions

View File

@@ -6,7 +6,6 @@ import { RepresentationMetadata } from '../representation/RepresentationMetadata
import { StreamParser } from 'n3';
import { TypedReadable } from '../../util/TypedReadable';
import { UnsupportedMediaTypeHttpError } from '../../util/errors/UnsupportedMediaTypeHttpError';
import 'jest-rdf';
export class SimpleBodyParser extends BodyParser {
private static readonly contentTypes = [
@@ -32,12 +31,12 @@ export class SimpleBodyParser extends BodyParser {
return undefined;
}
const specificType = contentType.split(';')[0];
const mediaType = contentType.split(';')[0];
const metadata: RepresentationMetadata = {
raw: [],
profiles: [],
contentType: specificType,
contentType: mediaType,
};
// StreamParser is a Readable but typings are incorrect at time of writing

View File

@@ -20,7 +20,7 @@ export class SimplePreferenceParser extends PreferenceParser {
// Datetime can have commas so requires separate rules
let datetime;
if (input.headers['accept-datetime']) {
datetime = [{ value: input.headers['accept-datetime'] as string }];
datetime = [{ value: input.headers['accept-datetime'] as string, weight: 1 }];
}
return { type, charset, datetime, language };
@@ -34,7 +34,7 @@ export class SimplePreferenceParser extends PreferenceParser {
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: 1 };
}
return { value: parts[0].trim(), weight: parseFloat(parts[1].trim().slice('q='.length)) };
});

View File

@@ -0,0 +1,43 @@
import { BodyParser } from './BodyParser';
import { HttpRequest } from '../../server/HttpRequest';
import { Operation } from '../operations/Operation';
import { PreferenceParser } from './PreferenceParser';
import { RequestParser } from './RequestParser';
import { TargetExtractor } from './TargetExtractor';
/**
* Input parsers required for a {@link SimpleRequestParser}.
*/
export interface SimpleRequestParserArgs {
targetExtractor: TargetExtractor;
preferenceParser: PreferenceParser;
bodyParser: BodyParser;
}
export class SimpleRequestParser extends RequestParser {
private readonly targetExtractor: TargetExtractor;
private readonly preferenceParser: PreferenceParser;
private readonly bodyParser: BodyParser;
public constructor(args: SimpleRequestParserArgs) {
super();
Object.assign(this, args);
}
public async canHandle(input: HttpRequest): Promise<void> {
if (!input.url) {
throw new Error('Missing URL.');
}
if (!input.method) {
throw new Error('Missing method.');
}
}
public async handle(input: HttpRequest): Promise<Operation> {
const target = await this.targetExtractor.handleSafe(input);
const preferences = await this.preferenceParser.handleSafe(input);
const body = await this.bodyParser.handleSafe(input);
return { method: input.method, target, preferences, body };
}
}

View File

@@ -9,5 +9,5 @@ export interface RepresentationPreference {
/**
* How important this preference is in a value going from 0 to 1.
*/
weight?: number;
weight: number;
}

View File

@@ -3,7 +3,7 @@
*/
export interface ResourceIdentifier {
/**
* Path to the relevant resource. Usually this would be an URL.
* Path to the relevant resource.
*/
path: string;
}