-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
350 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type { HttpRequest } from '../../../server/HttpRequest'; | ||
import { RepresentationMetadata } from '../../representation/RepresentationMetadata'; | ||
import { MetadataHandler } from './MetadataHandler'; | ||
import type { MetadataParser } from './MetadataParser'; | ||
|
||
/** | ||
* MetadataHandler that lets each of its MetadataParsers add metadata based on the HttpRequest. | ||
*/ | ||
export class BasicMetadataHandler extends MetadataHandler { | ||
private readonly parsers: MetadataParser[]; | ||
|
||
public constructor(parsers: MetadataParser[]) { | ||
super(); | ||
this.parsers = parsers; | ||
} | ||
|
||
public async canHandle(): Promise<void> { | ||
// Can handle all requests | ||
} | ||
|
||
public async handle(request: HttpRequest): | ||
Promise<RepresentationMetadata> { | ||
const metadata = new RepresentationMetadata(); | ||
for (const parser of this.parsers) { | ||
await parser.parse(request, metadata); | ||
} | ||
return metadata; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { HttpRequest } from '../../../server/HttpRequest'; | ||
import type { RepresentationMetadata } from '../../representation/RepresentationMetadata'; | ||
import type { MetadataParser } from './MetadataParser'; | ||
|
||
/** | ||
* Parser for the `content-type` header. | ||
* Currently only stores the media type and ignores other parameters such as charset. | ||
*/ | ||
export class ContentTypeParser implements MetadataParser { | ||
public async parse(request: HttpRequest, metadata: RepresentationMetadata): Promise<void> { | ||
const contentType = request.headers['content-type']; | ||
if (contentType) { | ||
// Will need to use HeaderUtil once parameters need to be parsed | ||
metadata.contentType = /^[^;]*/u.exec(contentType)![0].trim(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { DataFactory } from 'n3'; | ||
import type { HttpRequest } from '../../../server/HttpRequest'; | ||
import { UnsupportedHttpError } from '../../../util/errors/UnsupportedHttpError'; | ||
import { parseParameters, splitAndClean, transformQuotedStrings } from '../../../util/HeaderUtil'; | ||
import { RDF } from '../../../util/UriConstants'; | ||
import type { RepresentationMetadata } from '../../representation/RepresentationMetadata'; | ||
import type { MetadataParser } from './MetadataParser'; | ||
|
||
/** | ||
* Parses Link headers with "rel=type" parameters and adds them as RDF.type metadata. | ||
*/ | ||
export class LinkTypeParser implements MetadataParser { | ||
public async parse(request: HttpRequest, metadata: RepresentationMetadata): Promise<void> { | ||
const { link } = request.headers; | ||
if (link) { | ||
if (Array.isArray(link)) { | ||
link.forEach((entry): void => this.parseLink(entry, metadata)); | ||
} else { | ||
this.parseLink(link, metadata); | ||
} | ||
} | ||
} | ||
|
||
private parseLink(linkEntry: string, metadata: RepresentationMetadata): void { | ||
const { result, replacements } = transformQuotedStrings(linkEntry); | ||
splitAndClean(result).forEach((part): void => { | ||
const [ link, ...parameters ] = part.split(';'); | ||
if (!link.startsWith('<') || !link.endsWith('>')) { | ||
throw new UnsupportedHttpError(`Invalid link header ${part}.`); | ||
} | ||
parseParameters(parameters, replacements).forEach(({ name, value }): void => { | ||
if (name === 'rel' && value === 'type') { | ||
metadata.add(RDF.type, DataFactory.namedNode(link.slice(1, -1))); | ||
} | ||
}); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import type { HttpRequest } from '../../../server/HttpRequest'; | ||
import { AsyncHandler } from '../../../util/AsyncHandler'; | ||
import type { RepresentationMetadata } from '../../representation/RepresentationMetadata'; | ||
|
||
/** | ||
* Parses the metadata of a {@link HttpRequest} into a {@link RepresentationMetadata}. | ||
*/ | ||
export abstract class MetadataHandler extends | ||
AsyncHandler<HttpRequest, RepresentationMetadata> {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { HttpRequest } from '../../../server/HttpRequest'; | ||
import type { RepresentationMetadata } from '../../representation/RepresentationMetadata'; | ||
|
||
/** | ||
* A parser that takes a specific part of an HttpRequest and converts it to medata, | ||
* such as the value of a header entry. | ||
*/ | ||
export interface MetadataParser { | ||
/** | ||
* Potentially adds metadata to the RepresentationMetadata based on the HttpRequest contents. | ||
* @param request - Request with potential metadata. | ||
* @param metadata - Metadata objects that should be updated. | ||
*/ | ||
parse: (request: HttpRequest, metadata: RepresentationMetadata) => Promise<void>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import type { HttpRequest } from '../../../server/HttpRequest'; | ||
import { UnsupportedHttpError } from '../../../util/errors/UnsupportedHttpError'; | ||
import { HTTP } from '../../../util/UriConstants'; | ||
import type { RepresentationMetadata } from '../../representation/RepresentationMetadata'; | ||
import type { MetadataParser } from './MetadataParser'; | ||
|
||
/** | ||
* Converts the contents of the slug header to metadata. | ||
*/ | ||
export class SlugParser implements MetadataParser { | ||
public async parse(request: HttpRequest, metadata: RepresentationMetadata): Promise<void> { | ||
const { slug } = request.headers; | ||
if (slug) { | ||
if (Array.isArray(slug)) { | ||
throw new UnsupportedHttpError('At most 1 slug header is allowed.'); | ||
} | ||
metadata.set(HTTP.slug, slug); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { BasicMetadataHandler } from '../../../../../src/ldp/http/metadata/BasicMetadataHandler'; | ||
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 BasicMetadataHandler', (): void => { | ||
const handler = new BasicMetadataHandler([ | ||
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' ]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'); | ||
}); | ||
}); |
Oops, something went wrong.