feat: Allow filtering in ConstantConverter based on type

This commit is contained in:
Joachim Van Herwegen 2021-08-20 16:46:32 +02:00
parent fd52765651
commit ab06dd30f3
2 changed files with 42 additions and 2 deletions

View File

@ -23,6 +23,14 @@ export interface ConstantConverterOptions {
* The minimum requested quality/preference before this should trigger.
*/
minQuality?: number;
/**
* Media ranges for which the conversion should happen.
*/
enabledMediaRanges?: string[];
/**
* Media ranges for which the conversion should not happen.
*/
disabledMediaRanges?: string[];
}
/**
@ -57,6 +65,8 @@ export class ConstantConverter extends RepresentationConverter {
container: options.container ?? true,
document: options.document ?? true,
minQuality: options.minQuality ?? 0,
enabledMediaRanges: options.enabledMediaRanges ?? [ '*/*' ],
disabledMediaRanges: options.disabledMediaRanges ?? [],
};
}
@ -83,10 +93,19 @@ export class ConstantConverter extends RepresentationConverter {
throw new NotImplementedHttpError(`Preference is lower than the specified minimum quality`);
}
const sourceContentType = representation.metadata.contentType ?? '';
// Do not replace the representation if it already has our content type
if (matchesMediaType(representation.metadata.contentType ?? '', this.contentType)) {
if (matchesMediaType(sourceContentType, this.contentType)) {
throw new NotImplementedHttpError(`Representation is already ${this.contentType}`);
}
// Only replace the representation if it matches the media range settings
if (!this.options.enabledMediaRanges.some((type): boolean => matchesMediaType(sourceContentType, type))) {
throw new NotImplementedHttpError(`${sourceContentType} is not one of the enabled media types.`);
}
if (this.options.disabledMediaRanges.some((type): boolean => matchesMediaType(sourceContentType, type))) {
throw new NotImplementedHttpError(`${sourceContentType} is one of the disabled media types.`);
}
}
public async handle({ representation }: RepresentationConverterArgs): Promise<Representation> {

View File

@ -3,6 +3,7 @@ import arrayifyStream from 'arrayify-stream';
import { RepresentationMetadata } from '../../../../src/ldp/representation/RepresentationMetadata';
import type { ConstantConverterOptions } from '../../../../src/storage/conversion/ConstantConverter';
import { ConstantConverter } from '../../../../src/storage/conversion/ConstantConverter';
import { CONTENT_TYPE } from '../../../../src/util/Vocabularies';
const createReadStream = jest.spyOn(fs, 'createReadStream').mockReturnValue('file contents' as any);
@ -12,7 +13,7 @@ describe('A ConstantConverter', (): void => {
let converter: ConstantConverter;
beforeEach(async(): Promise<void> => {
options = { container: true, document: true, minQuality: 1 };
options = { container: true, document: true, minQuality: 1, enabledMediaRanges: [ '*/*' ], disabledMediaRanges: []};
converter = new ConstantConverter('abc/def/index.html', 'text/html', options);
});
@ -69,6 +70,26 @@ describe('A ConstantConverter', (): void => {
await expect(converter.canHandle(args)).rejects.toThrow('Representation is already text/html');
});
it('does not support representations if their content-type is not enabled.', async(): Promise<void> => {
const preferences = { type: { 'text/html': 1 }};
const representation = { metadata: new RepresentationMetadata({ [CONTENT_TYPE]: 'text/plain' }) } as any;
const args = { identifier: { path: 'container/' }, representation, preferences };
converter = new ConstantConverter('abc/def/index.html', 'text/html', { enabledMediaRanges: [ 'text/turtle' ]});
await expect(converter.canHandle(args)).rejects.toThrow('text/plain is not one of the enabled media types.');
});
it('does not support representations if their content-type is disabled.', async(): Promise<void> => {
const preferences = { type: { 'text/html': 1 }};
const representation = { metadata: new RepresentationMetadata({ [CONTENT_TYPE]: 'text/plain' }) } as any;
const args = { identifier: { path: 'container/' }, representation, preferences };
converter = new ConstantConverter('abc/def/index.html', 'text/html', { disabledMediaRanges: [ 'text/*' ]});
await expect(converter.canHandle(args)).rejects.toThrow('text/plain is one of the disabled media types.');
});
it('supports representations with an unknown content type.', async(): Promise<void> => {
const preferences = { type: { 'text/html': 1 }};
const metadata = new RepresentationMetadata();