Skip to content

Commit

Permalink
feat: Allow filtering in ConstantConverter based on type
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimvh committed Sep 2, 2021
1 parent fd52765 commit ab06dd3
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
21 changes: 20 additions & 1 deletion src/storage/conversion/ConstantConverter.ts
Expand Up @@ -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[];
}

/**
Expand Down Expand Up @@ -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 ?? [],
};
}

Expand All @@ -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> {
Expand Down
23 changes: 22 additions & 1 deletion test/unit/storage/conversion/ConstantConverter.test.ts
Expand Up @@ -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);

Expand All @@ -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);
});

Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit ab06dd3

Please sign in to comment.