diff --git a/src/util/handlers/StaticThrowHandler.ts b/src/util/handlers/StaticThrowHandler.ts index 1928f61d8..d33da9129 100644 --- a/src/util/handlers/StaticThrowHandler.ts +++ b/src/util/handlers/StaticThrowHandler.ts @@ -1,11 +1,11 @@ -import type { HttpError } from '../errors/HttpError'; +import type { HttpError, HttpErrorClass } from '../errors/HttpError'; import { AsyncHandler } from './AsyncHandler'; /** - * Utility handler that can handle all input and always throws the given error. + * Utility handler that can handle all input and always throws an instance of the given error. */ export class StaticThrowHandler extends AsyncHandler { - private readonly error: HttpError; + protected readonly error: HttpError; public constructor(error: HttpError) { super(); @@ -13,6 +13,8 @@ export class StaticThrowHandler extends AsyncHandler { } public async handle(): Promise { - throw this.error; + // We are creating a new instance of the error instead of rethrowing the error, + // as reusing the same error can cause problem as the metadata is then also reused. + throw new (this.error.constructor as HttpErrorClass)(); } } diff --git a/test/integration/LdpHandlerWithoutAuth.test.ts b/test/integration/LdpHandlerWithoutAuth.test.ts index b47492030..d27c4ec09 100644 --- a/test/integration/LdpHandlerWithoutAuth.test.ts +++ b/test/integration/LdpHandlerWithoutAuth.test.ts @@ -506,7 +506,11 @@ describe.each(stores)('An LDP handler allowing all requests %s', (name, { storeC }); it('returns 405 for unsupported methods.', async(): Promise => { - const response = await fetch(baseUrl, { method: 'TRACE' }); + let response = await fetch(baseUrl, { method: 'TRACE' }); + expect(response.status).toBe(405); + + // Testing two different URLs as there used to be a problem with this + response = await fetch(joinUrl(baseUrl, 'foo'), { method: 'TRACE' }); expect(response.status).toBe(405); }); diff --git a/test/unit/util/handlers/StaticThrowHandler.test.ts b/test/unit/util/handlers/StaticThrowHandler.test.ts index 3fc561558..803ca26a7 100644 --- a/test/unit/util/handlers/StaticThrowHandler.test.ts +++ b/test/unit/util/handlers/StaticThrowHandler.test.ts @@ -1,5 +1,6 @@ import { BadRequestHttpError } from '../../../../src/util/errors/BadRequestHttpError'; import { StaticThrowHandler } from '../../../../src/util/handlers/StaticThrowHandler'; +import { SOLID_ERROR } from '../../../../src/util/Vocabularies'; describe('A StaticThrowHandler', (): void => { const error = new BadRequestHttpError(); @@ -9,7 +10,26 @@ describe('A StaticThrowHandler', (): void => { await expect(handler.canHandle({})).resolves.toBeUndefined(); }); - it('always throws the given error.', async(): Promise => { + it('always throws an instance of the given error.', async(): Promise => { await expect(handler.handle()).rejects.toThrow(error); }); + + it('creates a new instance every time.', async(): Promise => { + /* eslint-disable jest/no-conditional-expect */ + try { + await handler.handle(); + } catch (error: unknown) { + expect(BadRequestHttpError.isInstance(error)).toBe(true); + // Change the metadata + (error as BadRequestHttpError).metadata.add(SOLID_ERROR.terms.target, 'http://example.com/foo'); + } + try { + await handler.handle(); + } catch (error: unknown) { + expect(BadRequestHttpError.isInstance(error)).toBe(true); + // Metadata should not have the change + expect((error as BadRequestHttpError).metadata.has(SOLID_ERROR.terms.target)).toBe(false); + } + /* eslint-enable jest/no-conditional-expect */ + }); });