119

I am using nginx as a reverse proxy and trying to read a custom header from the response of an upstream server (Apache) without success. The Apache response is the following:

HTTP/1.0 200 OK
Date: Fri, 14 Sep 2012 20:18:29 GMT 
Server: Apache/2.2.17 (Ubuntu)
X-Powered-By: PHP/5.3.5-1ubuntu7.10
Connection: close
Content-Type: application/json; charset=UTF-8
My-custom-header: 1

I want to read the value from My-custom-header and use it in a if clause:

location / {
    // ...
    // get My-custom-header value here
    // ...
}

Is this possible?

4 Answers 4

111

It's not only possible, it's easy:

in nginx the response header values are available through a variable (one per header). See https://nginx.org/r/$sent_http_ for the details on those variables.

In your examle the variable would be $sent_http_My_custom_header.

Sign up to request clarification or add additional context in comments.

5 Comments

As it turns out, this isn't correct either. OP asked to read the value for a response header. You should use $sent_http_my_custom_header. nginx.org/en/docs/http/ngx_http_core_module.html#var_sent_http_
check @dev-gosain answer below if you need upstream response header
the answer is wrong. The person asking is trying to access the header from upstream server. Correct answer is stackoverflow.com/a/30879181/111995
This answer was made more wrong by an edit in 2015, where $sent_http_ was replaced by $http_. I've reverted that edit now. The answer is still incorrect. $sent_http_name is a client response header, sent from NGINX to the client. The OP is asking for upstream response headers, the entries in the response from the upstream server back to NGINX. The difference between the two matters as some headers are not forwarded from upstream to client. Also, you can't use response header variables in an if condition.
For me it works to use $upstream_http_custom_header
91

When using NGINX as a proxy, there are four sets of headers:

  • client -> nginx: the client request headers
  • nginx -> upstream: the upstream request headers
  • upstream -> nginx: the upstream response headers
  • nginx -> client: the client response headers

You appear to be asking about the upstream response headers. Those are found in the $upstream_http_name variables.

However, take into account that any response headers are only set after the headers from the upstream server response have been received. Any if directives are run before sending the upstream request, and will not have access to any response headers! In other words, if directives are run after the client request has been received, before making the upstream request.

If you need to change how a response is handled, you can use a map directive however to set variables based on response headers, then use those variables in add_header (set client response headers), log_format or any othere directives that are active during the response phases (internally named the NGX_HTTP_CONTENT_PHASE and NGX_HTTP_LOG_PHASE phases). For more complex control you'll have to use a scripting add-on such as the Lua module (e.g. using a header_filter_by_lua_block directive).

To read or set individual headers, use:

from to type read (variable) write (directive)
client nginx request $http_name
ngnix upstream request proxy_set_header
upstream nginx response $upstream_http_name
nginx client response $sent_http_name add_header

NGINX copies certain headers from client request to upstream request, and from upstream response to client response using various proxy_ directives, giving you options to omit or explicitly include headers for either direction. So if an upstream response header is only found in $upstream_http_name variables, then those headers were specifically not copied to the client response, and the set of available $sent_http_name variables will include any extra headers set by NGINX that are not present in the upstream response.

2 Comments

Thank you! This is a great answer. That table alone is so informative. I wish this was laid out clearly in the nginx docs in a similar format. Would love to get bashed in the comments with people linking to the docs where this table is clearly presented
@zayquan: I created that table after I had to carefully piece together my own understanding of what all the different header collections are and what can be done to what. I certainly never found something similar in the NGINX docs.
65

I was facing the same issue. I tried both $http_my_custom_header and $sent_http_my_custom_header but it did not work for me.

Although solved this issue by using $upstream_http_my_custom_header.

1 Comment

The appropriate variable $upstream_http_name pattern is documented here: nginx.org/en/docs/http/ngx_http_upstream_module.html#variables
12

Use $http_MY_CUSTOM_HEADER

You can write some-thing like

set my_header $http_MY_CUSTOM_HEADER;
if($my_header != 'some-value') {
#do some thing;
}

1 Comment

man says - the last part of a variable name is the field name converted to lower case with dashes replaced by underscores.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.