Nginx inject script from remote location

121 views
Skip to first unread message

hende...@gmail.com

unread,
Jun 16, 2015, 6:20:11 AM6/16/15
to openre...@googlegroups.com

In one project, I need to inject a script to some requested page. With the proviso that the script is to be provided from yet another host (currently for test purposes loaded statically from localhost). I decided to use Ngnix + lua as a proxy.

Configuration is very simple:

sites-avaliable/default:

upstream app {
    server main_app:8080;
}

server {
    listen 80 default_server;
    root /usr/share/nginx/html;
    index index.html index.htm;
    server_name localhost;

location / {
  proxy_pass http://app;
}
location /login.html {
  content_by_lua '
  local res_main, res_guard = ngx.location.capture_multi{
    { "/main"..ngx.var.uri, {share_all_vars=true, always_forward_body=true}},
    { "/static/lore_ipsum.txt" }, 
}
  local output = res_main.body 
  output = string.gsub(output, "</head>", res_guard.body.."<!-- Agent JS -->")
  ngx.print(output)
';
}

location /main {
  proxy_pass http://app;
}

Location / works fine, but in /login.html variable res_main always is empty.

The problem probably is in the /main location. I checked in tcpdump and I saw:

  • if proxy_pass is set to http://app request to main_app contains /main/login.html instead of /login.html
  • if proxy_pass is set to http://app/ (with slash at end) request is //login.html

/main/login.html nor //login.html not exist.

Is any way to use proxy_pass from lua? Maybe someone has an idea how else to do something like that?

P.S. Also try body_filter_by_lua but (from lua_nginx docs):

Subrequest API functions (e.g., ngx.location.capture and ngx.location.capture_multi) 
are currently disabled within this context due to 
the limitations in NGINX output filter's current implementation

Yichun Zhang (agentzh)

unread,
Jun 16, 2015, 7:06:21 AM6/16/15
to openresty-en
Hello!

On Tue, Jun 16, 2015 at 6:20 PM, hendersson wrote:
> local res_main, res_guard = ngx.location.capture_multi{
> { "/main"..ngx.var.uri, {share_all_vars=true, always_forward_body=true}},

You know that setting share_all_vars=true is a bad idea?

> Location / works fine, but in /login.html variable res_main always is empty.
> The problem probably is in the /main location. I checked in tcpdump and I
> saw:
> if proxy_pass is set to http://app request to main_app contains
> /main/login.html instead of /login.html

This is the expected behaviour according to your configuration. If you
to strip the /main prefix for the proxy in location /main, then you
need to strip it yourself. Nginx has no way to guess your mind for
that. A simple way is to write (untested)

location /main {
rewrite ^/main '' break;
proxy_pass ...;
}

> if proxy_pass is set to http://app/ (with slash at end) request is
> //login.html
>
> /main/login.html nor //login.html not exist.
>

I cannot parse this question.

> Is any way to use proxy_pass from lua? Maybe someone has an idea how else to
> do something like that?
>

See above. Maybe you should check out the nginx tutorials first:

https://openresty.org/#eBooks

> P.S. Also try body_filter_by_lua but (from lua_nginx docs):
>
> Subrequest API functions (e.g., ngx.location.capture and
> ngx.location.capture_multi)
> are currently disabled within this context due to
> the limitations in NGINX output filter's current implementation
>

Yes, this is a limitation in the nginx core.

Regards,
-agentzh

hende...@gmail.com

unread,
Jun 17, 2015, 1:38:58 PM6/17/15
to openre...@googlegroups.com
W dniu wtorek, 16 czerwca 2015 13:06:21 UTC+2 użytkownik agentzh napisał:
 
This is the expected behaviour according to your configuration. If you
to strip the /main prefix for the proxy in location /main, then you
need to strip it yourself. Nginx has no way to guess your mind for
that. A simple way is to write (untested)

    location /main {
        rewrite ^/main '' break;
        proxy_pass ...;
    }

Thank you very much for your reply. I've tried to "rewrite" but without  "break" option (i don't know how i miss it), which did not give proper effect.
Current version:

  location /main {
     rewrite ^/main(.*) $1 break;
     proxy_pass http://app;
  }

Works fine.
 
Thank you once more and Best Regards
Bart
Reply all
Reply to author
Forward
0 new messages