Skip to content

oauthex: build defaultDiscoveryTransport lazily instead of at import - #1278

Open
kilarusravankumar wants to merge 1 commit into
modelcontextprotocol:mainfrom
kilarusravankumar:fix/1276-oauthex-proxy-init-cache
Open

kilarusravankumar wants to merge 1 commit into
modelcontextprotocol:mainfrom
kilarusravankumar:fix/1276-oauthex-proxy-init-cache

Conversation

@kilarusravankumar

@kilarusravankumar kilarusravankumar commented Sep 17, 2026

Copy link
Copy Markdown

Fixes #1276

What's happening

oauthex builds defaultDiscoveryTransport as a package-level var, so it
runs at import time. That path calls proxyConfigured, which invokes
http.DefaultTransport's proxy func (http.ProxyFromEnvironment). net/http
reads the proxy env vars only once and caches the result, so this import-time
call freezes the proxy config before main() can set HTTPS_PROXY.

New in v1.8.0, which is why it's a regression — just importing .../mcp
(which pulls in oauthex) triggers it, even with no use of the SDK.

Fix

Wrap the setup in sync.OnceValue so it runs on first use instead of at
import. Still built once and reused.

Testing (removed)

  • Ran the issue's repro against this branch via a local replace: prints
    proxy=http://127.0.0.1:9 now, proxy=<nil> before.
  • Added a regression test in oauthex.
  • go test ./... passes.

Comment thread oauthex/oauth2_test.go Outdated
Comment on lines +8 to +15
func TestImportDoesNotCacheProxyEnv(t *testing.T) {
t.Setenv("HTTPS_PROXY", "http://127.0.0.1:9")
req, _ := http.NewRequest(http.MethodGet, "https://example.com/", nil)
got, err := http.ProxyFromEnvironment(req)
if err != nil || got == nil {
t.Fatalf("proxy not detected: got=%v err=%v", got, err)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test fails when is not run in isolation

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's it — another discovery test calls newDiscoveryClient which calls defaultDiscoveryTransport() before my test, so ProxyFromEnvironment is already cached by the time my t.Setenv runs. It only passed because I ran it alone.

I'll drop the test. Since that proxy env is read once per process, any test I write here is at the mercy of whatever runs first, so it's not reliable. The change itself is small and the fix is clear.

is that okay ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's drop the test, but leave a comment explaining why OnceValue is used, thanks for the fix!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure @yarolegovich , done

@kilarusravankumar
kilarusravankumar force-pushed the fix/1276-oauthex-proxy-init-cache branch from c3f15f4 to 0206f96 Compare September 17, 2026 20:11
defaultDiscoveryTransport was a package-level var, so it got built the
moment the package was imported. Building it runs proxyConfigured, which
calls http.DefaultTransport's proxy func (that's http.ProxyFromEnvironment).

The problem is net/http only reads the proxy env vars once and caches the
result forever. So the first call wins, and here that first call happens at
import time, before main() has had a chance to set HTTPS_PROXY. By the time
the app sets it, it's already too late and the setting gets ignored.

You didn't hit this in v1.7.0 because this code didn't exist yet. Just
importing .../mcp pulls in oauthex, which was enough to trigger it even if
you never called anything in the SDK.

Fixing it by wrapping the setup in sync.OnceValue so it runs on first use
instead of at import. By then the app has set its proxy env. It's still only
built once and reused, same as before.

Fixes modelcontextprotocol#1276
@kilarusravankumar
kilarusravankumar force-pushed the fix/1276-oauthex-proxy-init-cache branch from 0206f96 to 76675f5 Compare September 17, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression: v1.8.0 import initializes Go HTTP proxy env cache before app startup

3 participants