nginx - Redirect specific page paths to https while keeping everything else on http (in a single server call)?

Posted by Kris Anderson on Server Fault See other posts from Server Fault or by Kris Anderson
Published on 2012-12-12T12:32:51Z Indexed on 2012/12/15 5:08 UTC
Read the original article Hit count: 441

Filed under:

From what I've gathered so far it's clear that running if statements in nginx should be avoided at all costs. Most of the examples I've found so far regarding specific page redirects involve multiple servers being used. But, isn't that a bit wasteful? I'm not sure, but I would think multiple servers to accomplish this would be somewhat slower then a single server when under heavy load.

My current server call is this:

server {
    listen  10.0.0.60:80;
    listen  10.0.0.60:443 default ssl;

    #other code
}

What I want to do is redirect certain http requests to https requests. For example, I want /login/ and /my-account/ to always be forced to use SSL. If you're on /help/ though, I want that served over the default http.

Is there a way to accomplish this within a single server call? Or is there no downside to using 2 server calls to get this working? nginx seems to be under pretty active development and a lot of the older guides I've followed were from times when you couldn't listen to requests for port 80 and 443 within the same server call. But now that nginx has been updated to support that (I'm running 1.2.4), I'm wondering if there's a "best practice" way of handling this today.

Any help would be greatly appreciated.

EDIT:

I did find this guide: http://redant.com.au/blog/manage-ssl-redirection-in-nginx-using-maps-and-save-the-universe/

and I updated my code as follows:

map $uri $my_preferred_proto {
        default "http";
        ~^/#/user/login "https";
}
server {
        listen  10.0.0.60:80; ## listen for ipv4; this line is default and implied
        listen  10.0.0.60:443 default ssl;

        if ($my_preferred_proto = "none") {
                set $my_preferred_proto $scheme;
        }

        if ($my_preferred_proto != $scheme) {
                return 301 $my_preferred_proto://mysite.com$request_uri;
        }

It's not working though. When I change the default to https everything is redirected to SSL so it does somewhat work. But the redirect of /#/user/login is not redirecting to HTTPS. Any ideas? Also, is this a good way to go about this?

© Server Fault or respective owner

Related posts about nginx