node.jsexpresspostx-www-form-urlencoded

forward POST x-www-form-urlencoded to another POST arrives with empty req.body


A 3rd party API uses a local bash agent to send data from local machine to itself (here is a simplified version): wget -q -T 25 --post-data "aa=bb&cc=dd" --no-check-certificate "$url"

The machine in question uses an internet from an ISP that blocks the 3rd party address, so I tried to create a proxy server that will receive the data from the agent and forward it to the 3rd party server. The problem is that the forwarded req.body arrives as an empty object and I don't understand why. Here is a simplified node.js code that fails of the proxy API and a simulated API for the 3rd party:

const http = require('http')
const compression = require('compression')
const express = require('express')

const httpServerPort = process.env.SERVER_PORT   /// SET YOUR PORT

const app = express()
app.use(express.urlencoded({ extended: true, limit: '50mb' }))
app.use(compression())

const httpServer = http.createServer(app)

httpServer.listen(httpServerPort, () => {
    console.log(`HTTP server started on port ${httpServerPort}`)
})

app.post('/api/v1/agent_proxy', async (req, res) => {
    try {
        const postData = querystring.stringify(req.body)
//        console.log(postData)
        const options = {
            hostname: 'localhost',
            port: httpServerPort,
            path: '/api/v1/simu_api',
            method: 'POST',
            Headers: {
                "Content-Type": "application/x-www-form-urlencoded",
                "Content-Length": Buffer.byteLength(postData)
            }
        }

        const innerReq = http.request(options, (innerRes) => {
            innerRes.on('data', (d) => {
                console.log(`statusCode: ${res.statusCode}`) 
                res.sendStatus(200)
            });
        });

        innerReq.on('error', (error) => {
            console.error(error)
            res.sendStatus(500)
        });

        innerReq.write(postData)
        innerReq.end()

    } catch (err) {
        console.error(err)
        res.sendStatus(501)
    }
})

app.post('/api/v1/simu_api', async (req, res) => {
    try {
////////// HERE I CAN SEE THE PROBLEM OF req.body == {} WHILE IT SHOULD BE EQUAL TO {aa: 'bb', cc: 'dd'} /////////
        console.log(req.body) 
    } catch (err) {
        console.error(err)
        res.sendStatus(501)
    }
    res.sendStatus(200)
})


Solution

  • In the options object, I wrote "Headers" instead of "headers". That's it.