How pi-web Honors HTTP_PROXY, HTTPS_PROXY, and NO_PROXY Environment Variables: Complete Technical Guide

The pi-web HTTP dispatcher in lib/http-dispatcher.ts automatically detects and applies HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables to all outbound requests by instantiating the appropriate proxy agent based on URL scheme and bypass rules.

The pi-web repository provides a lightweight HTTP dispatch layer that transparently handles proxy configuration for every network call. Whether you're fetching model data, installing skills, or calling external APIs, pi-web respects standard proxy environment variables without requiring explicit configuration in your application code.

How the HTTP Dispatcher Reads Proxy Environment Variables

In lib/http-dispatcher.ts, pi-web constructs a dispatcher function that inspects process.env at runtime. The implementation checks for both uppercase and lowercase variants of each variable, following common Unix conventions.

The dispatcher extracts three key configuration sources:

  • HTTP_PROXY / http_proxy — Used for http: URL schemes
  • HTTPS_PROXY / https_proxy — Used for https: URL schemes
  • NO_PROXY / no_proxy — Comma-separated list of hosts to connect to directly

Here's the core logic from lib/http-dispatcher.ts:

// lib/http-dispatcher.ts (simplified)
function createHttpDispatcher() {
  const httpProxy  = process.env.HTTP_PROXY  ?? process.env.http_proxy;
  const httpsProxy = process.env.HTTPS_PROXY ?? process.env.https_proxy;
  const noProxy    = (process.env.NO_PROXY ?? process.env.no_proxy ?? "")
                     .split(/\s*,\s*/)
                     .filter(Boolean);

  return (url: string, init?: RequestInit) => {
    const { hostname, protocol } = new URL(url);
    // Bypass proxy if host matches NO_PROXY
    if (noProxy.some(p => hostname.endsWith(p))) return fetch(url, init);

    // Choose the proper proxy agent
    const agent =
      protocol === "http:" && httpProxy
        ? new HttpProxyAgent(httpProxy)
        : protocol === "https:" && httpsProxy
          ? new HttpsProxyAgent(httpsProxy)
          : undefined;

    return fetch(url, { ...init, agent });
  };
}

The split and filter operation on NO_PROXY handles extra whitespace and empty entries, making the parser tolerant of real-world configuration styles like "localhost, 127.0.0.1, *.internal".

Proxy Agent Selection Based on URL Scheme

HTTP Proxy Agent

When the target URL uses http: and HTTP_PROXY is set, pi-web creates an HttpProxyAgent from the http-proxy-agent package:

protocol === "http:" && httpProxy
  ? new HttpProxyAgent(httpProxy)

This agent implements the HTTP CONNECT tunneling method required to route unencrypted HTTP traffic through a proxy server.

HTTPS Proxy Agent

For https: URLs with HTTPS_PROXY configured, pi-web instantiates HttpsProxyAgent from https-proxy-agent:

protocol === "https:" && httpsProxy
  ? new HttpsProxyAgent(httpsProxy)

The HTTPS agent performs TLS encryption after establishing the CONNECT tunnel, ensuring end-to-end security even through the proxy.

Direct Connection Fallback

If no matching proxy variable is set, or if the agent creation fails, the dispatcher passes undefined as the agent parameter. Modern Node.js fetch implementations (Undici) then use the default global agent for direct connections.

NO_PROXY Bypass Logic

The most nuanced part of pi-web's proxy handling is the NO_PROXY implementation. Before applying any proxy, the dispatcher checks:

if (noProxy.some(p => hostname.endsWith(p))) return fetch(url, init);

This suffix match behavior means:

NO_PROXY entry Matches these hosts
localhost localhost, myapp.localhost
.example.com api.example.com, deep.sub.example.com
192.168.1.1 Exact match only

The .endsWith() approach aligns with curl's interpretation and handles the leading-dot convention for domain wildcards.

Integration with Higher-Level Components

All pi-web network operations flow through this dispatcher. In lib/agent-client.ts, the dispatcher is imported and used for:

  • Model API requests
  • Skill registry queries
  • File downloads and uploads
  • Telemetry submissions
// lib/agent-client.ts usage pattern
import { createHttpDispatcher } from './http-dispatcher';

const dispatch = createHttpDispatcher();

export async function fetchModelMetadata(modelId: string) {
  return dispatch(`https://registry.example.com/models/${modelId}`);
}

This centralized routing ensures consistent proxy behavior across the entire application without scattering environment variable checks throughout the codebase.

Test Coverage for Proxy Behavior

The lib/http-dispatcher.test.mjs file validates proxy handling with a local mock proxy server:

// lib/http-dispatcher.test.mjs - conceptual test structure
test('uses HTTP_PROXY for http URLs', async () => {
  process.env.HTTP_PROXY = 'http://localhost:9999';
  const server = createMockProxy();
  
  const dispatch = createHttpDispatcher();
  await dispatch('http://example.com/data');
  
  expect(server.receivedConnections).toBe(1);
});

test('bypasses proxy for NO_PROXY hosts', async () => {
  process.env.HTTP_PROXY = 'http://localhost:9999';
  process.env.NO_PROXY = 'direct.example.com';
  
  const dispatch = createHttpDispatcher();
  await dispatch('http://direct.example.com/data');
  
  // Request went directly, not through proxy
});

Additional coverage in lib/project-command-env.test.mjs verifies that command-line tooling respects HTTPS_PROXY when executing subcommands.

Practical Configuration Examples

Basic Corporate Proxy Setup

export HTTP_PROXY="http://proxy.corp.internal:8080"
export HTTPS_PROXY="http://proxy.corp.internal:8080"
export NO_PROXY="localhost,127.0.0.1,.internal.corp"

# Run pi-web application - all requests automatically proxied

npm start

Split HTTP/HTTPS Proxies


# Different proxies for encrypted vs unencrypted traffic

export HTTP_PROXY="http://http-proxy.prd:3128"
export HTTPS_PROXY="https://secure-proxy.prd:8443"
export NO_PROXY="metadata.google.internal,.cluster.local"

Container/Kubernetes Deployment


# Kubernetes deployment snippet

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
        - name: pi-web
          env:
            - name: HTTP_PROXY
              value: "http://$(PROXY_SERVICE_HOST):$(PROXY_SERVICE_PORT)"
            - name: HTTPS_PROXY
              value: "http://$(PROXY_SERVICE_HOST):$(PROXY_SERVICE_PORT)"
            - name: NO_PROXY
              value: "kubernetes.default.svc,.cluster.local,169.254.169.254"

Summary

  • pi-web's proxy support is automatic — set environment variables and the lib/http-dispatcher.ts layer handles all request routing
  • Scheme-aware agent selection uses HttpProxyAgent for http: and HttpsProxyAgent for https: URLs
  • NO_PROXY suffix matching supports domain wildcards and exact host exceptions
  • Universal coverage through lib/agent-client.ts ensures every outbound request follows proxy rules
  • Comprehensive tests in lib/http-dispatcher.test.mjs verify correct behavior across proxy, direct, and bypass scenarios

Frequently Asked Questions

How does pi-web handle lowercase proxy variables like http_proxy?

pi-web checks both uppercase and lowercase variants using the nullish coalescing operator: process.env.HTTP_PROXY ?? process.env.http_proxy. The uppercase form takes precedence if both are present, matching the behavior of most Unix networking tools.

Can I disable proxying for specific subdomains only?

Yes. Add the subdomain pattern to NO_PROXY with a leading dot to match all subdomains: export NO_PROXY=".internal.example.com" matches api.internal.example.com but not external.example.com or example.com itself.

What happens if HTTPS_PROXY is set but the proxy URL uses http:// scheme?

The HttpsProxyAgent accepts both http:// and https:// proxy URLs. An http:// proxy URL for HTTPS traffic establishes an unencrypted CONNECT tunnel, which is then encrypted end-to-end between your application and the destination server. This is the most common enterprise configuration.

Does pi-web support authenticated proxies?

Yes. Include credentials directly in the proxy URL: https://user:pass@proxy.example.com:8080. The http-proxy-agent and https-proxy-agent packages parse and apply these credentials automatically in the Proxy-Authorization header.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →