diff --git a/src/ldp/http/SimpleBodyParser.ts b/src/ldp/http/SimpleBodyParser.ts index fe07b85b8..2736667bb 100644 --- a/src/ldp/http/SimpleBodyParser.ts +++ b/src/ldp/http/SimpleBodyParser.ts @@ -1,4 +1,5 @@ import { BodyParser } from './BodyParser'; +import { DATA_TYPE_QUAD } from '../../util/ContentTypes'; import { HttpRequest } from '../../server/HttpRequest'; import { PassThrough } from 'stream'; import { QuadRepresentation } from '../representation/QuadRepresentation'; @@ -53,7 +54,7 @@ export class SimpleBodyParser extends BodyParser { data.on('error', (error): boolean => errorStream.emit('error', new UnsupportedHttpError(error.message))); return { - dataType: 'quad', + dataType: DATA_TYPE_QUAD, data: errorStream, metadata, }; diff --git a/src/ldp/http/SimpleResponseWriter.ts b/src/ldp/http/SimpleResponseWriter.ts index bd812d22d..410317f49 100644 --- a/src/ldp/http/SimpleResponseWriter.ts +++ b/src/ldp/http/SimpleResponseWriter.ts @@ -1,3 +1,4 @@ +import { DATA_TYPE_BINARY } from '../../util/ContentTypes'; import { HttpError } from '../../util/errors/HttpError'; import { HttpResponse } from '../../server/HttpResponse'; import { ResponseDescription } from '../operations/ResponseDescription'; @@ -11,8 +12,8 @@ export class SimpleResponseWriter extends ResponseWriter { public async canHandle(input: { response: HttpResponse; result: ResponseDescription | Error }): Promise { if (!(input.result instanceof Error)) { const dataType = input.result.body?.dataType; - if (dataType && dataType !== 'binary' && dataType !== 'string') { - throw new UnsupportedHttpError('Only string or binary results are supported.'); + if (dataType && dataType !== DATA_TYPE_BINARY) { + throw new UnsupportedHttpError('Only binary results are supported.'); } } } diff --git a/src/storage/SimpleResourceStore.ts b/src/storage/SimpleResourceStore.ts index a4c0d1c83..e530ff3b4 100644 --- a/src/storage/SimpleResourceStore.ts +++ b/src/storage/SimpleResourceStore.ts @@ -11,6 +11,7 @@ import { ResourceStore } from './ResourceStore'; import streamifyArray from 'streamify-array'; import { StreamWriter } from 'n3'; import { UnsupportedMediaTypeHttpError } from '../util/errors/UnsupportedMediaTypeHttpError'; +import { CONTENT_TYPE_QUADS, DATA_TYPE_BINARY, DATA_TYPE_QUAD } from '../util/ContentTypes'; /** * Resource store storing its data as Quads in an in-memory map. @@ -113,7 +114,7 @@ export class SimpleResourceStore implements ResourceStore { * @returns Promise of array of Quads pulled from the stream. */ private async parseRepresentation(representation: Representation): Promise { - if (representation.dataType !== 'quad') { + if (representation.dataType !== DATA_TYPE_QUAD) { throw new UnsupportedMediaTypeHttpError('SimpleResourceStore only supports quad representations.'); } return arrayifyStream(representation.data); @@ -134,7 +135,7 @@ export class SimpleResourceStore implements ResourceStore { */ private generateRepresentation(data: Quad[], preferences: RepresentationPreferences): Representation { // Always return turtle unless explicitly asked for quads - if (preferences.type?.some((preference): boolean => preference.value.includes('internal/quads'))) { + if (preferences.type?.some((preference): boolean => preference.value.includes(CONTENT_TYPE_QUADS))) { return this.generateQuadRepresentation(data); } return this.generateBinaryRepresentation(data); @@ -148,7 +149,7 @@ export class SimpleResourceStore implements ResourceStore { */ private generateBinaryRepresentation(data: Quad[]): BinaryRepresentation { return { - dataType: 'binary', + dataType: DATA_TYPE_BINARY, data: streamifyArray([ ...data ]).pipe(new StreamWriter({ format: 'text/turtle' })), metadata: { raw: [], profiles: [], contentType: 'text/turtle' }, }; @@ -162,7 +163,7 @@ export class SimpleResourceStore implements ResourceStore { */ private generateQuadRepresentation(data: Quad[]): QuadRepresentation { return { - dataType: 'quad', + dataType: DATA_TYPE_QUAD, data: streamifyArray([ ...data ]), metadata: { raw: [], profiles: []}, }; diff --git a/src/storage/patch/SimpleSparqlUpdatePatchHandler.ts b/src/storage/patch/SimpleSparqlUpdatePatchHandler.ts index 22e88937c..6b9ba8f23 100644 --- a/src/storage/patch/SimpleSparqlUpdatePatchHandler.ts +++ b/src/storage/patch/SimpleSparqlUpdatePatchHandler.ts @@ -11,6 +11,7 @@ import { someTerms } from 'rdf-terms'; import { SparqlUpdatePatch } from '../../ldp/http/SparqlUpdatePatch'; import { Store } from 'n3'; import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError'; +import { CONTENT_TYPE_QUADS, DATA_TYPE_QUAD } from '../../util/ContentTypes'; /** * PatchHandler that supports specific types of SPARQL updates. @@ -55,7 +56,7 @@ export class SimpleSparqlUpdatePatchHandler extends PatchHandler { const lock = await this.locker.acquire(input.identifier); const quads = await this.source.getRepresentation(input.identifier, - { type: [{ value: 'internal/quads', weight: 1 }]}); + { type: [{ value: CONTENT_TYPE_QUADS, weight: 1 }]}); const store = new Store(); const importEmitter = store.import(quads.data); await new Promise((resolve, reject): void => { @@ -66,11 +67,11 @@ export class SimpleSparqlUpdatePatchHandler extends PatchHandler { store.addQuads(inserts); const representation: Representation = { data: store.match() as Readable, - dataType: 'quad', + dataType: DATA_TYPE_QUAD, metadata: { raw: [], profiles: [], - contentType: 'internal/quads', + contentType: CONTENT_TYPE_QUADS, }, }; await this.source.setRepresentation(input.identifier, representation); diff --git a/src/util/ContentTypes.ts b/src/util/ContentTypes.ts new file mode 100644 index 000000000..a757e88b8 --- /dev/null +++ b/src/util/ContentTypes.ts @@ -0,0 +1,4 @@ +export const DATA_TYPE_BINARY = 'binary'; +export const DATA_TYPE_QUAD = 'quad'; + +export const CONTENT_TYPE_QUADS = 'internal/quads'; diff --git a/test/integration/RequestParser.test.ts b/test/integration/RequestParser.test.ts index 173305d45..2fd796d98 100644 --- a/test/integration/RequestParser.test.ts +++ b/test/integration/RequestParser.test.ts @@ -1,5 +1,6 @@ import { AcceptPreferenceParser } from '../../src/ldp/http/AcceptPreferenceParser'; import arrayifyStream from 'arrayify-stream'; +import { DATA_TYPE_QUAD } from '../../src/util/ContentTypes'; import { HttpRequest } from '../../src/server/HttpRequest'; import { Readable } from 'stream'; import { SimpleBodyParser } from '../../src/ldp/http/SimpleBodyParser'; @@ -35,7 +36,7 @@ describe('A SimpleRequestParser with simple input parsers', (): void => { }, body: { data: expect.any(Readable), - dataType: 'quad', + dataType: DATA_TYPE_QUAD, metadata: { contentType: 'text/turtle', profiles: [], diff --git a/test/unit/ldp/http/SimpleBodyParser.test.ts b/test/unit/ldp/http/SimpleBodyParser.test.ts index 2bd078356..47984cadc 100644 --- a/test/unit/ldp/http/SimpleBodyParser.test.ts +++ b/test/unit/ldp/http/SimpleBodyParser.test.ts @@ -1,4 +1,5 @@ import arrayifyStream from 'arrayify-stream'; +import { DATA_TYPE_QUAD } from '../../../../src/util/ContentTypes'; import { HttpRequest } from '../../../../src/server/HttpRequest'; import { Readable } from 'stream'; import { SimpleBodyParser } from '../../../../src/ldp/http/SimpleBodyParser'; @@ -44,7 +45,7 @@ describe('A SimpleBodyparser', (): void => { const result = (await bodyParser.handle(input))!; expect(result).toEqual({ data: expect.any(Readable), - dataType: 'quad', + dataType: DATA_TYPE_QUAD, metadata: { contentType: 'text/turtle', profiles: [], diff --git a/test/unit/ldp/http/SimpleResponseWriter.test.ts b/test/unit/ldp/http/SimpleResponseWriter.test.ts index 15e0263be..91be497ce 100644 --- a/test/unit/ldp/http/SimpleResponseWriter.test.ts +++ b/test/unit/ldp/http/SimpleResponseWriter.test.ts @@ -5,6 +5,7 @@ import { SimpleResponseWriter } from '../../../../src/ldp/http/SimpleResponseWri import streamifyArray from 'streamify-array'; import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHttpError'; import { createResponse, MockResponse } from 'node-mocks-http'; +import { DATA_TYPE_BINARY, DATA_TYPE_QUAD } from '../../../../src/util/ContentTypes'; describe('A SimpleResponseWriter', (): void => { const writer = new SimpleResponseWriter(); @@ -15,11 +16,9 @@ describe('A SimpleResponseWriter', (): void => { }); it('requires the description body to be a string or binary stream if present.', async(): Promise => { - await expect(writer.canHandle({ response, result: { body: { dataType: 'quad' }} as ResponseDescription })) + await expect(writer.canHandle({ response, result: { body: { dataType: DATA_TYPE_QUAD }} as ResponseDescription })) .rejects.toThrow(UnsupportedHttpError); - await expect(writer.canHandle({ response, result: { body: { dataType: 'string' }} as ResponseDescription })) - .resolves.toBeUndefined(); - await expect(writer.canHandle({ response, result: { body: { dataType: 'binary' }} as ResponseDescription })) + await expect(writer.canHandle({ response, result: { body: { dataType: DATA_TYPE_BINARY }} as ResponseDescription })) .resolves.toBeUndefined(); }); @@ -33,7 +32,7 @@ describe('A SimpleResponseWriter', (): void => { it('responds with a body if the description has a body.', async(done): Promise => { const body = { data: streamifyArray([ ' .' ]), - dataType: 'binary', + dataType: DATA_TYPE_BINARY, metadata: { raw: [] as Quad[], profiles: [] as string[], @@ -54,7 +53,7 @@ describe('A SimpleResponseWriter', (): void => { it('responds with a content-type if the metadata has it.', async(done): Promise => { const body = { data: streamifyArray([ ' .' ]), - dataType: 'binary', + dataType: DATA_TYPE_BINARY, metadata: { raw: [] as Quad[], profiles: [] as string[], diff --git a/test/unit/ldp/operations/SimpleGetOperationHandler.test.ts b/test/unit/ldp/operations/SimpleGetOperationHandler.test.ts index ec334032e..b78a58a3e 100644 --- a/test/unit/ldp/operations/SimpleGetOperationHandler.test.ts +++ b/test/unit/ldp/operations/SimpleGetOperationHandler.test.ts @@ -1,3 +1,4 @@ +import { DATA_TYPE_QUAD } from '../../../../src/util/ContentTypes'; import { Operation } from '../../../../src/ldp/operations/Operation'; import { Representation } from '../../../../src/ldp/representation/Representation'; import { ResourceStore } from '../../../../src/storage/ResourceStore'; @@ -6,7 +7,7 @@ import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHtt describe('A SimpleGetOperationHandler', (): void => { const store = { - getRepresentation: async(): Promise => ({ dataType: 'quad' } as Representation), + getRepresentation: async(): Promise => ({ dataType: DATA_TYPE_QUAD } as Representation), } as unknown as ResourceStore; const handler = new SimpleGetOperationHandler(store); @@ -17,7 +18,7 @@ describe('A SimpleGetOperationHandler', (): void => { it('returns the representation from the store with the input identifier.', async(): Promise => { await expect(handler.handle({ target: { path: 'url' }} as Operation)).resolves.toEqual( - { identifier: { path: 'url' }, body: { dataType: 'quad' }}, + { identifier: { path: 'url' }, body: { dataType: DATA_TYPE_QUAD }}, ); }); }); diff --git a/test/unit/storage/SimpleResourceStore.test.ts b/test/unit/storage/SimpleResourceStore.test.ts index 0b8f85e70..eb16080e7 100644 --- a/test/unit/storage/SimpleResourceStore.test.ts +++ b/test/unit/storage/SimpleResourceStore.test.ts @@ -6,6 +6,7 @@ import { RepresentationMetadata } from '../../../src/ldp/representation/Represen import { SimpleResourceStore } from '../../../src/storage/SimpleResourceStore'; import streamifyArray from 'streamify-array'; import { UnsupportedMediaTypeHttpError } from '../../../src/util/errors/UnsupportedMediaTypeHttpError'; +import { CONTENT_TYPE_QUADS, DATA_TYPE_BINARY, DATA_TYPE_QUAD } from '../../../src/util/ContentTypes'; import { namedNode, triple } from '@rdfjs/data-model'; const base = 'http://test.com/'; @@ -24,7 +25,7 @@ describe('A SimpleResourceStore', (): void => { representation = { data: streamifyArray([ quad ]), - dataType: 'quad', + dataType: DATA_TYPE_QUAD, metadata: {} as RepresentationMetadata, }; }); @@ -43,16 +44,16 @@ describe('A SimpleResourceStore', (): void => { }); it('errors for wrong input data types.', async(): Promise => { - (representation as any).dataType = 'binary'; + (representation as any).dataType = DATA_TYPE_BINARY; await expect(store.addResource({ path: base }, representation)).rejects.toThrow(UnsupportedMediaTypeHttpError); }); it('can write and read data.', async(): Promise => { const identifier = await store.addResource({ path: base }, representation); expect(identifier.path.startsWith(base)).toBeTruthy(); - const result = await store.getRepresentation(identifier, { type: [{ value: 'internal/quads', weight: 1 }]}); + const result = await store.getRepresentation(identifier, { type: [{ value: CONTENT_TYPE_QUADS, weight: 1 }]}); expect(result).toEqual({ - dataType: 'quad', + dataType: DATA_TYPE_QUAD, data: expect.any(Readable), metadata: { profiles: [], @@ -74,7 +75,7 @@ describe('A SimpleResourceStore', (): void => { expect(identifier.path.startsWith(base)).toBeTruthy(); const result = await store.getRepresentation(identifier, { type: [{ value: 'text/turtle', weight: 1 }]}); expect(result).toEqual({ - dataType: 'binary', + dataType: DATA_TYPE_BINARY, data: expect.any(Readable), metadata: { profiles: [], @@ -92,7 +93,7 @@ describe('A SimpleResourceStore', (): void => { expect(identifier.path.startsWith(base)).toBeTruthy(); const result = await store.getRepresentation(identifier, { }); expect(result).toEqual({ - dataType: 'binary', + dataType: DATA_TYPE_BINARY, data: expect.any(Readable), metadata: { profiles: [], @@ -107,9 +108,9 @@ describe('A SimpleResourceStore', (): void => { it('can set data.', async(): Promise => { await store.setRepresentation({ path: base }, representation); - const result = await store.getRepresentation({ path: base }, { type: [{ value: 'internal/quads', weight: 1 }]}); + const result = await store.getRepresentation({ path: base }, { type: [{ value: CONTENT_TYPE_QUADS, weight: 1 }]}); expect(result).toEqual({ - dataType: 'quad', + dataType: DATA_TYPE_QUAD, data: expect.any(Readable), metadata: { profiles: [], diff --git a/test/unit/storage/patch/SimpleSparqlUpdatePatchHandler.test.ts b/test/unit/storage/patch/SimpleSparqlUpdatePatchHandler.test.ts index 9e82356f5..80b072999 100644 --- a/test/unit/storage/patch/SimpleSparqlUpdatePatchHandler.test.ts +++ b/test/unit/storage/patch/SimpleSparqlUpdatePatchHandler.test.ts @@ -8,6 +8,7 @@ import { SparqlUpdatePatch } from '../../../../src/ldp/http/SparqlUpdatePatch'; import streamifyArray from 'streamify-array'; import { translate } from 'sparqlalgebrajs'; import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHttpError'; +import { CONTENT_TYPE_QUADS, DATA_TYPE_QUAD } from '../../../../src/util/ContentTypes'; import { namedNode, quad } from '@rdfjs/data-model'; describe('A SimpleSparqlUpdatePatchHandler', (): void => { @@ -64,15 +65,15 @@ describe('A SimpleSparqlUpdatePatchHandler', (): void => { const basicChecks = async(quads: Quad[]): Promise => { expect(source.getRepresentation).toHaveBeenCalledTimes(1); expect(source.getRepresentation).toHaveBeenLastCalledWith( - { path: 'path' }, { type: [{ value: 'internal/quads', weight: 1 }]}, + { path: 'path' }, { type: [{ value: CONTENT_TYPE_QUADS, weight: 1 }]}, ); expect(source.setRepresentation).toHaveBeenCalledTimes(1); expect(order).toEqual([ 'acquire', 'getRepresentation', 'setRepresentation', 'release' ]); const setParams = (source.setRepresentation as jest.Mock).mock.calls[0]; expect(setParams[0]).toEqual({ path: 'path' }); expect(setParams[1]).toEqual(expect.objectContaining({ - dataType: 'quad', - metadata: { raw: [], profiles: [], contentType: 'internal/quads' }, + dataType: DATA_TYPE_QUAD, + metadata: { raw: [], profiles: [], contentType: CONTENT_TYPE_QUADS }, })); await expect(arrayifyStream(setParams[1].data)).resolves.toBeRdfIsomorphic(quads); };