1

I have a perl catalyst application that i'm mounting on a specific url (vs mounting on a subdomain) and am having problems setting SCRIPT_NAME on the request to the backend. This affects the urls generated by the application. It needs to know where it is mounted so that it can properly generate the urls.

So my chain is:

request => [ nginx, proxy_pass ] => [ starman:5000 ] => [ perl_app ]

When proxy_pass sends the request to starman, i'm expecting it to set SCRIPT_NAME. If I were using fastcgi, i would do fastcgi_param SCRIPT_NAME something or use fastcgi_split_path_info. At this point I'm ready to just flip over to fastcgi but i'm stubborn and want to figure out if this is possible. I've attempted to set fastcgi_params anyway just to see if it would affect the SCRIPT_NAME sent with proxy_pass but it doesn't as far as I can tell.

my nginx server config:

server {
  #listen   80; ## listen for ipv4; this line is default and implied
  #listen   [::]:80 default ipv6only=on; ## listen for ipv6

  root /usr/share/nginx/default;
  index index.html;

  server_name www.example.com example.com;
  listen 80 default_server;
  listen 443 ssl;
  ssl_certificate     certs/cert.pem;
  ssl_certificate_key certs/key.pem;
  ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers         HIGH:!aNULL:!MD5;

  location / {
    # First attempt to serve request as file, then
    # as directory, then fall back to index.html
    try_files $uri $uri/ =404;
  }

  location /ff/ {
    if ( $https = "off" ) {
      return 302 https://$server_name$request_uri;
    }

    #fastcgi_split_path_info (.*)(.*);
    #include fastcgi_params;
    #fastcgi_param PATH_INFO /blah;
    #fastcgi_param SCRIPT_NAME /test;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Port $server_port;
    #fastcgi_pass localhost:5000;
    proxy_pass  http://localhost:5000/;
  }

  error_page 404 /errors/404.html;
  error_page 500 502 503 504 /errors/50x.html;
}

So the application is on example.com/ff and the should redirect to example.com/ff/login if you try to go to example.com/ff/home without being logged in. Instead when you make a request to example.com/ff/home PATH_INFO is set to /home (as expected) and SCRIPT_NAME is '', so the application generates a redirect to example.com/home instead of example.com/ff/home

As far as I have found, my only solutions are:

  • use fastcgi
  • do something in the catalyst app to let it know where it is mounted (like read a http request header to know where it is mounted and then the uri generation code can create proper path)

Thanks for any insight.

mikew
  • 121
  • 1
  • 3
  • 1
    It seems to me inside `location ff { }` you just need to do the `rewrite ^/ff/(.+) /$1 break` in order to have correct URL. Would that help? Also you can go straight and use `proxy_set_header SCRIPT_NAME /test`. – Glueon Oct 12 '14 at 09:16
  • Why aren't you using FastCGI? – Michael Hampton Oct 12 '14 at 12:55
  • @Glueon the apps downstream of nginx still won't know what url they are mounted under and will generate the incorrect urls. When they generate incorrect urls, (i.e. without /ff/ in the path) then they will no longer match the /ff/ location and will not be sent to the app. I could proxy_set_header but that means the parameter will be HTTP_SCRIPT_NAME per CGI specs. – mikew Oct 12 '14 at 16:26
  • @MichaelHampton Just because this is how I set it up when I was using apache in a different env. Was learning nginx and was confounded and then i get stubborn. Given that django has specific code to handle this (being behind nginx) it seems the solutions I've outlined in the question are the only two. I guess I'll learn fastcgi now and change up my architecture :) – mikew Oct 12 '14 at 16:29

1 Answers1

0

The burden does not lie with nginx. Proxy or FastCGI both pass information over a socket, that gets interpreted. FastCGI is not that much different, except there's a contract that specifies how information that is to be put in the CGI application is to be transmitted and processed. The SCRIPT_NAME is one of them.

If you wish to stick to proxy you need to teach starman hoe interpret certain headers and tell nginx to set them using proxy_set_header.