> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codezero.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Compatibility

> Which HTTP clients and AI SDKs work with cordon out of the box, and how to configure the ones that don't.

Cordon works transparently with any HTTP client that respects the `HTTPS_PROXY` / `HTTP_PROXY` environment variables. Some languages and SDKs use custom HTTP implementations or different proxy mechanisms that need additional configuration.

## Compatibility matrix

| Language / Runtime | SDK / Library    | Works with env vars? | Workaround                                                                              |
| ------------------ | ---------------- | -------------------- | --------------------------------------------------------------------------------------- |
| CLI                | `curl`           | Partial              | HTTP: only lowercase `http_proxy`. HTTPS: both cases work. (see below)                  |
| CLI                | `wget`           | Partial              | Only reads lowercase `http_proxy` and `https_proxy` (see below)                         |
| Go                 | `net/http`       | Yes                  | None needed                                                                             |
| Rust               | `reqwest`        | Yes                  | None needed                                                                             |
| Python             | `requests`       | Yes                  | None needed                                                                             |
| Python             | `httpx`          | Yes                  | None needed                                                                             |
| Python             | `urllib`         | Yes                  | None needed                                                                             |
| Ruby               | `net/http`       | Partial              | HTTP: prefers lowercase `http_proxy`. HTTPS: **not supported** via env vars (see below) |
| C# / .NET          | `HttpClient`     | Yes                  | None needed                                                                             |
| Java               | `java.net.http`  | No                   | JVM proxy properties and Java trust configuration (see below)                           |
| PHP                | `curl_init()`    | Partial              | HTTP: only lowercase `http_proxy`. HTTPS: both cases work. (see below)                  |
| PHP                | Guzzle           | Yes (CLI only)       | Reads uppercase `HTTP_PROXY` in CLI mode                                                |
| Node.js            | `undici.fetch()` | Yes (with register)  | `--import @codezero-io/cordon/register` plus `NODE_EXTRA_CA_CERTS`                      |
| Node.js            | built-in `fetch` | Yes (with register)  | `--import @codezero-io/cordon/register` plus `NODE_EXTRA_CA_CERTS`                      |
| Node.js            | `node-fetch`     | No                   | Use `http-proxy-agent` package                                                          |
| Node.js            | `axios`          | Yes (with helper)    | `@codezero-io/cordon/axios`                                                             |
| Node.js            | `got`            | Yes                  | Respects env vars natively                                                              |

## Runtime CA and proxy notes

Use [`cordon env`](/cli/env) for the standard env vars and certificate paths. The notes below only cover runtimes with special proxy or trust-store behavior.

### curl

The `curl` CLI uses libcurl, which deliberately ignores uppercase `HTTP_PROXY` as a security measure against the [httpoxy vulnerability](https://httpoxy.org/) (CVE-2016-5385) — only lowercase `http_proxy` is read. For **HTTPS** requests, both `HTTPS_PROXY` and `https_proxy` are accepted (the httpoxy attack vector does not apply to HTTPS).

### wget

`wget` has its own HTTP implementation (it does **not** use libcurl). It only reads **lowercase** environment variables for both protocols: `http_proxy` and `https_proxy`. Uppercase variants (`HTTP_PROXY`, `HTTPS_PROXY`) are ignored entirely.

<Warning>
  `cordon setup` sets both uppercase and lowercase proxy variables automatically. If you configure the proxy manually, make sure to set lowercase `http_proxy` and `https_proxy` in addition to their uppercase counterparts.
</Warning>

### Java

Java's built-in `java.net.http.HttpClient` does **not** read `HTTP_PROXY` or `HTTPS_PROXY` environment variables. Instead, it uses JVM system properties:

```bash theme={null}
java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=6790 \
     -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=6790 \
     -jar your-app.jar
```

Java also uses its own trust configuration. If HTTPS requests fail with certificate errors, import the Cordon CA into the JVM trust store or point the JVM at an application-specific trust store:

```bash theme={null}
keytool -importcert -alias cordon \
  -file /path/to/ca-cert.pem \
  -keystore "$JAVA_HOME/lib/security/cacerts" \
  -storepass changeit -noprompt
```

Use the `ca-cert.pem` path from `cordon env` or your generated `cordon.toml`.

### Node runtime

Node.js does not use the system trust store, and built-in `fetch` does not read proxy env vars by default. Use both pieces:

```bash theme={null}
NODE_EXTRA_CA_CERTS="/path/to/ca-cert.pem" \
NODE_OPTIONS="--import @codezero-io/cordon/register" \
node your-app.js
```

`NODE_EXTRA_CA_CERTS` points to the raw Cordon CA cert, not `combined-ca.pem`. The register import is described in [Node register import](#node-register-import).

### PHP

PHP's `curl_init()` uses libcurl. For **HTTP** requests, it deliberately ignores uppercase `HTTP_PROXY` as a security measure against the [httpoxy vulnerability](https://httpoxy.org/) (CVE-2016-5385) — only lowercase `http_proxy` is read. For **HTTPS** requests, both `HTTPS_PROXY` and `https_proxy` are accepted.

[Guzzle](https://docs.guzzlephp.org/) (the most popular PHP HTTP client) handles this differently — it reads uppercase `HTTP_PROXY` at the application layer and explicitly sets `CURLOPT_PROXY`, but **only in CLI mode** (`PHP_SAPI === 'cli'`). In web/CGI contexts, Guzzle ignores `HTTP_PROXY` for the same httpoxy security reasons.

<Warning>
  For HTTP traffic: set **both** `HTTP_PROXY` and `http_proxy` to cover raw PHP curl and Guzzle. For HTTPS traffic: `HTTPS_PROXY` works for both raw curl and Guzzle.
</Warning>

### Ruby

Ruby's `net/http` only supports proxy env vars for **HTTP** requests. It prefers the lowercase form `http_proxy` and will warn when uppercase `HTTP_PROXY` is used:

```
warning: The environment variable HTTP_PROXY is discouraged. Use http_proxy.
```

For **HTTPS** requests, Ruby's `net/http` does **not** automatically read `HTTPS_PROXY` or `https_proxy` from the environment. HTTPS proxy support requires explicit configuration in code:

```ruby theme={null}
proxy_uri = URI.parse(ENV['HTTPS_PROXY'])
Net::HTTP.new(uri.host, uri.port, proxy_uri.host, proxy_uri.port).start do |http|
  http.use_ssl = true
  response = http.request(Net::HTTP::Get.new(uri))
end
```

<Warning>
  Ruby applications making HTTPS requests will **not** route through the proxy via environment variables alone. This may require code changes in Ruby applications that need HTTPS proxy support.
</Warning>

## Streaming support

Cordon streams response bodies through without buffering, so SSE (Server-Sent Events) and chunked transfer encoding responses work correctly. This is critical for AI API integrations that use `stream: true` — tokens are forwarded to the client as they arrive from the upstream API, with no added latency.

## AI / LLM SDKs

The major AI SDKs use custom `fetch` implementations and do **not** respect `HTTPS_PROXY` env vars or undici's global dispatcher on their own. However, `@codezero-io/cordon/register` patches `globalThis.fetch` to inject a proxy dispatcher transparently — no code changes needed.

### Automatic (recommended)

Use the [Node register import](#node-register-import). It works for the Anthropic SDK, OpenAI SDK, and any other library that uses `globalThis.fetch` internally. For TLS interception, also set `NODE_EXTRA_CA_CERTS` as described in [Node runtime](#node-runtime).

### Manual (if register import is not an option)

Both the Anthropic and OpenAI SDKs support explicit proxy configuration via `fetchOptions.dispatcher`:

```typescript theme={null}
import Anthropic from '@anthropic-ai/sdk';
import * as undici from 'undici';

const client = new Anthropic({
  fetchOptions: {
    dispatcher: new undici.ProxyAgent('http://127.0.0.1:6790'),
  },
});
```

```typescript theme={null}
import OpenAI from 'openai';
import * as undici from 'undici';

const client = new OpenAI({
  fetchOptions: {
    dispatcher: new undici.ProxyAgent('http://127.0.0.1:6790'),
  },
});
```

<Note>
  Both the Anthropic and OpenAI SDKs are generated by [Stainless](https://www.stainlessapi.com/), which acquires `globalThis.fetch` at client constructor time. Any other Stainless-generated SDK (e.g., Cloudflare, Lithic, Modern Treasury) will work the same way with `@codezero-io/cordon/register` — no code changes needed.
</Note>

### Other AI SDKs

| SDK                  | Status         |
| -------------------- | -------------- |
| Vercel AI SDK        | Not yet tested |
| LangChain.js         | Not yet tested |
| Google Generative AI | Not yet tested |
| AWS Bedrock          | Not yet tested |
| Cohere               | Not yet tested |
| Mistral              | Not yet tested |

<Info>
  We're actively testing more SDKs. If you've tested one not listed here, let us know so we can add it.
</Info>

## Node register import

The `@codezero-io/cordon/register` import patches `globalThis.fetch` to inject a proxy dispatcher into all outbound requests. It also sets undici's global dispatcher for code that uses `undici.fetch()` directly.

If you use the bare `@codezero-io/cordon/register` specifier, `@codezero-io/cordon` must be installed in the project/current working directory that launches Node. A global npm install is not automatically visible to Node's package resolution. Integration setup commands such as `cordon setup claude-code` avoid this by writing an absolute `register.mjs` path when the npm-installed package is discoverable.

```bash theme={null}
node --import @codezero-io/cordon/register your-app.js
```

Or via `NODE_OPTIONS`:

```bash theme={null}
NODE_OPTIONS="--import @codezero-io/cordon/register" npm run dev
```

Or as a direct import in your entry file (must be the first import):

```js theme={null}
import '@codezero-io/cordon/register';
```

This works for applications using `globalThis.fetch`, `undici.fetch()`, and fetch-based SDKs like Anthropic and OpenAI. Libraries with their own HTTP stack still need their own integration path: axios has `@codezero-io/cordon/axios`, while clients like `node-fetch` still require explicit proxy-agent configuration.
