0

I'm trying to create a reverse proxy with express and http-proxy-middleware@2.0.1 with some built-in validation. The hope is that in the onProxyReq function, I can perform a check, and if it fails, I'd return the error to the caller instead of continuing to proxy the request.

It seems that if I send a 404 with "Invalid" immediately, then it works as expected. If there is any delay while performing the validation operation (simulatied here with the setTimeout()) then it throws the error "Cannot set headers after they are send to the client". Is there a way I can get that onProxyReq to "wait" until my validation completes and I can decide whether or not I need to respond to client with error, or continue with proxy.

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

function onProxyReq(proxyReq, req, res) {
    // Some validation

    // ** This causes the error "Cannot set headers after they are sent to the client"
    // setTimeout(()=>{
    //     res.status(404).send('Invalid')
    // }, 500)
    
    // ** This returns "Invalid" to the client as expected
    return res.status(404).send('Invalid')
}

// proxy middleware options
const options = {
  target: 'https://google.com',
  changeOrigin: true,
  logLevel: 'debug',
  onProxyReq,
};

const testProxy = createProxyMiddleware(options);
const app = express();

app.use('/', testProxy);


app.listen(3000);
campbell.rw
  • 1,366
  • 12
  • 22

1 Answers1

1

I am facing a similar situation. I've read through the code in the node-proxy npm module (which is used by http-proxy-middleware). The relevant line where the proxyReq event is raised is here. There is no way to cancel or postpone the proxied request in the onProxyReq event.

For me, the solution lies in inserting my own middleware before the proxy middleware. Adapting your sample code to follow this pattern would result in something that looks like this:

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

function customValidation(req, res, next) {
    setTimeout(()=>{
        if (validationSucceeds) {
             next(); //forward request through to proxy middleware
        } else {
             res.status(404).send('Invalid');
        }
    }, 500)
};

// proxy middleware options
const options = {
  target: 'https://google.com',
  changeOrigin: true,
  logLevel: 'debug'
};

const testProxy = createProxyMiddleware(options);
const app = express();

app.use('/', [customValidation, testProxy]);

app.listen(3000);
Mark Glasgow
  • 529
  • 2
  • 9
  • I actually ended up doing that with my own middleware to do the checks and set a boolean on the req object, and then inside the onProxyReq function if the boolean is false, I do a res.status(404).send('error msg') call, and it seems to work. – campbell.rw Sep 13 '21 at 13:57
  • Nice, yours is a very similar approach. Only difference with mine above is the proxy middleware is not called at all if validation does not succeed. – Mark Glasgow Sep 15 '21 at 00:18
  • @MarkGlasgow I want to access my `req.body` before I send to my proxy server and i tried you method. But inside my middleware `req.body` is undefined. Can you suggest why and what else I can do to achieve what I want ? Thanks. – VIVEK JAIN Oct 25 '21 at 12:46