將開發 Proxy 與 Node.js 應用程式一起使用

一目了然
目標: 設定 Node.js 應用程式使用 Dev Proxy
時間: 10分鐘
前置條件:設定開發代理,Node.js 應用程式

你如何透過 Dev Proxy 路由 Node.js 請求,取決於你的 Node.js 版本和你用來發送 HTTP 請求的函式庫。 最近的 Node.js 版本可透過環境變數定義的代理路由原生 fetch API 與 httphttps 模組。 對於較舊的 Node.js 版本和其他函式庫,你可以在程式碼中設定代理,或使用 global-agent 套件啟用代理支援,只需最小化程式碼修改。

不管你用哪種方法,Node.js 都必須信任開發代理的根憑證,才能透過開發代理發送 HTTPS 請求。 更多資訊請參閱 「信任開發代理證書」。

信任開發代理憑證

Node.js 預設不使用作業系統憑證儲存庫,所以即使你已在你的電腦上信任 Dev Proxy 的根憑證,Node.js 仍然不信任 Dev Proxy 的根憑證。 與其停用憑證驗證,不如使用 NODE_EXTRA_CA_CERTS 環境變數將開發代理的根憑證加入 Node.js 信任的憑證中。

NODE_EXTRA_CA_CERTS 需持有PEM格式的證書。 當 Dev Proxy 執行時,請使用 devproxy api token,取得 API 令牌,並使用 Dev Proxy API 下載 PEM 格式的根憑證:

TOKEN=$(devproxy api token)
curl -H "Authorization: Bearer $TOKEN" -o dev-proxy-ca.pem "http://127.0.0.1:8897/proxy/rootCertificate?format=crt"

如果你使用 PowerShell,請執行:

$token = devproxy api token
Invoke-WebRequest -Headers @{ Authorization = "Bearer $token" } -OutFile dev-proxy-ca.pem -Uri "http://127.0.0.1:8897/proxy/rootCertificate?format=crt"

然後,啟動應用程式時,將 NODE_EXTRA_CA_CERTS 環境變數指向下載的檔案:

NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node index.js

Node.js 只在程序開始時讀取 NODE_EXTRA_CA_CERTS,所以你無法從程式碼中設定它。 每個 Dev Proxy 安裝都使用自己的根憑證。 如果你重新建立憑證,例如使用 devproxy cert remove 和 devproxy cert ensure,請再次下載。

原生Node.js擷取 API

從 Node.js v24.0.0 和 v22.21.0 開始,原生 fetch API 可以使用在 HTTPS_PROXY、NO_PROXY 和 HTTP_PROXY 環境變數中定義的代理。 從 Node.js v24.5.0 和 v22.21.0 開始,同樣適用於 https 和 http 模組。 除非你將 NODE_USE_ENV_PROXY 環境變數設為 1 以啟用代理伺服器支援,或以 --use-env-proxy 旗標啟動 Node.js,否則 Node.js 會忽略這些變數。

你不需要修改程式碼就能使用 Dev Proxy 搭配原生 fetch API:

(async () => {
  const result = await fetch('https://jsonplaceholder.typicode.com/posts');
  const jsonResult = await result.json();
  console.log(JSON.stringify(jsonResult, null, 2));
})();

啟動應用程式時,啟用代理支援,指定 Dev Proxy 為代理,並信任 Dev Proxy 根憑證:

NODE_USE_ENV_PROXY=1 HTTPS_PROXY=http://127.0.0.1:8000 HTTP_PROXY=http://127.0.0.1:8000 NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node index.js

或者,也可以使用 flag --use-env-proxy 代替 NODE_USE_ENV_PROXY 環境變數:

HTTPS_PROXY=http://127.0.0.1:8000 HTTP_PROXY=http://127.0.0.1:8000 NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node --use-env-proxy index.js

Note

Node.js 正在積極開發內建代理支援。 要檢查你的 Node.js 版本是否支援,請執行 node --version。 如果你使用較舊版本,請使用 undici 套件或以下章節所述的 global-agent 套件。

舊版 Node.js 請使用原生的 fetch API

如果你使用的 Node.js 版本不支援 NODE_USE_ENV_PROXY,請使用 undici 套件中的 EnvHttpProxyAgent,它實作了 Node.js 的原生 fetch API。 EnvHttpProxyAgent從 HTTPS_PROXY、NO_PROXY 和 HTTP_PROXY 環境變數讀取代理。 在你的應用程式開始時,將它設為全域調度器:

import { EnvHttpProxyAgent, setGlobalDispatcher } from 'undici';
setGlobalDispatcher(new EnvHttpProxyAgent());

(async () => {
  const result = await fetch('https://jsonplaceholder.typicode.com/posts');
  const jsonResult = await result.json();
  console.log(JSON.stringify(jsonResult, null, 2));
})();

啟動應用程式時,請指定 Dev Proxy 作為代理,並信任 Dev Proxy 的根憑證:

HTTPS_PROXY=http://127.0.0.1:8000 HTTP_PROXY=http://127.0.0.1:8000 NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node index.mjs

global-agent

global-agent 是一個熱門的函式庫,可為 Node.js 提供全域性的 HTTP/HTTPS 協定代理程式。 它可讓您使用環境變數來指定 Proxy。 使用 global-agent 的優點是,您不需要變更在應用程式中發出 HTTP 要求以使用 Dev Proxy 的方式。

以下是如何在使用 global-agent 的 Node.js 應用程式中使用 node-fetch 的範例:

import fetch from 'node-fetch';
import { bootstrap } from 'global-agent';
bootstrap();

(async () => {
  const result = await fetch('https://jsonplaceholder.typicode.com/posts');
  const jsonResult = await result.json();
  console.log(JSON.stringify(jsonResult, null, 2));
})();

以下是您可以搭配Node.js和標準global-agent模組使用https的方式:

const https = require('https');
const globalAgent = require('global-agent');
globalAgent.bootstrap();

https.get('https://jsonplaceholder.typicode.com/posts', (resp) => {
  let data = '';
  resp.on('data', (d) => {
    data += d;
  });
  resp.on('end', () => {
    console.log(JSON.parse(data));
  });
  resp.on('error', (err) => {
    console.error(err);
  });
});

啟動應用程式時,請用 GLOBAL_AGENT_HTTP_PROXY 環境變數指定代理,並 信任開發代理的根憑證。

NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem GLOBAL_AGENT_HTTP_PROXY=http://127.0.0.1:8000 node global-node-fetch.mjs

node-fetch

node-fetch 是廣受歡迎的函式庫,提供用於 Node.js 的 fetch 實作。 node-fetch 不支援使用環境變數指定 Proxy。 相反地,您必須建立自定義代理程式,並將其傳遞至 fetch 方法。

以下範例說明如何使用 node-fetch 套件來定義代理程式,以搭配開發 Proxy 使用 https-proxy-agent 。

const fetch = require('node-fetch');
const { HttpsProxyAgent } = require('https-proxy-agent');

(async () => {
  // Create a custom agent pointing to Dev Proxy
  const agent = new HttpsProxyAgent('http://127.0.0.1:8000');
  // Pass the agent to the fetch method
  const result = await fetch('https://jsonplaceholder.typicode.com/posts', { agent });
  const jsonResult = await result.json();
  console.log(JSON.stringify(jsonResult, null, 2));
})();

啟動應用程式時,信任開發代理的根憑證:

NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node index.js

Axios

Axios 是另一個熱門連結庫,用於在 Node.js 中提出 HTTP 要求。 Axios 可讓您使用環境變數指定 Proxy,或直接在要求組態中指定代理程式。

搭配環境變數使用 Axios 和 Dev Proxy

當您搭配 Axios 使用 Dev Proxy 並使用環境變數指定 Proxy 時,您不需要變更程式碼。 您只需要設定環境變數, https_proxy 而 Axios 會用它來提出要求。

import axios from 'axios';

(async () => {
  const result = await axios.get('https://jsonplaceholder.typicode.com/posts');
  const response = result.data;
  console.log(JSON.stringify(response, null, 2));
})();

全域指定 https_proxy 環境變數,或在啟動應用程式時指定,並 信任開發代理的根憑證。

https_proxy=http://127.0.0.1:8000 NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node axios.mjs

了解

類似於 node-fetch, Got 不支援使用環境變數指定 Proxy。 相反地,您必須建立自定義代理程式,並將其傳遞至要求。

以下是如何使用 Got 程式庫與 Dev Proxy 進行搭配的範例:

import got from 'got';
import { HttpsProxyAgent } from 'https-proxy-agent';

(async () => {
  // Create a custom agent pointing to Dev Proxy
  const agent = new HttpsProxyAgent('http://127.0.0.1:8000');
  const result = await got('https://jsonplaceholder.typicode.com/posts', {
    // Pass the agent to the request
    agent: {
      https: agent
    }
  }).json();
  console.log(JSON.stringify(result, null, 2));
})();

啟動應用程式時, 請相信開發代理的根憑證:

NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node got.mjs

SuperAgent

SuperAgent 不支援使用環境變數指定 Proxy。 若要搭配 SuperAgent 使用 Dev Proxy,您必須安裝 superagent-proxy 外掛程式,並使用 proxy 方法來設定 Proxy。

const superagent = require('superagent');
require('superagent-proxy')(superagent);

(async () => {
  const result = await superagent
    .get('https://jsonplaceholder.typicode.com/posts')
    .proxy('http://127.0.0.1:8000');
  console.log(JSON.stringify(result.body, null, 2));
})();

啟動應用程式時,信任 Dev Proxy 根憑證:

NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node superagent.js

已知問題

當您搭配Node.js使用Dev Proxy時,可能會遇到下列問題。

UNABLE_TO_VERIFY_LEAF_SIGNATURE 錯誤

當您搭配Node.js使用 Dev Proxy 時,會收到類似下列的錯誤:

/Users/user/my-app/node_modules/node-fetch/lib/index.js:1501
                        reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err));
                               ^
FetchError: request to https://jsonplaceholder.typicode.com/posts failed, reason: unable to verify the first certificate
    at ClientRequest.<anonymous> (/Users/user/my-app/node_modules/node-fetch/lib/index.js:1501:11)
    at ClientRequest.emit (node:events:518:28)
    at TLSSocket.socketErrorListener (node:_http_client:495:9)
    at TLSSocket.emit (node:events:518:28)
    at emitErrorNT (node:internal/streams/destroy:169:8)
    at emitErrorCloseNT (node:internal/streams/destroy:128:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  type: 'system',
  errno: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
  code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
}

這個錯誤表示 Node.js 不信任開發代理的根憑證。 要解決這個問題,請下載 Dev Proxy 根憑證,並在啟動應用程式時將 NODE_EXTRA_CA_CERTS 環境變數設為下載檔案的路徑。 更多資訊請參閱 「信任開發代理證書」。

NODE_EXTRA_CA_CERTS=./dev-proxy-ca.pem node index.js

Warning

避免將 NODE_TLS_REJECT_UNAUTHORIZED 設定為 0 來規避此問題。 它會停用你應用程式所有 HTTPS 請求的憑證驗證。

另請參閱