Knowledge Base/How to use proxy with Next.js and Uniform

How to use proxy with Next.js and Uniform

how-toDeveloperCLISDKSecurity

Using an HTTP Proxy with Uniform SDK and CLI

The Problem

If your development machine or production environment is behind a corporate firewall, outbound HTTPS requests to Uniform's API endpoints will be blocked. Your Next.js app will fail with errors like:

TypeError: fetch failed [cause]: Error: read ECONNRESET code: 'ECONNRESET', syscall: 'read'

or:

TypeError: fetch failed [cause]: ConnectTimeoutError: Connect Timeout Error code: 'UND_ERR_CONNECT_TIMEOUT'

Your app needs to reach two Uniform endpoints:

  • https://uniform.app — Management API
  • https://uniform.global — Edge Delivery API

This guide covers how to route these requests through your corporate HTTP proxy.

Step 1: Configure the Uniform CLI

The Uniform CLI is used under the hood even if you don't call it directly — for example, to download the Context manifest for personalization and A/B testing at app start.

Set the standard proxy environment variable before running any CLI commands or starting your app:

export HTTPS_PROXY=http://your-proxy-server:8080

Replace http://your-proxy-server:8080 with your corporate proxy address.

Step 2: Configure the Uniform SDK (differs by Next.js router)

Node.js does not automatically route fetch() requests through HTTP_PROXY/HTTPS_PROXY environment variables. You need additional configuration depending on which Next.js router you use.

Next.js Page Router

The Uniform SDK clients accept a custom fetch parameter. Use https-proxy-agent to create a proxy-aware fetch wrapper and pass it to each SDK client.

Install the dependency:

npm install https-proxy-agent

Create a proxy-aware fetch function and pass it to Uniform SDK clients:

import { HttpsProxyAgent } from "https-proxy-agent"; import { RouteClient } from "@uniformdev/canvas"; function proxyFetch(input: RequestInfo | URL, init?: RequestInit) { if (process.env.HTTPS_PROXY) { const agent = new HttpsProxyAgent(process.env.HTTPS_PROXY); return fetch(input, { ...init, agent } as any); } return fetch(input, init); } // Pass proxyFetch to every Uniform SDK client you create export const routeClient = new RouteClient({ apiKey: process.env.UNIFORM_API_KEY, projectId: process.env.UNIFORM_PROJECT_ID, fetch: proxyFetch, });

Repeat this for every SDK client in your app (e.g., CanvasClient, ContentClient, etc.).

Next.js App Router

The App Router uses Node.js native fetch() internally. You cannot pass a custom fetch function or agent to it, and Next.js overrides the global fetch dispatcher. The Next.js team has acknowledged this limitation.

The solution is to override globalThis.fetch in a Next.js instrumentation file, which runs when the server starts — before any page requests are handled. This patches all server-side fetch() calls to route external requests through your proxy.

Install the dependency:

npm install undici

Create instrumentation.ts in your src/ directory (or project root if you don't use a src/ directory):

// src/instrumentation.ts export async function register() { if (process.env.NEXT_RUNTIME === "nodejs" && process.env.HTTPS_PROXY) { const undici = await import("undici"); const proxyAgent = new undici.ProxyAgent({ uri: process.env.HTTPS_PROXY, }); const originalFetch = globalThis.fetch; globalThis.fetch = ((input: any, init?: any) => { const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url; const isLocal = url?.includes("localhost") || url?.includes("127.0.0.1"); if (isLocal) { return originalFetch(input, init); } return originalFetch(input, { ...init, dispatcher: proxyAgent, } as any); }) as typeof fetch; console.log( "[proxy] Routing external fetch requests through " + process.env.HTTPS_PROXY"; ); } }

Why this approach? Using undici.setGlobalDispatcher() alone is not reliable because Next.js 15 overrides the global dispatcher internally. Patching globalThis.fetch directly and passing the dispatcher option per-request ensures the proxy is used for all external requests. The process.env.NEXT_RUNTIME === "nodejs" check prevents the undici import from being bundled into client-side code.

Note on Next.js 14 and earlier: Instrumentation is enabled by default in Next.js 15+. If you're on Next.js 14 or earlier, you may need to enable it by adding experimental: { instrumentationHook: true } to your next.config.ts.

How to run:

export HTTPS_PROXY=http://your-proxy-server:8080 export NO_PROXY=localhost,127.0.0.1 npm run dev

Note: If your corporate proxy performs SSL inspection (MITM), you may also need to trust the proxy's CA certificate:

export NODE_EXTRA_CA_CERTS=/path/to/corporate-proxy-ca-cert.pem

Summary

What

Page Router

App Router

CLI proxy

HTTPS_PROXY env var

HTTPS_PROXY env var

SDK proxy

Custom fetch with https-proxy-agent on each SDK client

globalThis.fetch override with undici in instrumentation.ts

SSL inspection

NODE_EXTRA_CA_CERTS env var

NODE_EXTRA_CA_CERTS env var

Environment variables reference

Variable

Purpose

Example

HTTPS_PROXY

Proxy server URL for HTTPS requests

http://10.0.0.113:9090

HTTP_PROXY

Proxy server URL for HTTP requests

http://10.0.0.113:9090

NO_PROXY

Comma-separated list of hosts to bypass the proxy

localhost,127.0.0.1

NODE_EXTRA_CA_CERTS

Path to CA certificate for SSL-inspecting proxies

/path/to/ca-cert.pem

Verifying Your Proxy Configuration

To confirm the proxy is working, look for this log message when your app starts:

[proxy] Routing external fetch requests through http://your-proxy-server:8080

If you don't see this message, check that:

  1. The HTTPS_PROXY environment variable is set.
  2. Your instrumentation.ts file is in the correct location (src/ directory if your project uses one, otherwise project root).
  3. The instrumentation hook is enabled (Next.js 14 and earlier require experimental.instrumentationHook: true in your Next.js config).
Published: January 6, 2025