I’m currently using OpenResty, and one of the things I am trying to do
is
have the backend send a specific header, and if that header is present,
run
a body_filter_by_lua call on the output. However, while I can use the
$upstream_http_* vars for populating (i.e. I can go add_header
SomeHeader
$upstream_http_foo, and if Foo has been sent see SomeHeader: FooVar in
the
output. However, all tests for them seem to break.
Example:
location @backend {
expires off;
proxy_pass http://_varnish;
set $test $upstream_http_csrf; # definitely exists, I
can
see it in the response headers
add_header SomeHeader $upstream_http_csrf; # And I can
read
it, but…
if ($upstream_http_csrf = 1) { # doesn’t matter if it’s
1,
“one” ~* “one”, anything…
# this block never gets called
}
add_header someOtherHeader $test; # Not present in
output as
empty
set_by_lua $use_token
’
if not ngx.var.sent_http_csrf == “” then
return ngx.var.upstream_http_csrf
end
return “baz”
'; # Always return ‘baz’
add_header WIllThisWork $use_token; # Again, empty
}
the same - set_by_lua is executed before a response is available.
Yes, set_by_lua runs at exactly the same phase of the standard
ngx_rewrite module’s “set” directive. Actually set_by_lua is injected
into ngx_rewrite so that it can be mixed with other rewrite module
directives.
@shrikeh: you’re recommended to read my Nginx tutorials to learn more
about the Nginx config directive running order:
On Fri, Feb 01, 2013 at 08:59:38AM -0500, shrikeh wrote:
location @backend {
expires off;
proxy_pass http://_varnish;
set $test $upstream_http_csrf; # definitely exists, I can
see it in the response headers
The “set” directive is rewrite module directive, and it is
executed during the rewrite request processing phase, which
happens before a request is passed to the upstream.
Unless the request was previusly processed using an upstream
server, the $test variable will be empty.
add_header SomeHeader $upstream_http_csrf; # And I can read
it, but…
This will work.
if ($upstream_http_csrf = 1) { # doesn't matter if it's 1,
“one” ~* “one”, anything…
# this block never gets called
}
This won’t, for the same reasons as outlined above - the “if”
directive can’t see upstream response headers as it’s executed
before a response is available.
add_header someOtherHeader $test; # Not present in output as
empty
See above.
set_by_lua $use_token
'
if not ngx.var.sent_http_csrf == "" then
return ngx.var.upstream_http_csrf
end
return "baz"
'; # Always return 'baz'
add_header WIllThisWork $use_token; # Again, empty
I’m not familiar with lua module, but likely the explanation is
the same - set_by_lua is executed before a response is available.
Lua script generates a token, and populates the appropriate tag in
the
body copy with the token.
Token is pushed into user’s cookies and also stored in Redis.
From what I can gather, to do this, I need to:
Add conditional logic within body_filter_by_lua based on the value of
ngx.var.sent_http_csrf
Generate the token
Filter the body.
Make a subrequest with the token to a separate internal location
block so
that Redis can save the token (as redis will be disabled within the
context
of body_filter_by_lua)