Forum: NGINX $upstream_http_* variables exist but do not seem to be readable

Posted by shrikeh (Guest)
on 2013-02-01 15:00
(Received via mailing list)
Hi,

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
}

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,235808,235808#msg-235808
Posted by Maxim Dounin (Guest)
on 2013-02-01 15:48
(Received via mailing list)
Hello!

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.

--
Maxim Dounin
http://nginx.com/support.html
Posted by agentzh (Guest)
on 2013-02-01 21:26
(Received via mailing list)
Hello!

On Fri, Feb 1, 2013 at 6:48 AM, Maxim Dounin wrote:
> 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:

    http://openresty.org/#eBooks

Best regards,
-agentzh
Posted by shrikeh (Guest)
on 2013-02-04 12:10
(Received via mailing list)
Here is what I'm trying to achieve:

1. Backend sends response header saying "this page requires filtering".
2. Lua script generates a token, and populates the appropriate tag in 
the
body copy with the token.
3. Token is pushed into user's cookies and also stored in Redis.

From what I can gather, to do this, I need to:

1. Add conditional logic within body_filter_by_lua based on the value of
ngx.var.sent_http_csrf
2. Generate the token
3. Filter the body.
4. 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)

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,235808,235881#msg-235881
Posted by shrikeh (Guest)
on 2013-02-04 13:47
(Received via mailing list)
Hi!

Thanks for the responses. Is there any way for nginx to work 
conditionally
based on headers in the upstream response?

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,235808,235878#msg-235878
Posted by shrikeh (Guest)
on 2013-02-08 17:57
(Received via mailing list)
I resolved this issue, the result is in this gist should anyone wish to 
use
it: https://gist.github.com/shrikeh/4722427

Thanks.

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,235808,236023#msg-236023
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.