nginx-gateway-fabric icon indicating copy to clipboard operation
nginx-gateway-fabric copied to clipboard

Avoid variable name conflicts in complex routing rules implementation

Open pleshakov opened this issue 1 year ago • 1 comments
trafficstars

To implement complex routing rules like https://github.com/nginxinc/nginx-gateway-fabric/blob/03e24fed91d9a39a626bdfaa83108a89824a3d6e/examples/advanced-routing/cafe-routes.yaml#L18-L30 , we use njs, where we encode the routing rule into a variable $http_matches to pass it to njs code for further processing.

    location @rule0-route0 {
        proxy_set_header Host "$gw_api_compliant_host";
        proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
        proxy_set_header Upgrade "$http_upgrade";
        proxy_set_header Connection "$connection_upgrade";
        proxy_http_version 1.1;
        proxy_pass http://default_coffee-v2-svc_80$request_uri;
    }

    location @rule0-route1 {
        proxy_set_header Host "$gw_api_compliant_host";
        proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
        proxy_set_header Upgrade "$http_upgrade";
        proxy_set_header Connection "$connection_upgrade";
        proxy_http_version 1.1;
        proxy_pass http://default_coffee-v1-svc_80$request_uri;
    }

    location /coffee/ {
        set $http_matches "[{\"redirectPath\":\"@rule0-route0\",\"params\":[\"matches=v2\"]},{\"redirectPath\":\"@rule0-route1\",\"any\":true}]";
        js_content httpmatches.redirect;
    }

    location = /coffee {
        set $http_matches "[{\"redirectPath\":\"@rule0-route0\",\"params\":[\"matches=v2\"]},{\"redirectPath\":\"@rule0-route1\",\"any\":true}]";
        js_content httpmatches.redirect;
    }

Unfortunately, $http_ variable is a built-in variable used to look up headers - https://nginx.org/en/docs/http/ngx_http_core_module.html#var_http_` , which can override the original header value and create problems.

Note: right now, it doesn't cause any problems - because njs code gets access to headers separately through r.headersIn https://github.com/nginxinc/nginx-gateway-fabric/blob/03e24fed91d9a39a626bdfaa83108a89824a3d6e/internal/mode/static/nginx/modules/src/httpmatches.js#L109

However, when we implement configurable access logging or start using NGINX variables in other places, it can create problems, if users uses the request header with the name matches.

For example, consider the following NGINX configurations and curl requests:

server {
    listen 80;
    set $http_matches "my-value";
    return 200 "$http_matches\n";
}
curl localhost -H "matches: 123"
my-value
server {
    listen 80;
    #set $http_matches "my-value";
    return 200 "$http_matches\n";
}
curl localhost -H "matches: 123"
123

pleshakov avatar Mar 29 '24 20:03 pleshakov

This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 14 days.

github-actions[bot] avatar Apr 13 '24 02:04 github-actions[bot]