Client setup for tools and runtimes

Proxy and certificate settings you can paste for curl, Node, Python, Ruby, Go, Rust, Java, PHP, .NET, Docker, Electron, React Native and Flutter.

Mac

Apps that use the macOS system proxy are captured as soon as WireLens runs with the This Mac scope. Command line tools, language runtimes, containers and some frameworks ignore the system proxy, keep their own certificate store, or both. This page gets each of them into WireLens without ever turning certificate verification off.

Tools ▸ Client Setup in the app has every recipe below with the real paths for your Mac filled in. It lists the runtimes you have installed first, and it can open a shell with the variables already set (Open with env), launch Electron with the right switches, or run keytool for you.

The two values every client needs#

  • Proxy: http://127.0.0.1:9090, the default listener. Check Settings ▸ Capture if you changed the port.
  • Root certificate: your WireLens root as a PEM file, at ~/Library/Application Support/WireLens/ca/wirelens-root.pem.

The examples below use them through two shell variables:

bash
export WL_PROXY=http://127.0.0.1:9090
export WL_CA="$HOME/Library/Application Support/WireLens/ca/wirelens-root.pem"

curl and HTTPie#

bash
curl --proxy "$WL_PROXY" --cacert "$WL_CA" https://example.com

# HTTPie takes scheme:host:port for --proxy
http --proxy=http:"$WL_PROXY" --verify="$WL_CA" https://example.com

# or for the whole shell session
export HTTPS_PROXY="$WL_PROXY" HTTP_PROXY="$WL_PROXY" CURL_CA_BUNDLE="$WL_CA"

Node.js#

bash
export NODE_EXTRA_CA_CERTS="$WL_CA"
export HTTPS_PROXY="$WL_PROXY" HTTP_PROXY="$WL_PROXY"
node app.js

NODE_EXTRA_CA_CERTS adds the WireLens root to Node's bundled store rather than replacing it. Node's own http and https modules ignore proxy variables; axios, got and node-fetch with an agent read them, and the built-in fetch (undici) needs a ProxyAgent.

Python#

bash
export SSL_CERT_FILE="$WL_CA" REQUESTS_CA_BUNDLE="$WL_CA"
export HTTPS_PROXY="$WL_PROXY" HTTP_PROXY="$WL_PROXY"
python3 app.py

requests reads REQUESTS_CA_BUNDLE; httpx, urllib and aiohttp read SSL_CERT_FILE.

Ruby#

bash
export SSL_CERT_FILE="$WL_CA"
export https_proxy="$WL_PROXY" http_proxy="$WL_PROXY"
ruby app.rb

Go#

bash
export HTTPS_PROXY="$WL_PROXY" HTTP_PROXY="$WL_PROXY"
go run .

On macOS, Go verifies certificates against the keychain and ignores SSL_CERT_FILE, so trust the root in the keychain (Certificate ▸ Install for All Users… or wirelens cert install).

Rust#

bash
export HTTPS_PROXY="$WL_PROXY" ALL_PROXY="$WL_PROXY" SSL_CERT_FILE="$WL_CA"
cargo run

SSL_CERT_FILE covers the OpenSSL and native-tls backends. With rustls, add the root explicitly, which also works everywhere else:

rust
let pem = std::fs::read(ca_path)?;
let client = reqwest::Client::builder()
    .proxy(reqwest::Proxy::all("http://127.0.0.1:9090")?)
    .add_root_certificate(reqwest::Certificate::from_pem(&pem)?)
    .build()?;

Java and the JVM#

The JVM keeps its own truststore. Import the root into a named truststore, not the JDK's cacerts in place, then point the JVM at it:

bash
TS="$HOME/Library/Application Support/WireLens/java-truststore/cacerts"
mkdir -p "$(dirname "$TS")"
cp "$JAVA_HOME/lib/security/cacerts" "$TS"
keytool -importcert -noprompt -trustcacerts -alias wirelens \
  -file "$WL_CA" -keystore "$TS" -storepass changeit

java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=9090 \
     -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=9090 \
     -Djavax.net.ssl.trustStore="$TS" \
     -Djavax.net.ssl.trustStorePassword=changeit \
     -jar your-app.jar

changeit is the JDK's stock truststore password, not a placeholder. Tools ▸ Client Setup ▸ Import CA with keytool runs the import for you.

PHP#

bash
export HTTPS_PROXY="$WL_PROXY" HTTP_PROXY="$WL_PROXY"
php -d curl.cainfo="$WL_CA" -d openssl.cafile="$WL_CA" your-script.php

PHP's OpenSSL does not use the macOS keychain. Set both options: file_get_contents reads openssl.cafile and ignores curl.cainfo. With Guzzle you can pass 'proxy' and 'verify' per client instead.

.NET#

bash
export HTTPS_PROXY="$WL_PROXY" HTTP_PROXY="$WL_PROXY" NO_PROXY=localhost,127.0.0.1
dotnet run

On macOS, .NET validates against the system trust store, so trust the root in the keychain, like Go. In a Linux container it reads SSL_CERT_FILE instead. A handler that sets Proxy explicitly ignores the environment, so set one or the other.

Docker#

Inside a container, localhost is the container. Your Mac is host.docker.internal:

bash
docker run --rm \
  -e HTTPS_PROXY=http://host.docker.internal:9090 \
  -e HTTP_PROXY=http://host.docker.internal:9090 \
  -e NO_PROXY=localhost,127.0.0.1 \
  -v "$WL_CA":/usr/local/share/ca-certificates/wirelens.crt:ro \
  your-image sh -c "update-ca-certificates && your-command"

In Compose, add the same environment and volume, plus extra_hosts: ["host.docker.internal:host-gateway"] if you also run it on Linux. Alpine images need the ca-certificates package before update-ca-certificates exists.

Electron#

bash
export NODE_EXTRA_CA_CERTS="$WL_CA"
electron . --proxy-server=127.0.0.1:9090

The main process is Node, so NODE_EXTRA_CA_CERTS covers it. Renderer traffic goes through Chromium, which takes --proxy-server and trusts roots from the keychain, so install the root there too. Tools ▸ Client Setup ▸ Launch Electron does both.

React Native and Flutter#

  • iOS Simulator shares your Mac's network, so system capture already covers it. Install the root into the simulator: xcrun simctl keychain booted add-root-cert "$WL_CA".
  • Android emulator: the host is 10.0.2.2, and app traffic on Android 7 and later needs a debug network security config. See Capture other devices.
  • Flutter: Dart's HttpClient does not read proxy variables. Set findProxy to PROXY 127.0.0.1:9090 and add the root with SecurityContext.setTrustedCertificates, or install a debug HttpOverrides.global. Tools ▸ Client Setup ▸ Copy Dart override puts one on the pasteboard.

Proving it works#

Every recipe in the app comes with a one-line verify command. Run it and look for the request in the traffic list. If it succeeds but no row appears, the client went direct: the proxy variable was not read.

Something here is unclear, or wrong for your setup? Contact support or write to support@wirelens.app.