aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
authorChirag Singhal <chirag.singhal@sumerusolutions.com>2016-02-28 15:56:12 +0530
committerChirag Singhal <chirag.singhal@sumerusolutions.com>2016-08-22 10:53:41 +0530
commit64f9802e90369bcf8bb906a8c7b01212e02b0e39 (patch)
tree2c5139c9aedbbfd35877ee25dd11c905f1510a46 /actionpack/lib/action_dispatch
parent9ef56e51624ca7056599115eee3b43e248354bf7 (diff)
downloadrails-64f9802e90369bcf8bb906a8c7b01212e02b0e39.tar.gz
rails-64f9802e90369bcf8bb906a8c7b01212e02b0e39.tar.bz2
rails-64f9802e90369bcf8bb906a8c7b01212e02b0e39.zip
Return 307 status instead of 301 when rerouting POST requests to SSL
When `config.force_ssl` is set to `true`, any POST/PUT/DELETE requests coming in to non-secure url are being redirected with a 301 status. However, when that happens, the request is converted to a GET request and ends up hitting a different action on the controller. Since we can not do non-GET redirects, we can instead redirect with a 307 status code instead to indicate to the caller that a fresh request should be tried preserving the original request method. `rack-ssl` gem which was used to achieve this before we had this middleware directly baked into Rails also used to do the same, ref: https://github.com/josh/rack-ssl/blob/master/lib/rack/ssl.rb#L54 This would be specially important for any apps switching from older version of Rails or apps which expose an API through Rails.
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb10
1 files changed, 9 insertions, 1 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 0b81d0ad43..992daab3aa 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -133,12 +133,20 @@ module ActionDispatch
end
def redirect_to_https(request)
- [ @redirect.fetch(:status, 301),
+ [ @redirect.fetch(:status, redirection_status(request)),
{ "Content-Type" => "text/html",
"Location" => https_location_for(request) },
@redirect.fetch(:body, []) ]
end
+ def redirection_status(request)
+ if request.get? || request.head?
+ 301 # Issue a permanent redirect via a GET request.
+ else
+ 307 # Issue a fresh request redirect to preserve the HTTP method.
+ end
+ end
+
def https_location_for(request)
host = @redirect[:host] || request.host
port = @redirect[:port] || request.port