- Edited
Happy holidays all,
I ran into some odd behavior with multiple accesses of the `request_id` Nginx variable via the 'ngx.var` API. Consider the following example:
location /orvar {
content_by_lua_block {
ngx.say(ngx.var.request_id)
ngx.say(ngx.var.request_id)
ngx.say(ngx.var.request_id)
}
}
This produces three distinct values:
$ curl localhost:8080/orvar
c57276ee45246776f5b1d868da1c2483
cee11ac0ed7926477302c0406ba7d3d1
21ea6af7fabdc0324d98526ea595a7b8
One would expect these values should be identical. NGX_HTTP_VAR_NOCACHEABLE is not set for this variable: https://github.com/nginx/nginx/blob/746fba0d79c6909e9e09b4d1cb9ddbf052ab545e/src/http/ngx_http_variables.c#L291.
Loading or not loading resty.core has no impact on behavior.
When defining the variable into the config directly via the add_header directive, things work as intuition would lead:
server {
listen 8080;
server_name localhost;
location /orvar {
add_header X-Foo $request_id;
add_header X-Bar $request_id;
content_by_lua_block {
ngx.say(ngx.var.request_id)
ngx.say(ngx.var.request_id)
ngx.say(ngx.var.request_id)
}
}
}
$ curl -vvv localhost:8080/orvar
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /orvar HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: openresty/1.13.6.1
< Date: Fri, 28 Dec 2018 04:32:11 GMT
< Content-Type: application/octet-stream
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Foo: 004c648700ecbe25db8719b1fe0fb2d8
< X-Bar: 004c648700ecbe25db8719b1fe0fb2d8
<
004c648700ecbe25db8719b1fe0fb2d8
004c648700ecbe25db8719b1fe0fb2d8
004c648700ecbe25db8719b1fe0fb2d8
* Connection #0 to host localhost left intact
However, when the headers are added via a lua-nginx-module header_filter handler, we see the same incorrect behavior:
header_filter_by_lua_block {
ngx.header["X-Foo"] = ngx.var.request_id
ngx.header["X-Bar"] = ngx.var.request_id
}
$ curl -vvv localhost:8080/orvar
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /orvar HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: openresty/1.13.6.1
< Date: Fri, 28 Dec 2018 04:36:15 GMT
< Content-Type: application/octet-stream
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Foo: ead844bb511d73552aa60c66d926b583
< X-Bar: 67c36be8692e9ede3f5433811ef80c1b
<
45ef1042902969f5380208b2244e60fe
0f5368da218d33a24040b470ecccbc41
473473815be63b11e616fed52d672163
* Connection #0 to host localhost left intact
This makes me feel like there's an odd implementation within the lua-nginx-module var accesses. From what I can grok, I'm guessing it's because the variable is never indexed (http://lxr.nginx.org/source/src/http/ngx_http_variables.c#0673), so the handler is called for every access from the var metatable. I don't see a good immediate solution for this that doesn't involve declaring the $request_id variable to be defined within the Nginx config itself. Anyone run into this before, with a workaround that doesn't involve some hack like using ngx.ctx?