簡體   English   中英

Nginx 如何處理來自 nodejs 作為客戶端的傳出請求?

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

簡介:我的 angular 前端和節點后端(服務器 A)工作正常。 對服務器 A 也使用 nginx。現在從我的節點服務器(服務器 A)我需要調用其他服務器(服務器 B)的 API 端點。

服務器 B 的 Nginx 配置無關緊要,因為 curl 命令運行正常。

我有一個從我的節點服務器到其他服務器的 PUT 和 POST https傳出請求。 在我的系統上,我有 nginx 服務工作。

當我從終端使用curl時,API 工作正常,但是通過節點https模塊服務器給出了 400 個錯誤請求。

  1. nginx的傳出請求的流程是什么?
  2. 為什么 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();

}

我認為來自終端的 curl 不會通過客戶端 nginx 路由,因此存在一些差異。 我對么?

我在您的問題的代碼中看到了幾個問題:

  1. 似乎有一些不匹配的支撐會在您關閉 function 之前將其關閉。

  2. 您沒有發送請求的正文。 https.request()沒有body選項。 相反,您使用req.write(datastr)發送正文。 您可以在文檔中看到選項 object 中沒有body屬性,它還顯示了req.write()所在的代碼示例。 由於 POST 請求需要有正文,這可能是您的錯誤的原因。

  3. 您正在創建一個新的 https 代理,但沒有將其傳遞給適當的 arguments 目前尚不清楚為什么要創建新代理,因為通常不需要這樣做,如果要這樣做,則必須指定原因,然后使用適當的 arguments。 在下面的代碼解決方案中,我刪除了創建新代理的代碼,因為它不正確。 取而代之的是,我在選項 object 中添加了agent: false ,它將使用默認選項專門為此請求創建一個新代理。 如果要自定義選項,則需要使用文檔中顯示的正確選項創建代理。

  4. 您在客戶端請求中包含keycert 除非服務器特別要求客戶端證書身份驗證,否則客戶端請求通常不需要這樣做。 但是,您的 curl 請求不提供這些,因此顯然不需要它們。 我建議刪除這兩個選項。

這是您更改了這些問題的代碼:

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();

}

您可能還需要注意res.on('data', ...)可以接收多個data事件,因此您可以多次調用回調。

這里看起來可疑的另一件事是您包含以下兩個選項:

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

這是一個客戶請求。 您通常不需要提供這些,除非目標服務器需要客戶端證書身份驗證,因為您的 curl 命令不提供這些。 我建議從您的選項 object 中刪除這些。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM