@e12e/http-exception
v1.0.1
Published
Framework-agnostic HTTP exception classes and status codes for Node.js
Maintainers
Readme
@e12e/http-exception
Framework-agnostic HTTP exception classes and status codes for Node.js. Zero dependencies.
Features
- 17 common HTTP exception classes (400-504)
- Full
HttpStatusenum covering all RFC 9110 status codes - Static factory methods on
HttpExceptionfor concise usage - Full TypeScript support with type declarations
- Dual CJS/ESM build
- Zero runtime dependencies
- Works with any framework (Express, Fastify, Koa, NestJS, Hono, etc.) or no framework at all
Installation
npm install @e12e/http-exceptionQuick Start
import { HttpException, HttpStatus, NotFoundException } from '@e12e/http-exception';
// Using exception classes
throw new NotFoundException('User not found');
// Using factory methods
throw HttpException.notFound('User not found');
// Using HttpStatus enum
console.log(HttpStatus.NOT_FOUND); // 404Usage
Exception Classes
Each exception class extends HttpException and comes with a sensible default message:
import {
BadRequestException, // 400
UnauthorizedException, // 401
ForbiddenException, // 403
NotFoundException, // 404
MethodNotAllowedException, // 405
NotAcceptableException, // 406
RequestTimeoutException, // 408
ConflictException, // 409
GoneException, // 410
PayloadTooLargeException, // 413
UnsupportedMediaTypeException, // 415
UnprocessableEntityException, // 422
TooManyRequestsException, // 429
InternalServerErrorException, // 500
NotImplementedException, // 501
BadGatewayException, // 502
ServiceUnavailableException, // 503
GatewayTimeoutException, // 504
} from '@e12e/http-exception';
// Custom message
throw new BadRequestException('Invalid email format');
// With errors payload (useful for validation)
throw new UnprocessableEntityException('Validation failed', {
errors: {
name: 'Name is required',
email: 'Invalid email format',
},
});Factory Methods
The base HttpException class provides static factory methods for all common exceptions:
import { HttpException } from '@e12e/http-exception';
throw HttpException.badRequest('Invalid input');
throw HttpException.unauthorized();
throw HttpException.forbidden('Insufficient permissions');
throw HttpException.notFound('Resource not found');
throw HttpException.conflict('Username already taken');
throw HttpException.tooManyRequests('Rate limit exceeded');
throw HttpException.internal('Something went wrong');
throw HttpException.serviceUnavailable('Server is down for maintenance');Custom Exceptions
Use the base HttpException class with a custom status code:
import { HttpException, HttpStatus } from '@e12e/http-exception';
// Using status code number
throw new HttpException(418, "I'm a teapot");
// Using HttpStatus enum
throw new HttpException(HttpStatus.IM_A_TEAPOT, "I'm a teapot");HttpStatus Enum
Full RFC 9110 status codes available as an enum:
import { HttpStatus } from '@e12e/http-exception';
// 2xx Success
console.log(HttpStatus.OK); // 200
console.log(HttpStatus.CREATED); // 201
console.log(HttpStatus.ACCEPTED); // 202
console.log(HttpStatus.NO_CONTENT); // 204
// 3xx Redirection
console.log(HttpStatus.MOVED_PERMANENTLY); // 301
console.log(HttpStatus.FOUND); // 302
console.log(HttpStatus.NOT_MODIFIED); // 304
console.log(HttpStatus.TEMPORARY_REDIRECT); // 307
console.log(HttpStatus.PERMANENT_REDIRECT); // 308
// 4xx Client Error
console.log(HttpStatus.BAD_REQUEST); // 400
console.log(HttpStatus.UNAUTHORIZED); // 401
console.log(HttpStatus.FORBIDDEN); // 403
console.log(HttpStatus.NOT_FOUND); // 404
console.log(HttpStatus.CONFLICT); // 409
console.log(HttpStatus.UNPROCESSABLE_ENTITY); // 422
console.log(HttpStatus.TOO_MANY_REQUESTS); // 429
// 5xx Server Error
console.log(HttpStatus.INTERNAL_SERVER_ERROR); // 500
console.log(HttpStatus.BAD_GATEWAY); // 502
console.log(HttpStatus.SERVICE_UNAVAILABLE); // 503
console.log(HttpStatus.GATEWAY_TIMEOUT); // 504Framework Integration
Express
import express from 'express';
import { HttpException } from '@e12e/http-exception';
const app = express();
app.get('/users/:id', (req, res) => {
const user = findUser(req.params.id);
if (!user) {
throw HttpException.notFound('User not found');
}
res.json(user);
});
// Error handler middleware
app.use((err, req, res, next) => {
if (err instanceof HttpException) {
return res.status(err.statusCode).json({
statusCode: err.statusCode,
message: err.message,
errors: err.errors,
});
}
res.status(500).json({ message: 'Internal Server Error' });
});Fastify
import Fastify from 'fastify';
import { HttpException } from '@e12e/http-exception';
const app = Fastify();
app.setErrorHandler((error, request, reply) => {
if (error instanceof HttpException) {
return reply.status(error.statusCode).send({
statusCode: error.statusCode,
message: error.message,
errors: error.errors,
});
}
reply.status(500).send({ message: 'Internal Server Error' });
});NestJS
import { HttpException, NotFoundException } from '@e12e/http-exception';
// NestJS has its own HttpException, but you can throw ours
// and catch them in a filter
throw new NotFoundException('User not found');
// Or use the base class for custom status codes
throw new HttpException('Custom error', 418);Hono
import { Hono } from 'hono';
import { HttpException } from '@e12e/http-exception';
const app = new Hono();
app.onError((err, c) => {
if (err instanceof HttpException) {
return c.json(
{ statusCode: err.statusCode, message: err.message },
err.statusCode as any,
);
}
return c.json({ message: 'Internal Server Error' }, 500);
});API
Classes
HttpException
Base exception class.
class HttpException extends Error {
readonly statusCode: number;
readonly statusMessage: string;
readonly errors?: Record<string, unknown>;
constructor(statusCode: number, message?: string, errors?: Record<string, unknown>);
}Specific Exceptions
All extend HttpException with a hardcoded status code:
| Class | Status Code |
|-------|-------------|
| BadRequestException | 400 |
| UnauthorizedException | 401 |
| ForbiddenException | 403 |
| NotFoundException | 404 |
| MethodNotAllowedException | 405 |
| NotAcceptableException | 406 |
| RequestTimeoutException | 408 |
| ConflictException | 409 |
| GoneException | 410 |
| PayloadTooLargeException | 413 |
| UnsupportedMediaTypeException | 415 |
| UnprocessableEntityException | 422 |
| TooManyRequestsException | 429 |
| InternalServerErrorException | 500 |
| NotImplementedException | 501 |
| BadGatewayException | 502 |
| ServiceUnavailableException | 503 |
| GatewayTimeoutException | 504 |
Enum
HttpStatus
All HTTP status codes from RFC 9110 (1xx through 5xx).
License
MIT
