46

I have a website which should only be reachable over HTTPS except one URL-pattern (because I have on some pages http-iframe's and I would like to avoid security warnings)

E.g. this pages should be redirected to https:
http://example.com
http://example.com/a/this-is-an-article
http://example.com/v/this-is-a-video

This pages should not be redirected to https (or should be redirected form https to http)
http://example.com/l/page-with-unsafe-iframe
http://example.com/l/other-page-with-unsafe-iframe
tiefenb
  • 732
  • 3
  • 16
  • 32

2 Answers2

74

If the iframe pages are always in the same directory, simple prefix locations could be used.

server {
    listen 443;

    location /l/ {  # redirect https iframe requests to http server
        return 301 http://$server_name$request_uri;
    }
    # ...
}

server {
    listen 80;

    location / {  # the default location redirects to https
        return 301 https://$server_name$request_uri;
    }

    location /l/ {}  # do not redirect requests for iframe location
    # ...
}
Cole Tierney
  • 9,571
  • 1
  • 27
  • 35
  • It might be useful for someone, but if you try to redirect everything to HTTPS except one (or more) location, keep in mind that if you're using PHP, remember to include PHP handling code in both server {} blocks for HTTP & HTTPS version. – Bartosz Wójcik Apr 29 '16 at 15:38
  • 2
    There's a not-so-obvious trick here: **the order of the server directives above is important**. I had the `listen 80;` one go first and it didn't work. – ᴍᴇʜᴏᴠ Feb 09 '17 at 22:38
  • I'll try to reproduce that with my example. Can you post a link to your config? – Cole Tierney Feb 10 '17 at 02:00
  • Something else in your config might be interfering. I would start with just the above. If that works, start adding back elements of your config to isolate the problem. – Cole Tierney Mar 31 '19 at 16:45
17

You may use map and simple redirect rules, for example:

map $uri $redirect_https {
    /l/page-with-unsafe-iframe         0;
    /l/other-page-with-unsafe-iframe   0; # you can use regex here
    default                            1;
}

server {
    listen 443;

    if ($redirect_https = 0) {
       return 301 http://$server_name$request_uri;
    }

    # other code
}
server {
    listen 80;

    if ($redirect_https = 1) {
       return 301 https://$server_name$request_uri;
    }

    # other code
}

I should mention that 301 redirect is a good practice unlike permanent rewrite.

Dmitriy Z
  • 383
  • 1
  • 9