Setting a custom header on a proxied request

Maxime Henrion mhenrion at
Wed Oct 14 16:56:35 UTC 2015

Hello Maxim!

Thank you again for your answer.

I have read more about the upstream code as well as the the proxy module code, and now realize that headers are being serialized into a buffer a chain within the create_request callback, and that peer selection can happen after that.

I cannot however use proxy_set_header in this particular case, as I have no variable to use that would expand to the desired value (the actual IP address of the peer currently being contacted). To the best of my knowledge, the $upstream_addr variable is closest to what I need, except that it contains all the upstream addresses that were contacted during request processing.

Would you have any idea on how best to approach this problem? I was considering implementing a full-blown upstream module, but I have no evidence that the way the ngx_http_upstream.c code works is compatible with a scheme where headers would potentially need to be changed each time we select a new peer.

Thanks in advance,

From: nginx-devel [nginx-devel-bounces at] on behalf of Maxim Dounin [mdounin at]
Sent: Wednesday, October 14, 2015 6:32 PM
To: nginx-devel at
Subject: Re: Setting a custom header on a proxied request


On Mon, Oct 12, 2015 at 02:12:47PM +0000, Maxime Henrion wrote:

> Hi all,
> I'm currently writing an nginx module that sends a number of
> subrequests to upstream servers based on application logic, and
> then aggregates the results and send them back. That part
> currently works just fine, thanks to the help I was given here
> in the past.
> However, I am now trying to add a custom header to the request
> that is being proxied and currently failing at it. For various
> technical reasons, I need to add a header that contains the IP
> address and port (from the point of view of nginx) of the
> upstream server currently being contacted. In order to get at
> that address, I have hooked my module into the peer selection
> mechanism, much like the keepalive, ip_hash modules and others
> do. So far so good, I get at that address and can log it just
> fine. However, I can't seem to be able to add it as a header to
> my request.


>         h = ngx_list_push(&r->headers_in.headers);
>         if (h == NULL) {
>                 return NGX_ERROR;
>         }
>         h->hash = 1;
>         ngx_str_set(&h->key, "X-Shard-Addr");
>         h-> = ngx_pstrdup(r->pool, &peeraddr);
>         if (h-> == NULL) {
>                 return NGX_ERROR;
>         }
>         h->value.len = peeraddr.len;
>         return NGX_OK;
> }
> So after getting at the actual address we're forwarding our
> request to, I try to add a custom header to r->headers_in, on
> the request object that I saved in my peer data.
> I suspect I'm not actually dealing with the correct request
> here, because no matter what I try, I can't get this code to
> actually alter the headers of the forwarded request in any way.

What you are trying to do is wrong.  You shouldn't modify original
request headers - they are expected to be from original request,
and arbitrary modifications will cause problems with later
processing.  Instead, consider using the proxy_set_header
directive ( to add headers to
requests to upstream servers.

Additionally, this is not going to work as you are doing it too
late.  You are trying to add headers from balancing function, but
balancing happens when a request to upstream is already created.
(And re-balancing due to proxy_next_upstream may select a
different upstream server for the same request.)

Maxim Dounin

nginx-devel mailing list
nginx-devel at

More information about the nginx-devel mailing list