fix: Retain status codes when combining errors

This commit is contained in:
Joachim Van Herwegen
2020-09-30 14:19:21 +02:00
parent 7a41108931
commit 10723bb6b8
4 changed files with 71 additions and 7 deletions

View File

@@ -1,4 +1,6 @@
import type { AsyncHandler } from './AsyncHandler';
import { HttpError } from './errors/HttpError';
import { InternalServerError } from './errors/InternalServerError';
import { UnsupportedHttpError } from './errors/UnsupportedHttpError';
/**
@@ -70,7 +72,7 @@ export class CompositeAsyncHandler<TIn, TOut> implements AsyncHandler<TIn, TOut>
* @returns A promise resolving to a handler that supports the data or otherwise rejecting.
*/
private async findHandler(input: TIn): Promise<AsyncHandler<TIn, TOut>> {
const errors: Error[] = [];
const errors: HttpError[] = [];
for (const handler of this.handlers) {
try {
@@ -78,16 +80,28 @@ export class CompositeAsyncHandler<TIn, TOut> implements AsyncHandler<TIn, TOut>
return handler;
} catch (error: unknown) {
if (error instanceof Error) {
if (error instanceof HttpError) {
errors.push(error);
} else if (error instanceof Error) {
errors.push(new InternalServerError(error.message));
} else {
errors.push(new Error('Unknown error.'));
errors.push(new InternalServerError('Unknown error.'));
}
}
}
const joined = errors.map((error: Error): string => error.message).join(', ');
const message = `No handler supports the given input: [${joined}].`;
throw new UnsupportedHttpError(`No handler supports the given input: [${joined}].`);
// Check if all errors have the same status code
if (errors.every((error): boolean => error.statusCode === errors[0].statusCode)) {
throw new HttpError(errors[0].statusCode, errors[0].name, message);
}
// Find the error range (4xx or 5xx)
if (errors.some((error): boolean => error.statusCode >= 500)) {
throw new InternalServerError(message);
}
throw new UnsupportedHttpError(message);
}
}

View File

@@ -1,8 +1,8 @@
/**
* An abstract class for all errors that could be thrown by Solid.
* A class for all errors that could be thrown by Solid.
* All errors inheriting from this should fix the status code thereby hiding the HTTP internals from other components.
*/
export abstract class HttpError extends Error {
export class HttpError extends Error {
public statusCode: number;
/**
@@ -11,7 +11,7 @@ export abstract class HttpError extends Error {
* @param name - Error name. Useful for logging and stack tracing.
* @param message - Message to be thrown.
*/
protected constructor(statusCode: number, name: string, message?: string) {
public constructor(statusCode: number, name: string, message?: string) {
super(message);
this.statusCode = statusCode;
this.name = name;

View File

@@ -0,0 +1,9 @@
import { HttpError } from './HttpError';
/**
* A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
*/
export class InternalServerError extends HttpError {
public constructor(message?: string) {
super(500, 'InternalServerError', message);
}
}