Home > front end >  How Nginx handles outgoing requests going from nodejs as a client?
How Nginx handles outgoing requests going from nodejs as a client?

Time:09-27

Intro: I have and angular frontend and node backend (Server A) working fine. Using nginx as well for Server A. Now from my node server (Server A) I need to call an API endpoint of other server (Server B).

Nginx configurations for Server B wont matter because curl command is working fine.

I have a PUT and POST https outgoing request from my node server to other server. On my system I have nginx service working.

The API is working fine when I use curl from the terminal but for the same thing via node https module the server is giving 400 BAD REQUEST.

  1. What is the process for outgoing requests for nginx?
  2. Why is the curl command working and node env requests not working?
curl -i --insecure --request PUT --url https://example.com:443/update --header 'content-type:application/json'  --data '{"example":"Goodmorning"}'

httpsRequest(serverurl, method, header, data, callback){
    console.log("httpsRequest function body")
    let datastr = "";

    if (data !== undefined)
        datastr = JSON.stringify(data);
    const options = {
       host:'example.com',
       port : 443,
       rejectUnauthorized: false,
       path : "/update",
       body : datastr,
       method : method,
       secure:false,
       key : readFileSync("example.key"),
       cert : readFileSync("example.crt"),
      };
    if (header !== undefined) {
          options['headers'] = header
};
    }
    console.log("options\n", options);

    process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
    options.agent = new https.Agent(options);

    // options.agent = httpsAgent;
    const req = https.request(options, (res) => {
        console.log('status code ', res.statusCode);
        console.log('headers:', res.headers);

        res.on('data', (d) => {
            process.stdout.write(d);
            console.log(d);
            if(res.statusCode === "errorexample"){
                callback(null, {data : "success"})
            }else{
               let errormsg = {
                    message : res.message,
                    statusCode : res.statusCode,
                    failureAlarmCode : res.failureAlarmCode
                }
                callback(null, { "error": errormsg });
            }
          });
    });

    req.on('error', (e) => {
        console.error(e);
        callback(e, null);
      });
    req.end();

}

I think the curl from terminal does not route via the client nginx, hence some difference there. AM I correct?

CodePudding user response:

I see a couple problems in the code in your question:

  1. There appears to be some mismatched bracing that closes your function before you want it closed.

  2. You aren't sending the body of the request. https.request() does not have a body option. Instead, you use req.write(datastr) to send the body. You can see in the doc that there is no body property in the options object and it also shows a code example where req.write() goes. Since a POST request is required to have a body, this could be the cause of your error.

  3. You are creating a new https agent, but not passing it appropriate arguments. It's unclear why you are creating a new agent as that would not generally be required and if you are going to do that, you'd have to specify the reason and then use appropriate arguments. In my code solution below, I've removed the code creating a new agent since it isn't correct. In its place, I added agent: false to the option object which will create a new agent specifically for this request with default options. If you want to customize the options, then you need to create an agent using the proper options shown in the doc.

  4. You are including key and cert in a client request. This is not typically required for a client request unless the server specifically requires client certificate authentication. But, your curl request does not supply these so apparently they are not needed. I'd suggest removing those two options.

Here's your code with these issues changed:

httpsRequest(serverurl, method, header, data, callback) {
    console.log("httpsRequest function body")
    let datastr = "";

    if (data !== undefined)
        datastr = JSON.stringify(data);

    const options = {
        host: 'example.com',
        port: 443,
        rejectUnauthorized: false,
        path: "/update",
        method: method,
        secure: false,
        // create new agent with default values just for this request
        agent: false,       
    };
    if (header !== undefined) {
        options['headers'] = header
    }
    console.log("options\n", options);

    process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

    const req = https.request(options, (res) => {
        console.log('status code ', res.statusCode);
        console.log('headers:', res.headers);

        res.on('data', (d) => {
            process.stdout.write(d);
            console.log(d);
            if (res.statusCode === "errorexample") {
                callback(null, { data: "success" })
            } else {
                let errormsg = {
                    message: res.message,
                    statusCode: res.statusCode,
                    failureAlarmCode: res.failureAlarmCode
                }
                callback(null, { "error": errormsg });
            }
        });
    });

    req.on('error', (e) => {
        console.error(e);
        callback(e, null);
    });
    req.write(datastr);
    req.end();

}

You may also want to note that res.on('data', ...) can receive more than one data event so you could be calling your callback more than once.

One other thing that look suspicious here is your inclusion of these two options:

    key: readFileSync("example.key"),
    cert: readFileSync("example.crt"),

This is a client request. You would not normally need to supply these unless the target server requires client certificate authentication which it does not appear to because your curl command does not provide these. I would suggest removing these from your options object.

  • Related