Nginx map directive only matching default

6,706

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 {
Share:
6,706

Related videos on Youtube

Paul Murray
Author by

Paul Murray

Updated on September 18, 2022

Comments

  • Paul Murray
    Paul Murray almost 2 years

    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.

  • Paul Murray
    Paul Murray over 6 years
    Yep, this was it. I was even correctly referencing the variable in my log format directive and didn't notice they were different. Thanks!