Skip to content

CLI HTTP client ignores NO_PROXY, so emulators can’t reach each other behind a proxy #11249

Open

Description

@KKrisu

[REQUIRED] Environment info

firebase-tools: 15.33.0 (also reproduced on 15.32.1)

Platform: Ubuntu 24.04.5 LTS (x86_64), Node.js 24.21.0

[REQUIRED] Test case

When HTTPS_PROXY is set, the CLI's HTTP client (lib/apiv2.js) sends every request through new undici.ProxyAgent({ uri: proxyURI }) and never checks NO_PROXY / no_proxy. Requests between emulators on 127.0.0.1 therefore go to the proxy too. The Functions emulator then can't register Firestore triggers with the Firestore emulator, and emulators:start / emulators:exec fail.

This affects anyone running the emulators behind a corporate or sandbox proxy, even with NO_PROXY=localhost,127.0.0.1. #4637 and #4386 describe similar symptoms on older versions.

Minimal project:

firebase.json

{
  "functions": [{ "source": "functions" }],
  "emulators": {
    "firestore": { "port": 8080 },
    "functions": { "port": 5001 },
    "ui": { "enabled": false },
    "singleProjectMode": true
  }
}

functions/package.json

{
  "name": "functions",
  "main": "index.js",
  "engines": { "node": "24" },
  "dependencies": {
    "firebase-admin": "^14.4.0",
    "firebase-functions": "^7.0.0"
  }
}

functions/index.js

const { onDocumentUpdated } = require('firebase-functions/firestore')

exports.onUserUpdated = onDocumentUpdated('users/{userId}', (event) => {
  console.log('updated', event.params.userId)
})

[REQUIRED] Steps to reproduce

  1. Create the files above and run npm install in functions/.
  2. Point the proxy variables at any proxy that can't reach localhost. A port with nothing listening is enough to reproduce:
    export HTTPS_PROXY=http://127.0.0.1:9
    export NO_PROXY=localhost,127.0.0.1
  3. Run:
    firebase emulators:exec --debug --project demo-repro --only firestore,functions "echo SCRIPT RAN"

[REQUIRED] Expected behavior

Hosts listed in NO_PROXY are connected to directly, as in other Node and CLI tools. The Functions emulator registers the trigger with the local Firestore emulator, and the script runs:

✔  functions[us-central1-onUserUpdated]: firestore function initialized.
i  Running script: echo SCRIPT RAN
SCRIPT RAN
✔  Script exited successfully (code 0)

[REQUIRED] Actual behavior

The request to the local Firestore emulator is sent to the proxy, so trigger registration fails:

>>> [apiv2][query] POST http://127.0.0.1:8080/emulator/v1/projects/demo-repro/eventarcTrigger?eventarcTriggerId=us-central1-onUserUpdated-0 [none]
*** [apiv2] error from fetch(http://127.0.0.1:8080/emulator/v1/projects/demo-repro/eventarcTrigger?eventarcTriggerId=us-central1-onUserUpdated-0, {"headers":{},"method":"POST","dispatcher":{...}}): Error: connect ECONNREFUSED 127.0.0.1:9
⚠  Error adding firestore function: FirebaseError: Failed to make request to http://127.0.0.1:8080/emulator/v1/projects/demo-repro/eventarcTrigger?eventarcTriggerId=us-central1-onUserUpdated-0
Error: Failed to make request to http://127.0.0.1:8080/emulator/v1/projects/demo-repro/eventarcTrigger?eventarcTriggerId=us-central1-onUserUpdated-0

ECONNREFUSED 127.0.0.1:9 is the proxy address, not the emulator. Behind a real proxy that rejects localhost, the proxy's error page comes back instead, and the emulator fails with Unable to parse JSON: SyntaxError: Unexpected token 'r', "request bl"... is not valid JSON.

Suggested fix: in lib/apiv2.js (src/apiv2.ts), use undici's EnvHttpProxyAgent, which applies NO_PROXY, with the same proxy URL:

fetchOptions.dispatcher = new undici.EnvHttpProxyAgent({ httpProxy: proxyURI, httpsProxy: proxyURI });

With only this change, the same repro passes (output under "Expected behavior"). We've used it as a local patch, and our full emulator-based E2E suite passes behind a proxy. undici 6 prints an "EnvHttpProxyAgent is experimental" warning. Happy to open a PR if that approach works for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    ⌂ Proxy