From ea788ba406d50f3428cee2df72b59dbf5a8bd2e9 Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Fri, 10 Jul 2020 16:25:32 +0200 Subject: [PATCH] fix: Throw correct error for invalid triple data --- src/ldp/http/SimpleBodyParser.ts | 11 ++++++++++- test/integration/RequestParser.test.ts | 4 ++-- test/unit/ldp/http/SimpleBodyParser.test.ts | 12 ++++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/ldp/http/SimpleBodyParser.ts b/src/ldp/http/SimpleBodyParser.ts index 1ad22eef5..f0eddce2e 100644 --- a/src/ldp/http/SimpleBodyParser.ts +++ b/src/ldp/http/SimpleBodyParser.ts @@ -1,8 +1,10 @@ import { BodyParser } from './BodyParser'; import { HttpRequest } from '../../server/HttpRequest'; +import { PassThrough } from 'stream'; import { QuadRepresentation } from '../representation/QuadRepresentation'; import { RepresentationMetadata } from '../representation/RepresentationMetadata'; import { StreamParser } from 'n3'; +import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError'; import { UnsupportedMediaTypeHttpError } from '../../util/errors/UnsupportedMediaTypeHttpError'; /** @@ -41,9 +43,16 @@ export class SimpleBodyParser extends BodyParser { contentType: mediaType, }; + // Catch parsing errors and emit correct error + // Node 10 requires both writableObjectMode and readableObjectMode + const errorStream = new PassThrough({ writableObjectMode: true, readableObjectMode: true }); + const data = input.pipe(new StreamParser()); + data.pipe(errorStream); + data.on('error', (error): boolean => errorStream.emit('error', new UnsupportedHttpError(error.message))); + return { dataType: 'quad', - data: input.pipe(new StreamParser()), + data: errorStream, metadata, }; } diff --git a/test/integration/RequestParser.test.ts b/test/integration/RequestParser.test.ts index dcc156cdf..469d2835b 100644 --- a/test/integration/RequestParser.test.ts +++ b/test/integration/RequestParser.test.ts @@ -1,11 +1,11 @@ import { AcceptPreferenceParser } from '../../src/ldp/http/AcceptPreferenceParser'; import arrayifyStream from 'arrayify-stream'; import { HttpRequest } from '../../src/server/HttpRequest'; +import { Readable } from 'stream'; import { SimpleBodyParser } from '../../src/ldp/http/SimpleBodyParser'; import { SimpleRequestParser } from '../../src/ldp/http/SimpleRequestParser'; import { SimpleTargetExtractor } from '../../src/ldp/http/SimpleTargetExtractor'; import streamifyArray from 'streamify-array'; -import { StreamParser } from 'n3'; import { namedNode, triple } from '@rdfjs/data-model'; describe('A SimpleRequestParser with simple input parsers', (): void => { @@ -34,7 +34,7 @@ describe('A SimpleRequestParser with simple input parsers', (): void => { language: [{ value: 'en-gb', weight: 1 }, { value: 'en', weight: 0.5 }], }, body: { - data: expect.any(StreamParser), + data: expect.any(Readable), dataType: 'quad', metadata: { contentType: 'text/turtle', diff --git a/test/unit/ldp/http/SimpleBodyParser.test.ts b/test/unit/ldp/http/SimpleBodyParser.test.ts index 6e141e1fe..e5a0d4300 100644 --- a/test/unit/ldp/http/SimpleBodyParser.test.ts +++ b/test/unit/ldp/http/SimpleBodyParser.test.ts @@ -1,8 +1,9 @@ import arrayifyStream from 'arrayify-stream'; import { HttpRequest } from '../../../../src/server/HttpRequest'; +import { Readable } from 'stream'; import { SimpleBodyParser } from '../../../../src/ldp/http/SimpleBodyParser'; import streamifyArray from 'streamify-array'; -import { StreamParser } from 'n3'; +import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHttpError'; import { UnsupportedMediaTypeHttpError } from '../../../../src/util/errors/UnsupportedMediaTypeHttpError'; import { namedNode, triple } from '@rdfjs/data-model'; import 'jest-rdf'; @@ -42,7 +43,7 @@ describe('A SimpleBodyparser', (): void => { input.headers = { 'content-type': 'text/turtle' }; const result = await bodyParser.handle(input); expect(result).toEqual({ - data: expect.any(StreamParser), + data: expect.any(Readable), dataType: 'quad', metadata: { contentType: 'text/turtle', @@ -56,4 +57,11 @@ describe('A SimpleBodyparser', (): void => { namedNode('http://test.com/o'), ) ]); }); + + it('throws an UnsupportedHttpError on invalid triple data when reading the stream.', async(): Promise => { + const input = streamifyArray([ ' ' ]) as HttpRequest; + input.headers = { 'content-type': 'text/turtle' }; + const result = await bodyParser.handle(input); + await expect(arrayifyStream(result.data)).rejects.toThrow(UnsupportedHttpError); + }); });