Skip to content

proxy: allow setting dynamic headers at intercept time#2881

Open
phlip9 wants to merge 1 commit intoseanmonstar:masterfrom
phlip9:proxy-intercept-time-auth
Open

proxy: allow setting dynamic headers at intercept time#2881
phlip9 wants to merge 1 commit intoseanmonstar:masterfrom
phlip9:proxy-intercept-time-auth

Conversation

@phlip9
Copy link

@phlip9 phlip9 commented Dec 9, 2025

My main use case here is to set a short-lived Proxy-Authorization Bearer auth token and dynamic trace id on a proxy connection.

To support this, the callback in Proxy::custom needs to be able to return auth/headers alongside a Url.

I've packaged the auth/headers as ProxyExtra (formerly Extra), which is now part of the public API.

Preserving backwards compat needed some minor trait contortions. Technically there's a new Sized trait bound on IntoProxy, but this should be OK, since I'm not sure how you would impl the trait for an unsized type anyway. Existing callers should not need to change anything.

We've been running a (hacky) version of this patch for ~2 years. I just finally got around to cleaning this up so it's suitable for upstreaming : )

To support this, I need the callback in `Proxy::custom` to be able to
return auth/headers alongside a `Url`.

I've packaged the auth/headers as `ProxyExtra` (formerly `Extra`), which
is now part of the public API.

Preserving backwards compat needed some minor trait contortions.
Technically there's a new `Sized` trait bound on `IntoProxy`, but this
_should_ be OK, since I'm not sure how you would impl the trait for an
unsized type anyway.
@seanmonstar
Copy link
Owner

Thanks for the PR! I'm curious about your use case, would you need it to be something that runs with custom, or would it be better if you could configure details on the RequestBuilder? (The meta one is #2641, but people have asked about proxy specifically.)

@phlip9
Copy link
Author

phlip9 commented Dec 9, 2025

Sure, you can see how we're using an older version here: https://github.com/lexe-app/lexe-public/blob/master/app-rs/src/client.rs#L300

The Proxy::custom callback picks up the most recent Bearer auth token that it needs to send to the proxy.

Before making a request, you call self.ensure_authed().await? to ensure you have an unexpired token:

impl Client {
    async fn node_info(&self) -> Result<NodeInfo, NodeApiError> {
        self.ensure_authed().await?;
        let run_url = &self.run_url;
        let url = format!("{run_url}/app/node_info");
        let req = self.run_rest.get(url, &Empty {});
        self.run_rest.send(req).await
    }
}

A per-request proxy config might also work (as long as the connection pooling continues to work):

impl Client {
    async fn node_info(&self) -> Result<NodeInfo, NodeApiError> {
        let url = format!("{run_url}/app/node_info");
        let token = self.ensure_authed().await?;
        let proxy = Proxy::all(self.gateway_url).custom_http_auth(token)?;
        let req = self
            .run_rest
            .get(url, &Empty {})
            .proxy(proxy);
        self.run_rest.send(req).await
    }
}

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.

2 participants