Nginx map directive only matching default

Paul Murray asked:

I’m using Nginx’s map directive to route users to either stable or beta servers depending on the value of a custom http header. However, Nginx will only match to the default value, even when I’ve confirmed that the header is ‘TEST’.

worker_processes  2;

events {
    worker_connections  1024;
}


http {
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" "$http_x_cp_client_class" $upstream';

access_log  logs/access.log  main;

upstream dataserver_stable {
    server localhost:8081;
}

upstream dataserver_beta {
    server localhost:8082 fail_timeout=1m;
}

map $http_x-cp-client-class $upstream {
    TEST "dataserver_beta";
    # STABLE "dataserver_stable"; technically redundant I think
    default "dataserver_stable";
}

server {
    listen       81;
    server_name  localhost;

    location / {
            proxy_set_header Host $host;
            add_header My-Upstream $upstream;

            proxy_pass       http://$upstream;
            proxy_connect_timeout 5s;
            proxy_read_timeout 10s;
    }
}
}

Headers:

Req:

GET /pages/widgets/calendar/tradeDateCalendar.tpl.html HTTP/1.1
Host: ny7wlpmurray:81
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
X-CP-Client-Class: TEST
Referer: http://ny7wlpmurray:81/pages/dashboard/dashboard.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: _ga=GA1.1.1629631386.1511812518; _gid=GA1.1.892280347.1511812518

Res:

HTTP/1.1 200
Server: nginx/1.12.2
Date: Wed, 29 Nov 2017 21:33:54 GMT
Content-Type: text/html
Content-Length: 594
Connection: keep-alive
Accept-Ranges: bytes
ETag: W/"594-1511969617175"
Last-Modified: Wed, 29 Nov 2017 15:33:37 GMT
My-Upstream: dataserver_stable

Have I written something wrong? I’ve tried TEST, ~TEST, “TEST”, and “~TEST”, none of which worked.

My answer:


When converting HTTP request headers to variable names, nginx will convert hyphens to underscores. Thus, a variable representing the X-CP-Client-Class header will be $http_x_cp_client_class.

This suggests that your map should be declared as follows:

map $http_x_cp_client_class $upstream {

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.