Nodejs Http Proxy Server Gives Socket Hang up Error

135 Views Asked by At

I have created a containerized proxy server (say worker server) that listens on port 5000. I ran the container with --network=host option so that it may access the ports on host machine without needing the -p flag.The server has an endpoint get-buttons. The endpoint executes a shell script and then forwards the request to port 6000 of host machine with the same endpoint. I have used http-proxy of nodejs. The code is given below:

const express = require('express');
const httpProxy = require('http-proxy');
const { exec, execSync } = require('child_process');

const app = express();
const proxy = httpProxy.createProxyServer({});

app.get('/get-buttons', (req, res) => {
  // Execute a shell script
  exec(`sh hello_world.sh ${req.query.abc}`, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error starting engine: ${error}`);
      res.status(500).send('Error executing shell script');
      return;
    }
    console.log('Shell script executed successfully');
    proxy.web(req, res, { target: 'http://localhost:6000/get-buttons' }, function (error) {
      console.log("Proxy Error ", error)
    });
  });
});

app.listen(5000, () => {
  console.log('Worker server is running on port 5000');
});

I get the following error every time

Error: socket hang up
    at connResetException (internal/errors.js:639:14)
    at Socket.socketOnEnd (_http_client.js:499:23)
    at Socket.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1333:12)
    at processTicksAndRejections (internal/process/task_queues.js:82:21) {
  code: 'ECONNRESET

It may be noted that, if I run curl localhost:6000/get-buttons from inside the container, it gives me a response. I am confused, if the curl command works,why the nodejs proxy giving me a socker hang up error.

1

There are 1 best solutions below

4
On

http-proxy does not replace the path you are calling, only the host (but with the target path as well). The server on :6000 is receiving a request for /get-buttons/get-buttons.

To reproduce:

  • Use your exact code in a simple container with network host flag.
  • Start a new netcat listener with nc -ltp 6000 on the host
  • Run curl localhost:5000/get-buttons
  • Confirm output from nc:
GET /get-buttons/get-buttons HTTP/1.1
accept: */*
user-agent: curl/7.81.0
host: localhost:5000
connection: close

You can change the target to the following to get the desired result:

    proxy.web(req, res, { target: 'http://localhost:6000'}

The above code yields the below on the target:

:: nc -ltp 6000
GET /get-buttons HTTP/1.1
accept: */*
user-agent: curl/7.81.0
host: localhost:5000
connection: close

Update:

If you are really just wanting to "call some other server", not "proxy the request", you can have a look at axios or got, they might be a better fit for your use-case with less surprises

Update 2:

Removed req.url rewrite based on the update question