0

I'm building an API Gateway using Node.js, Express, and http-proxy-middleware. All incoming requests are forwarded to different services based on dynamic routing logic.

I'm encountering a 408 Request Timeout from the target server. What’s confusing is that the proxy seems to hang before the onProxyReq hook even runs, as my logs stop right before that.

EDIT
No more 408 Request Timeout. But onProxyReq still not triggered. Turns out the request body is not being sent, hence the hanging and 408 status. To make sure request body is being sent instead of being swallowed/missing, I use req.rawBody + streamifier.createReadStream().

In my app.js

//get the raw body data
app.use(async (req, res, next) => {
 if (['POST', 'PUT', 'PATCH'].includes(req.method)) {
 try {
 req.rawBody = await getRawBody(req);
 if (req.headers['content-type']?.includes('application/json')) {
 req.body = JSON.parse(req.rawBody.toString());
 }
 } catch (err) {
 return res.status(400).send('Invalid JSON body');
 }
 }
 next();
});
//my proxy function is inside this
app.use(dynamicRouter);

//dynamicRouter function

const dynamicRouter = (req, res, next) => {
 const entrypoint = req.path;
 const clientId = req.body?.client;
 if (!clientId || !req.rawBody) {
 return res.status(400).json({ error: 'Missing client_id or raw body' });
 }
 // Example route
 const proxyRoute = {
 endpointPath: '/api/test',
 targetUrl: 'https://example.com'
 };
 if (entrypoint === proxyRoute.endpointPath) {
 return handleProxyRequest(proxyRoute, req, res, next);
 }
 return res.status(404).json({ message: 'Route not found' });
};
const handleProxyRequest = (route, req, res, next) => {
 const { targetUrl, endpointPath } = route;
 console.log(`[GATEWAY] Forwarding ${req.path} to ${targetUrl}${endpointPath}`);
 console.log("Request Body:", req.body);
 const middleware = createProxyMiddleware({
 target: targetUrl,
 changeOrigin: true,
 logLevel: 'debug',
 pathRewrite: () => endpointPath,
 buffer: streamifier.createReadStream(req.rawBody),
 onProxyReq: (proxyReq, req, res) => {
 console.log('✅ onProxyReq is being called');
 // send JSON body manually
 if (
 req.method === 'POST' &&
 req.headers['content-type']?.includes('application/json') &&
 req.body
 ) {
 const bodyData = JSON.stringify(req.body);
 proxyReq.setHeader('Content-Type', 'application/json');
 proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
 }
 // Log
 console.log('Forwarding:', req.method, req.originalUrl);
 },
 onProxyRes: (proxyRes, req) => {
 console.log('onProxyRes is being called');
 },
 onError: (err, req, res) => {
 console.error('Proxy error:', err.message);
 if (!res.headersSent) {
 res.status(502).json({ error: 'Bad Gateway' });
 }
 }
 });
 return middleware(req, res, next);
};

I see the log: console.log("Request Body:", req.body); But I never see the onProxyReq log even when the target API returns the correct response.

Can someone help me or point me to the right direction? Thank you in advance!

Here's what I've tried

  • Req.body is populated correctly (I use express.json before this runs)
  • targetUrl and endpointPath are valid and point to a reachable API (based on log :"[GATEWAY] Forwarding ..."
  • req.method is POST, and Content-Type is application/json

my logs stops here: console.log("Request Body:", req.body);

and no log for console.log('✅ onProxyReq is being called');

asked Jul 2 at 2:27
3
  • 1
    Could you please edit your question to better show how dynamicRouter is defined? You've got return middleware(req, res, next) but that doesn't appear to be in a function nor are req, res or next defined Commented Jul 2 at 4:35
  • @Phil edited! I call the middleware (handleProxyRequest) after getting info from request body in dynamicRouter. Good news is, no more 408 status. Bad news is, onProxyReq log still not executed Commented Jul 2 at 6:42
  • 1
    Your documentation or guide is out-of-date. See github.com/chimurai/… Commented Jul 2 at 7:15

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.