Proxy in NodeJS einrichten

Proxy in NodeJS einrichten


Kürzlich benötigte ein Projekt, dass NodeJS einen Proxy verwendet. Ich dachte zunächst, es wäre eine einfache Konfiguration, aber es stellte sich als recht herausfordernd heraus.

NodeJS liest standardmäßig keine System-Proxys, und da NodeJS mehrere Methoden zum Senden von Netzwerkanfragen hat, variieren auch die Möglichkeiten zur Einrichtung von Proxys. Hier ist eine Zusammenfassung.

Voraussetzungen

Nehmen wir an, die Proxy-Server-Adressen kommen aus Umgebungsvariablen, was die Standardpraxis für viele Web-Apps ist. Der Einfachheit halber nennen wir sie HTTP_PROXY und HTTPS_PROXY.

Fetch

Neuere Versionen von NodeJS unterstützen die Fetch-Schnittstelle, die versucht, konsistent mit dem Browser-Fetch zu sein, aber wenn sie vollständig konsistent wäre, gäbe es keine Möglichkeit, Proxys einzurichten. Glücklicherweise hat NodeJS eine Hintertür geöffnet, indem es einen einzigartigen Parameter dispatcher hinzugefügt hat, um Netzwerkanfrageparameter, einschließlich Proxy-Server, zu modifizieren.

Wir können das undici-Paket verwenden, um den dispatcher einzurichten:

npm install undici

Fetch-Proxy einrichten

Verwenden Sie ProxyAgent zur Einrichtung:

import { ProxyAgent } from "undici";

const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
if (proxyUrl) {
  await fetch(url, { dispatcher: new ProxyAgent(proxyUrl) });
}

Globalen Fetch-Proxy einrichten

setGlobalDispatcher wird verwendet, um Proxys für alle Fetch-Aufrufe im NodeJS-Programm einzurichten:

import { setGlobalDispatcher, ProxyAgent } from "undici";

const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
if (proxyUrl) {
  setGlobalDispatcher(new ProxyAgent(proxyUrl));
}

Um den Proxy zu entfernen, können Sie einen leeren Agent setzen:

import { Agent, setGlobalDispatcher } from "undici";
setGlobalDispatcher(new Agent());

Wie es funktioniert

setGlobalDispatcher verwendet tatsächlich einen versteckten Einstiegspunkt in NodeJS. Das globale Objekt in NodeJS hat ein Symbol zum Setzen des globalen Dispatchers:

global[Symbol.for("undici.globalDispatcher.1")] = yourDispatcher;

Dies scheint in NodeJS nicht dokumentiert zu sein (zumindest konnte ich es nicht finden). Weitere Details finden Sie unter: https://github.com/nodejs/node/issues/43187

Was der Dispatcher sonst noch kann, außer Proxys einzurichten

Wenn Sie Agent statt ProxyAgent importieren, können Sie auch Netzwerkparameter wie keepAlive und timeout setzen:

import { Agent } from "undici";

const res = await fetch("https://example.com", {
  dispatcher: new Agent({
    keepAliveTimeout: 10,
    keepAliveMaxTimeout: 10,
  }),
});
const json = await res.json();
console.log(json);

Weitere Details finden Sie in der undici-Dokumentation.

NodeJS Native Module http und https

Wie oben erwähnt, hat NodeJS keine eingebauten Methoden zur Einrichtung von Proxys, daher müssen wir sie mit http.Agent und https.Agent entwickeln. Derzeit sind die beliebten Pakete http-proxy-agent und https-proxy-agent.

Hier ist ein Beispiel mit https-proxy-agent:

import https from "https";
import { HttpsProxyAgent } from "https-proxy-agent";

const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
if (proxyUrl) {
  const agent = new HttpsProxyAgent(proxyUrl);

  https.get(
    {
      host: "example.com",
      path: "/",
      agent,
    },
    (res) => {
      // Antwort verarbeiten
    }
  );
}

Axios

Axios ist fast der Industriestandard für JavaScript. Es hat mehrere Möglichkeiten, Proxys einzurichten (in der Reihenfolge der Priorität von niedrig nach hoch):

  1. Umgebungsvariablen: Axios selbst liest die Umgebungsvariablen HTTP_PROXY und HTTPS_PROXY

  2. proxy-Parameter:

    import axios from "axios";
    
    axios.get("https://example.com", {
      proxy: {
        host: "127.0.0.1",
        port: 7890,
      },
    });
  3. httpAgent und httpsAgent Parameter: Sie können NodeJS’s eingebaute http.Agent und https.Agent übergeben, um Netzwerkparameter zu steuern.

    Hier verwenden wir die im vorherigen Abschnitt erwähnten http-proxy-agent und https-proxy-agent:

    import axios from "axios";
    import { HttpsProxyAgent } from "https-proxy-agent";
    import { HttpProxyAgent } from "http-proxy-agent";
    
    const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
    if (proxyUrl) {
      const httpsAgent = new HttpsProxyAgent(proxyUrl);
      const httpAgent = new HttpProxyAgent(proxyUrl);
    
      const instance = axios.create({
        httpAgent,
        httpsAgent,
      });
    }

Weitere Details finden Sie in der Axios-Dokumentation.

HTTPS-Verbindungsbeschränkungen

Ich habe festgestellt, dass Axios keine HTTPS-Verbindungen herstellen kann, wenn Sie einen HTTP-Proxy mit den ersten beiden Methoden einrichten. Der Grund ist, dass Axios die CONNECT-Methode nicht sendet, daher kann es keine TLS-Verbindungen herstellen (wenn Sie die CONNECT-Methode nicht verstehen, können Sie diesen Artikel lesen).