When the user is on HTTP, I can successfully redirect him to a HTTPS (SSL) variant like so:
redirect_to { protocol: 'https://', domain: 'ssl.tld' }
However, when I want to do the reverse, it creates an infinite redirection loop. I've tried several variants. To mention some:
redirect_to { protocol: 'http://', domain: 'nonssl.tld' }
redirect_to "http://nonssl.tld#{request.fullpath}"
The loop, according to the log:
000.000.000.000 - - [21/Apr/2016:18:50:04 -0100] "GET /en HTTP/1.1" 302 887 "https://ssl.tld/en/users/sign_in" "= THE_USER_AGENT_HERE"
Whereas https://ssl.tld/en/users/sign_in
apparantly is the referrer/the current page before redirection.
I wonder why the GET
shows a path as opposed to a URL - especially given that redirect_to "http://nonssl.tld#{request.fullpath}"
should explicitly be considered an absolute URL, according to the docs.
UPDATE Here is the relevant part from the application_controller's before_action
:
exceptions = ['errors', 'subscriptions', 'users']
ssl_is_mandatory = ! exceptions.include?(controller_name)
currently_on_ssl = request.ssl?
if currently_on_ssl
if !current_user && !ssl_is_mandatory
logger.debug "#{__method__}: Visitor currently on SSL, but SSL not desired. Redirecting to non_ssl"
redirect_to "http://my.domain#{request.fullpath}"
end
else
if current_user || ssl_is_mandatory
logger.debug "#{__method__}: Currently on no-SSL, but user in session or SSL mandatory. Redirecting to ssl"
redirect_to { protocol: 'https://', domain: 'my.ssldomain' }
end
end
UPDATE: As requested by Marc in the comments, here are the request headers:
Request headers for SSL domain
# curl -s -I https://SSL.tld
HTTP/1.1 302 Found
Date: Mon, 02 May 2016 23:33:34 GMT
Server: Apache/2.2.15 (Red Hat)
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Cache-Control: no-cache
X-Request-Id: 8d182c5e-cec6-46c0-b845-eafe2d313fe2
X-Runtime: 0.005948
X-Powered-By: Phusion Passenger 4.0.18
Location: https://SSL.tld/en
Content-Length: 895
Status: 302 Found
Content-Type: text/html; charset=utf-8
Set-Cookie: GEAR=local-554148915973ca816300021b; path=/
# curl -s -I https://SSL.tld/en
HTTP/1.1 200 OK
Date: Mon, 02 May 2016 23:33:52 GMT
Server: Apache/2.2.15 (Red Hat)
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
ETag: "acf44db83201e4da25659ab8545936b3"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 671d9407-0cdd-4401-9537-abff660e1b18
X-Runtime: 0.078496
X-Powered-By: Phusion Passenger 4.0.18
Content-Length: 10964
Status: 200 OK
Content-Type: text/html; charset=utf-8
Cache-control: private
Set-Cookie: GEAR=local-554148915973ca816300021b; path=/
Vary: Accept-Encoding
Request headers for NONSSL domain
# curl -s -I http://NONSSL.tld
HTTP/1.1 302 Found
Date: Mon, 02 May 2016 23:34:16 GMT
Server: Apache/2.2.15 (Red Hat)
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Cache-Control: no-cache
X-Request-Id: 9f7b4341-0489-48fa-b15d-b45f787db690
X-Runtime: 0.007811
X-Powered-By: Phusion Passenger 4.0.18
Location: http://NONSSL.tld/en
Content-Length: 873
Status: 302 Found
Content-Type: text/html; charset=utf-8
Set-Cookie: GEAR=local-554148915973ca816300021b; path=/
# curl -s -I http://NONSSL.tld/en
HTTP/1.1 200 OK
Date: Mon, 02 May 2016 23:34:47 GMT
Server: Apache/2.2.15 (Red Hat)
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
ETag: "05294c86e7f806ebf2e90c5f52fd7497"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 25a0ac8c-6cba-4a83-9a15-b95474436a3e
X-Runtime: 0.290131
X-Powered-By: Phusion Passenger 4.0.18
Content-Length: 10877
Status: 200 OK
Content-Type: text/html; charset=utf-8
Cache-control: private
Set-Cookie: GEAR=local-554148915973ca816300021b; path=/
Vary: Accept-Encoding
UPDATE
I further simplified the redirection code in application_controller's before_action
:
def debug_toggle_ssl
if params[:x].eql?('yes')
redirect_to "http://NONSSL.tld#{request.fullpath}"
end
end
So now, to reproduce the issue:
- Go to https://SSL.tld
- Try to go to https://SSL.tld/?x=yes
- Notice how a loop to https://SSL.tld is caused (http://NONSSL.tld is never even requested)