Rails 应用程序 HTTP 到 HTTPS 重定向不适用于公开 API
Rails App HTTP to HTTPS Redirect Not Working for Exposed API
我正在构建一个 Rails 4 应用程序,其中包含前端网站和公开的 API。 API 用作移动应用程序和桌面应用程序的后端。
我在 Heroku 上部署了该应用程序。因为该网站有一个订购系统,所以我决定 全局强制使用 ssl。当我发出 HTTP 请求时,站点成功将我重定向到 HTTPS。
但是,当我从命令行使用 cURL 向公开的 API 发出 HTTP 请求时,我没有得到预期的响应。相反,我在 Heroku 日志中看到了 301 状态消息(见下文)。当我通过 HTTPS 使用 cURL 发出相同的请求时,一切正常,我得到了成功的响应。
因此,除 API 之外的任何地方,HTTP 请求都被成功重定向到 HTTPS。但是,API 仍然正确响应 HTTPS 请求。
我做错了什么?我怎样才能允许用户向我的 API 发出 HTTP 请求,而只是像在应用程序的其余部分一样通过 HTTPS 重定向他们的请求?这没有意义吗?
我正在使用它在我的控制器中强制使用 https:
# /app/controllers/api/v1/pairings_controller.rb
before_filter :redirect_to_https
...
def redirect_to_https
redirect_to :protocol => "https://" unless (request.ssl? || request.local?)
end
我也试过了
# config/application.rb
config.force_ssl = (ENV["ENABLE_HTTPS"] == "yes")
config.ssl_options = {hsts: {expires: 1209600}}
Heroku 日志:
HTTP 不成功:
2015-03-20T13:40:26.590091+00:00 heroku[router]: at=info method=POST path="/api/v1/pairing/request" host=xxx.herokuapp.com request_id=f832239b-d352-43ed-b5c6-e8d6c9f7c242 fwd="23.27.14.153" dyno=web.1 connect=1ms service=11325ms status=200 bytes=540
2015-03-20T13:40:26.585221+00:00 app[web.1]: Completed 200 OK in 4954ms (Views: 0.3ms | ActiveRecord: 20.3ms)
2015-03-20T13:45:43.502413+00:00 heroku[router]: at=info method=POST path="/api/v1/pairing/request" host=xxx.herokuapp.com request_id=dd633b85-a70b-4a2d-bb39-b450972bb2ab fwd="23.27.14.153" dyno=web.1 connect=1ms service=1739ms status=301 bytes=211
使用 HTTPS 成功:
2015-03-20T13:40:19.113646+00:00 app[web.1]: Started POST "/api/v1/pairing/request" for 23.27.14.153 at 2015-03-20 13:40:18 +0000
2015-03-20T13:40:21.064630+00:00 app[web.1]: Processing by Api::V1::PairingsController#post_pairing_request as JSON
2015-03-20T13:40:21.631071+00:00 app[web.1]: Parameters: {"flags"=>"xxx", "otp"=>"xxx", "phone"=>"xxx", "pin"=>"xxx", "user"=>{"address"=>"xxx", "city"=>"Ripley", "email"=>"xxx", "name"=>"xxx", "state"=>"xxx", "zip"=>"xxx"}, "pairing"=>{"pin"=>"xxx", "phone"=>"xxx", "otp"=>"xxx"}}
2015-03-20T13:40:26.590091+00:00 heroku[router]: at=info method=POST path="/api/v1/pairing/request" host=xxx.herokuapp.com request_id=f832239b-d352-43ed-b5c6-e8d6c9f7c242 fwd="23.27.14.153" dyno=web.1 connect=1ms service=11325ms status=200 bytes=540
2015-03-20T13:40:26.585221+00:00 app[web.1]: Completed 200 OK in 4954ms (Views: 0.3ms | ActiveRecord: 20.3ms)
问题不在于您的 Rails 应用程序 - 它通过 301 重定向消息正确响应到不使用 https 的连接。
是否遵循 301 重定向取决于客户端。我的猜测是您的 Web 浏览器会遵循重定向,但 cURL 不会。
也许这可以帮助:Is there a way to follow redirects with command line cURL
我正在构建一个 Rails 4 应用程序,其中包含前端网站和公开的 API。 API 用作移动应用程序和桌面应用程序的后端。
我在 Heroku 上部署了该应用程序。因为该网站有一个订购系统,所以我决定 全局强制使用 ssl。当我发出 HTTP 请求时,站点成功将我重定向到 HTTPS。
但是,当我从命令行使用 cURL 向公开的 API 发出 HTTP 请求时,我没有得到预期的响应。相反,我在 Heroku 日志中看到了 301 状态消息(见下文)。当我通过 HTTPS 使用 cURL 发出相同的请求时,一切正常,我得到了成功的响应。
因此,除 API 之外的任何地方,HTTP 请求都被成功重定向到 HTTPS。但是,API 仍然正确响应 HTTPS 请求。
我做错了什么?我怎样才能允许用户向我的 API 发出 HTTP 请求,而只是像在应用程序的其余部分一样通过 HTTPS 重定向他们的请求?这没有意义吗?
我正在使用它在我的控制器中强制使用 https:
# /app/controllers/api/v1/pairings_controller.rb
before_filter :redirect_to_https
...
def redirect_to_https
redirect_to :protocol => "https://" unless (request.ssl? || request.local?)
end
我也试过了
# config/application.rb
config.force_ssl = (ENV["ENABLE_HTTPS"] == "yes")
config.ssl_options = {hsts: {expires: 1209600}}
Heroku 日志:
HTTP 不成功:
2015-03-20T13:40:26.590091+00:00 heroku[router]: at=info method=POST path="/api/v1/pairing/request" host=xxx.herokuapp.com request_id=f832239b-d352-43ed-b5c6-e8d6c9f7c242 fwd="23.27.14.153" dyno=web.1 connect=1ms service=11325ms status=200 bytes=540
2015-03-20T13:40:26.585221+00:00 app[web.1]: Completed 200 OK in 4954ms (Views: 0.3ms | ActiveRecord: 20.3ms)
2015-03-20T13:45:43.502413+00:00 heroku[router]: at=info method=POST path="/api/v1/pairing/request" host=xxx.herokuapp.com request_id=dd633b85-a70b-4a2d-bb39-b450972bb2ab fwd="23.27.14.153" dyno=web.1 connect=1ms service=1739ms status=301 bytes=211
使用 HTTPS 成功:
2015-03-20T13:40:19.113646+00:00 app[web.1]: Started POST "/api/v1/pairing/request" for 23.27.14.153 at 2015-03-20 13:40:18 +0000
2015-03-20T13:40:21.064630+00:00 app[web.1]: Processing by Api::V1::PairingsController#post_pairing_request as JSON
2015-03-20T13:40:21.631071+00:00 app[web.1]: Parameters: {"flags"=>"xxx", "otp"=>"xxx", "phone"=>"xxx", "pin"=>"xxx", "user"=>{"address"=>"xxx", "city"=>"Ripley", "email"=>"xxx", "name"=>"xxx", "state"=>"xxx", "zip"=>"xxx"}, "pairing"=>{"pin"=>"xxx", "phone"=>"xxx", "otp"=>"xxx"}}
2015-03-20T13:40:26.590091+00:00 heroku[router]: at=info method=POST path="/api/v1/pairing/request" host=xxx.herokuapp.com request_id=f832239b-d352-43ed-b5c6-e8d6c9f7c242 fwd="23.27.14.153" dyno=web.1 connect=1ms service=11325ms status=200 bytes=540
2015-03-20T13:40:26.585221+00:00 app[web.1]: Completed 200 OK in 4954ms (Views: 0.3ms | ActiveRecord: 20.3ms)
问题不在于您的 Rails 应用程序 - 它通过 301 重定向消息正确响应到不使用 https 的连接。
是否遵循 301 重定向取决于客户端。我的猜测是您的 Web 浏览器会遵循重定向,但 cURL 不会。
也许这可以帮助:Is there a way to follow redirects with command line cURL