0

I would like to redirect all HTTP traffic to HTTPS, with one exception. Anything with /preview/ in the URL should be served via HTTP.

I have tried with below configuration, but it keeps telling me I have a redirect loop.

server {
    listen 80;
    server_name example.com;

    root            /var/www/html/example.com/public;
    index           index.php index.html;


    location /preview {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location / {
        # we are in http server, but want https for normal
        # requests - redirect to https

        return 301 https://$server_name$request_uri;
    }


    location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

            # With php5-cgi alone:
            #fastcgi_pass 127.0.0.1:9000;
            # With php5-fpm:
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
    }
}


 server {
    listen 443;
    server_name example.com;

    ssl on;
    ssl_certificate /etc/nginx/ssl/cert_chain.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    add_header Strict-Transport-Security max-age=31536000;

    access_log  /var/log/nginx/example.com/access.log;
    error_log   /var/log/nginx/example.com/error.log;

    charset utf-8;


    root            /var/www/html/example.com/public;
    index           index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location /preview {
        # we are in http server, but want https for normal
        # requests - redirect to https

        return 301 http://$server_name$request_uri;
    }

    location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

            # With php5-cgi alone:
            #fastcgi_pass 127.0.0.1:9000;
            # With php5-fpm:
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
    }
}

2 Answers 2

1

As per this related question:

https://stackoverflow.com/questions/11493325/nginx-redirect-all-directories-except-one

You need to be aware of the order nginx processes location blocks. It confuses the hell out of me too, but it looks like if you swap "location /preview" and "location /" around in your :80 server block, you will get the desired result.

Same as (a duplicate question) here:

https://stackoverflow.com/questions/27857334/nginx-redirect-everything-from-http-to-https-except-one-url-pattern

It may help to force the order of processing if you make the preview location a regex.

Also see: http://nginx.org/en/docs/http/request_processing.html

nginx first searches for the most specific prefix location given by literal strings regardless of the listed order. In the configuration above the only prefix location is “/” and since it matches any request it will be used as a last resort. Then nginx checks locations given by regular expression in the order listed in the configuration file. The first matching expression stops the search and nginx will use this location. If no regular expression matches a request, then nginx uses the most specific prefix location found earlier.

1
  • Tried as per your suggestion. Still not resolved. FYI, i have followed those two questions but no luck. Jul 17, 2015 at 16:32
-2

Try to clean the browser cache before testing each time. It looks like your config is worked. I tested it with the links:

https:// example.com/preview/any.html -(301)-> http:// example.com/preview/any.html
http:// example.com/preview/any.html - no redirects
https:// example.com/any.html - no redirects
http:// example.com/any.html -(301)-> https:// example.com/any.html
https:// example.com/preview/any.php - no redirects
http:// example.com/preview/any.php - no redirects
https:// example.com/any.php - no redirects
http:// example.com/any.php - no redirects

everything as configured. Pls, explain where do you get the loops.

2
  • Are you claiming you tested example.com domains?
    – Sven
    Jul 17, 2015 at 19:31
  • 1
    I changed the hosts-file to resolve example.com as 127.0.0.1
    – bolD
    Jul 28, 2015 at 23:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .