I have an Ubuntu image based docker container working as a development environment. Inside this container, I have my express app. Below are the code files.
// Start the Express Server - index.ts
import expressApp from "./expressApp";
import 'dotenv/config';
import connectDatabase from "./database/connectDatabase";
import disconnectDatabase from "./database/disconnectDatabase";
import { Server } from "node:http";
const getEnv = (key: string): number => {
const value = process.env[key];
if(!value) {
throw new Error(`Missing environment variable: ${key}`);
}
const parsedValue: number = parseInt(value, 10);
if(isNaN(parsedValue)) {
throw new Error(`Invalid number value for environment variable: ${key}`);
}
return parsedValue;
};
(
async () => {
try {
const port: number = getEnv("EXPRESS_SERVER_PORT");
await connectDatabase();
const server: Server = expressApp.listen(port, () => {
console.log(`Express server started at port ${port}`);
});
process.on('SIGINT', async () => {
await disconnectDatabase();
server.close((error) => {
if(error) {
console.error("Error shutting down the server. Error details: ", error);
} else {
console.log(`Server closed successfully.`);
}
});
});
} catch (initialServerError) {
console.error("Express server couldn't be started.");
console.error(initialServerError);
}
}
)();
// Create the Express Server - expressApp.ts
import express, { Express, Request, Response, NextFunction } from 'express';
import cors from 'cors';
import mainRouter from './routes/mainRouter';
import validateRequestHeader from './middlewares/validateRequestHeader';
import globalErrorHandler from './middlewares/globalErrorHandler';
const expressApp: Express = express();
expressApp.use(express.json()); // parse json requests
// handle express.json() errors
expressApp.use((err: any, req: Request, res: Response, next: NextFunction) => {
console.error(`Express level error: ${err}`);
if (res.headersSent) {
return next(err);
}
res.status(err.status || 500).json({
msg: "An unexpected error occurred.",
error: err.message || "Internal Server Error",
});
});
expressApp.use(cors()); // enable cors
// middlewares to validate incoming request
expressApp.use(validateRequestHeader);
expressApp.use(mainRouter);
expressApp.use(globalErrorHandler);
export default expressApp;
// Global Error Handler - globalErrorHandler.ts
import { Request, Response, NextFunction } from 'express';
const globalErrorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
console.error(`Express level error: ${err}`);
if(res.headersSent) {
return next(err);
}
res.status(err.status || 500).json({
msg: "An unexpected error occurred.",
error: err.message || "Internal Server Error"
});
}
export default globalErrorHandler;
// Middleware to validate if the 'req' object has valid and non-empty HEADERS - validateRequestHeader.ts
import { Request, Response, NextFunction } from 'express';
const validateRequestHeader = (req: Request, res: Response, next: NextFunction): void => {
console.log(req.headers);
// check if 'rawHeaders' exist and are not empty
if(!req.rawHeaders || req.rawHeaders.length === 0) {
res.status(400).json({msg: "Bad request. Empty or missing 'rawHeaders' in 'req'."});
return;
}
// check if 'headers' in 'req' is EMPTY
if(!req.headers || Object.keys(req.headers).length === 0) {
res.status(400).json({msg: "Bad request. Empty 'headers' in 'req'."});
return;
}
// check if 'Content-Type', 'Content-Length', 'Host' details are missing in 'headers' in 'req' object
if(!req.headers['content-type'] || !req.headers['content-length'] || !req.headers['host']) {
res.status(400).json({msg: "Bad request. Missing mandatory details."});
return;
}
console.log('req HEADERS validated successfully.');
next();
}
export default validateRequestHeader;
I have employed multiple middlewares to ensure any bad request gets handled properly. Still, when I am sending a POST method HTTP request to one of the routes with an empty Header and empty Body in the 'req', this request is getting passed through without getting rejected by any of the middlewares or error handlers that I have used in my code. Could someone please help me understand why is this happening, and how can I somehow get this empty HTTP request being rejected successfully by any of the middlewares or error handlers in my code? I am stuck here in my project, and any help to resolve this would be greatly appreciated.