Skip to content

Avoid variable name conflicts in complex routing rules implementation #1789

Open
@pleshakov

Description

@pleshakov

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    backlogCurrently unprioritized work. May change with user feedback or as the product progresses.tech-debtShort-term pain, long-term benefit

    Type

    No type

    Projects

    Status

    🆕 New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions