At the moment I'm building an API on Express.js with ts-node. At first 30 mins - 1 Hour everything works fine, but after a couple of hours I'm starting getting error context deadline exceeded (Client.Timeout exceeded while awaiting headers)
on every request (from other application and Postman). Application is deployed with NGINX & Docker.
Here is code of main API module:
import express, { Request, Response } from "express";
import cors from "cors";
import dotenv from "dotenv";
import path from 'path';
import * as http from 'http';
import { CheckerRequestBody, CheckerResponse } from "./types";
import { blacklistHandler } from "../src/accounts/accountsMonitor";
import helmet from "helmet";
import { asyncLogger } from "../config/appConfig";
import { AuthToken, BlacklistedWallet } from "../db/models/entity";
import { createAuthorizationMiddleware } from "./middleware";
dotenv.config({ path: path.resolve(__dirname, '../.env') });
const app = express();
const PORT = parseInt(process.env.PORT) || 3000;
const DEFAULT_API_PATH: string = "/api/v1/";
export class DataFromDB{
public static authTokens: AuthToken[] = [];
public static blacklistedAddresses: Set<string> = new Set<string>();
}
app.use(express.json());
app.use(cors({
origin: '*',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: false,
}));
app.use(helmet());
app.use(DEFAULT_API_PATH, createAuthorizationMiddleware());
app.post(DEFAULT_API_PATH + 'check', async (req: Request<{}, {}, CheckerRequestBody>, res: Response<CheckerResponse>) => {
/**
* Returns information about provided Mint Addresses - is this token in Blacklisted or not.
*
* @param req - Object of Request, which contains Array of Mint Addresses.
* @param res - Object of Response, which contains result.
* @returns JSON with Blacklist status and message.
*/
try {
const body: CheckerRequestBody = req.body;
const accountAddresses: string[] = body.accountAddresses;
const result = accountAddresses.some(address => DataFromDB.blacklistedAddresses.has(address));
if (result) {
res.status(200).json({
blacklisted: true,
message: "Blacklisted wallet found"
});
} else {
res.status(200).json({
blacklisted: false,
message: "Blacklisted wallet not found"
});
}
} catch (error) {
res.status(500).json({
blacklisted: false,
message: "Error on server occurred"
});
asyncLogger.error(`Error on API occurred: ${error}`);
}
});
async function getDataFromDatabase(){
try{
const blacklistedAddressesObjects: BlacklistedWallet[] = await blacklistHandler.getAllEntities(blacklistHandler.BlacklistedWalletRepository);
DataFromDB.authTokens = await blacklistHandler.getAllEntities(blacklistHandler.AuthTokensRepository);
DataFromDB.blacklistedAddresses = new Set(blacklistedAddressesObjects.map(({ accountAddress }) => accountAddress));
asyncLogger.info(`Succesfully retrieved data from Database in API module.`);
} catch(error){
asyncLogger.error(`Error occurred while retrieving data from Database in API: ${error}`)
}
}
const server = http.createServer(app);
setInterval(async () => {
await getDataFromDatabase();
}, 1000);
server.listen(PORT, async () => {
asyncLogger.info('Server is currently running on port 3000.');
});
server.on('error', (error) => {
asyncLogger.error(`Error occurred: ${error.message}`);
});
middleware:
import { asyncLogger } from "../config/appConfig";
import { Request, Response, NextFunction } from "express";
import { DataFromDB } from "./schema";
export const createAuthorizationMiddleware = () => {
return async (req: Request, res: Response, next: NextFunction) => {
if (req.path.startsWith("/docs")){
next();
}
const authHeader = req.get('Authorization');
if (!authHeader) {
res.status(403).json({
blacklisted: false,
message: "No Authentication token provided"
});
return;
}
try {
const foundToken = DataFromDB.authTokens.find((entry) => entry.token === authHeader);
if (!foundToken) {
res.status(403).json({
blacklisted: false,
message: "Invalid Authentication token"
});
return;
}
const currentDate = new Date();
const expirationDate = new Date(foundToken.expirationDate);
if (currentDate > expirationDate) {
res.status(403).json({
blacklisted: false,
message: "Authentication token has expired"
});
return;
}
next();
} catch (error) {
asyncLogger.error(`Error reading the auth tokens: ${error}`);
res.status(500).json({
blacklisted: false,
message: "Error on server occurred"
});
}
};
};