feat: Add metadata to errors

This commit is contained in:
Joachim Van Herwegen
2023-07-25 14:10:46 +02:00
parent a333412e19
commit f373dff1d7
42 changed files with 455 additions and 419 deletions

View File

@@ -20,6 +20,7 @@ import { NotFoundHttpError } from '../../../src/util/errors/NotFoundHttpError';
import { NotImplementedHttpError } from '../../../src/util/errors/NotImplementedHttpError';
import { PreconditionFailedHttpError } from '../../../src/util/errors/PreconditionFailedHttpError';
import type { Guarded } from '../../../src/util/GuardedStream';
import { ContentType } from '../../../src/util/Header';
import { SingleRootIdentifierStrategy } from '../../../src/util/identifiers/SingleRootIdentifierStrategy';
import { trimTrailingSlashes } from '../../../src/util/PathUtil';
import { guardedStreamFrom } from '../../../src/util/StreamUtil';
@@ -673,7 +674,7 @@ describe('A DataAccessorBasedStore', (): void => {
representation.metadata.add(
SOLID_META.terms.preserve, namedNode(metaResourceID.path), SOLID_META.terms.ResponseMetadata,
);
representation.metadata.contentType = 'text/plain; charset=UTF-8';
representation.metadata.contentTypeObject = new ContentType('text/plain', { charset: 'UTF-8' });
await store.setRepresentation(resourceID, representation);
const { metadata } = accessor.data[resourceID.path];
expect(metadata.quads(null, RDF.terms.type)).toHaveLength(2);

View File

@@ -1,6 +1,7 @@
import { BasicRepresentation } from '../../../../src/http/representation/BasicRepresentation';
import { ErrorToJsonConverter } from '../../../../src/storage/conversion/ErrorToJsonConverter';
import { BadRequestHttpError } from '../../../../src/util/errors/BadRequestHttpError';
import { errorTermsToMetadata } from '../../../../src/util/errors/HttpErrorUtil';
import type { OAuthErrorFields } from '../../../../src/util/errors/OAuthHttpError';
import { OAuthHttpError } from '../../../../src/util/errors/OAuthHttpError';
import { readJsonStream } from '../../../../src/util/StreamUtil';
@@ -28,11 +29,13 @@ describe('An ErrorToJsonConverter', (): void => {
statusCode: 400,
errorCode: 'H400',
stack: error.stack,
details: {},
});
});
it('copies the HttpError details.', async(): Promise<void> => {
const error = new BadRequestHttpError('error text', { details: { important: 'detail' }});
const metadata = errorTermsToMetadata({ important: 'detail' });
const error = new BadRequestHttpError('error text', { metadata });
const representation = new BasicRepresentation([ error ], 'internal/error', false);
const prom = converter.handle({ identifier, representation, preferences });
await expect(prom).resolves.toBeDefined();
@@ -75,11 +78,13 @@ describe('An ErrorToJsonConverter', (): void => {
error_description: 'error_description',
scope: 'scope',
state: 'state',
details: {},
});
});
it('does not copy the details if they are not serializable.', async(): Promise<void> => {
const error = new BadRequestHttpError('error text', { details: { object: BigInt(1) }});
it('only adds stack if it is defined.', async(): Promise<void> => {
const error = new BadRequestHttpError('error text');
delete error.stack;
const representation = new BasicRepresentation([ error ], 'internal/error', false);
const prom = converter.handle({ identifier, representation, preferences });
await expect(prom).resolves.toBeDefined();
@@ -91,39 +96,7 @@ describe('An ErrorToJsonConverter', (): void => {
message: 'error text',
statusCode: 400,
errorCode: 'H400',
stack: error.stack,
});
});
it('defaults to status code 500 for non-HTTP errors.', async(): Promise<void> => {
const error = new Error('error text');
const representation = new BasicRepresentation([ error ], 'internal/error', false);
const prom = converter.handle({ identifier, representation, preferences });
await expect(prom).resolves.toBeDefined();
const result = await prom;
expect(result.binary).toBe(true);
expect(result.metadata.contentType).toBe('application/json');
await expect(readJsonStream(result.data)).resolves.toEqual({
name: 'Error',
message: 'error text',
statusCode: 500,
stack: error.stack,
});
});
it('only adds stack if it is defined.', async(): Promise<void> => {
const error = new Error('error text');
delete error.stack;
const representation = new BasicRepresentation([ error ], 'internal/error', false);
const prom = converter.handle({ identifier, representation, preferences });
await expect(prom).resolves.toBeDefined();
const result = await prom;
expect(result.binary).toBe(true);
expect(result.metadata.contentType).toBe('application/json');
await expect(readJsonStream(result.data)).resolves.toEqual({
name: 'Error',
message: 'error text',
statusCode: 500,
details: {},
});
});
});

View File

@@ -1,6 +1,7 @@
import { BasicRepresentation } from '../../../../src/http/representation/BasicRepresentation';
import { ErrorToTemplateConverter } from '../../../../src/storage/conversion/ErrorToTemplateConverter';
import { BadRequestHttpError } from '../../../../src/util/errors/BadRequestHttpError';
import { errorTermsToMetadata } from '../../../../src/util/errors/HttpErrorUtil';
import { resolveModulePath } from '../../../../src/util/PathUtil';
import { readableToString } from '../../../../src/util/StreamUtil';
import type { TemplateEngine } from '../../../../src/util/templates/TemplateEngine';
@@ -91,7 +92,8 @@ describe('An ErrorToTemplateConverter', (): void => {
});
it('adds additional information if an error code description is found.', async(): Promise<void> => {
const error = new BadRequestHttpError('error text', { errorCode, details: { key: 'val' }});
const metadata = errorTermsToMetadata({ key: 'val' });
const error = new BadRequestHttpError('error text', { errorCode, metadata });
const representation = new BasicRepresentation([ error ], 'internal/error', false);
const prom = converter.handle({ identifier, representation, preferences });
await expect(prom).resolves.toBeDefined();
@@ -154,8 +156,9 @@ describe('An ErrorToTemplateConverter', (): void => {
});
it('has default template options.', async(): Promise<void> => {
const metadata = errorTermsToMetadata({ key: 'val' });
converter = new ErrorToTemplateConverter(templateEngine);
const error = new BadRequestHttpError('error text', { errorCode, details: { key: 'val' }});
const error = new BadRequestHttpError('error text', { errorCode, metadata });
const representation = new BasicRepresentation([ error ], 'internal/error', false);
const prom = converter.handle({ identifier, representation, preferences });
await expect(prom).resolves.toBeDefined();