简体   繁体   English

Nginx 如何处理来自 nodejs 作为客户端的传出请求?

[英]How Nginx handles outgoing requests going from nodejs as a client?

Intro: I have and angular frontend and node backend (Server A) working fine.简介:我的 angular 前端和节点后端(服务器 A)工作正常。 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).对服务器 A 也使用 nginx。现在从我的节点服务器(服务器 A)我需要调用其他服务器(服务器 B)的 API 端点。

Nginx configurations for Server B wont matter because curl command is working fine.服务器 B 的 Nginx 配置无关紧要,因为 curl 命令运行正常。

I have a PUT and POST https outgoing request from my node server to other server.我有一个从我的节点服务器到其他服务器的 PUT 和 POST https传出请求。 On my system I have nginx service working.在我的系统上,我有 nginx 服务工作。

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.当我从终端使用curl时,API 工作正常,但是通过节点https模块服务器给出了 400 个错误请求。

  1. What is the process for outgoing requests for nginx? nginx的传出请求的流程是什么?
  2. Why is the curl command working and node env requests not working?为什么 curl 命令有效而节点环境请求无效?
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.我认为来自终端的 curl 不会通过客户端 nginx 路由,因此存在一些差异。 AM I correct?我对么?

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.似乎有一些不匹配的支撑会在您关闭 function 之前将其关闭。

  2. You aren't sending the body of the request.您没有发送请求的正文。 https.request() does not have a body option. https.request()没有body选项。 Instead, you use req.write(datastr) to send the body.相反,您使用req.write(datastr)发送正文。 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.您可以在文档中看到选项 object 中没有body属性,它还显示了req.write()所在的代码示例。 Since a POST request is required to have a body, this could be the cause of your error.由于 POST 请求需要有正文,这可能是您的错误的原因。

  3. You are creating a new https agent, but not passing it appropriate arguments .您正在创建一个新的 https 代理,但没有将其传递给适当的 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.目前尚不清楚为什么要创建新代理,因为通常不需要这样做,如果要这样做,则必须指定原因,然后使用适当的 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.取而代之的是,我在选项 object 中添加了agent: false ,它将使用默认选项专门为此请求创建一个新代理。 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.您在客户端请求中包含keycert 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.但是,您的 curl 请求不提供这些,因此显然不需要它们。 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.您可能还需要注意res.on('data', ...)可以接收多个data事件,因此您可以多次调用回调。

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.您通常不需要提供这些,除非目标服务器需要客户端证书身份验证,因为您的 curl 命令不提供这些。 I would suggest removing these from your options object.我建议从您的选项 object 中删除这些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM