Nginx: rewriting https:// to http://

nginxrewrite

I'm trying to get Nginx to rewrite incoming requests to a site my server prefixed with https:// to http:// (this is because a CMS used on this site forces URIs instead of relative paths — essentially breaking the whole site by making images, scripts, and stylesheets unavailable).

I'm currently trying to retrofit an existing directive put in place by a predecessor, but I find myself limited by my knowledge of Nginx config syntax. Here's the code:

if ($ssl_protocol = "") {
    rewrite ^   https://$http_host$request_uri? permanent;
}

I've current commented this code out to prevent forcible rewrites of http:// to https://, but I can't reverse the process without breaking the site. Here's what I've tried so far:

if ($ssl_protocol = "https") {
    rewrite ^   http://$http_host$request_uri? permanent;
}

and

# also tried ($ssl_protocol != "")
if (!($ssl_protocol = "")) {
    rewrite ^   http://$http_host$request_uri? permanent;
}

The first one doesn't seem to have an effect. The HTML sent to the client still makes HTTPS requests that aren't being rewritten.

The second snippet doesn't appear to have any effect either – if I understand correctly (although I'm still somewhat surprised), Nginx doesn't support boolean negation.

What would be the best way (or a working way) to do this?

EDIT: I've tried adding the code from @NathanC's answer; however, this unconditional rewrite causes a redirect loop. Help is still appreciated.

Best Answer

The cleaner, way would be:

if ( $scheme = "https" ) {
    return 301 http://example.com$request_uri

or somewhere between that and Nathans answer, where your default ssl server block contains simply the return 301 (whichever ssl block it is, you'll have to take a close look at yours to see how its implemented and adapt) No point in doing regex for a simple redirect

return - http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return

edit: i just noticed there is a variable $https that can be used in the if statement instead. Returns " " if not https:

if ( $https = "on" ) {
    ...

Keep in mind, while testing changes, you should use a 302 temporary redirect instead of 301 permanent, to save hair-pulling when you discover you fixed it an hour earlier but the changes didn't reflect in your browser :)

Related Topic