Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nginx redirect to an external URL

What I'm trying to do is route all requests to /rdr/extern_url to redirect to extern_url through my web server instead of doing it through PHP.

location /rdr {
    rewrite ^/rdr/(.*)$ $1 permanent;
}

What's wrong here is it if I access http://localhost/rdr/http://google.com my browser is telling me:

Error 310 (net::ERR_TOO_MANY_REDIRECTS): There were too many redirects.

How do I redirect properly?

like image 498
Jürgen Paul Avatar asked Aug 05 '12 06:08

Jürgen Paul


1 Answers

Trivial check:

$ curl -si 'http://localhost/rdr/http://www.google.com' | head -8
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.0
Date: Sun, 05 Aug 2012 09:33:14 GMT
Content-Type: text/html
Content-Length: 184
Connection: keep-alive
Location: http:/www.google.com

As you can see, there is only one slash after scheme in Location.

After adding the following directive to server:

merge_slashes off;

We'll get the correct reply:

$ curl -si 'http://localhost/rdr/http://www.google.com' | head -8
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.0
Date: Sun, 05 Aug 2012 09:36:56 GMT
Content-Type: text/html
Content-Length: 184
Connection: keep-alive
Location: http://www.google.com

It becomes clear from the comments you may want to pass hostname without the schema to your redirecting service. To solve this problem you need to define two locations to process both cases separately:

server {
  listen 80;
  server_name localhost;
  merge_slashes off;

  location /rdr {
    location /rdr/http:// {
      rewrite ^/rdr/(.*)$ $1 permanent;
    }
    rewrite ^/rdr/(.*)$ http://$1 permanent;
  }
}

Here I've defined /rdr/http:// as a sub-location of /rdr just to keep the redirector service in one block -- it's perfectly valid to create both locations at server-level.

like image 180
Alexander Azarov Avatar answered Oct 18 '22 04:10

Alexander Azarov