14

我有一个在 Nginx 中运行的 Sinatra 应用程序(使用 Thin 作为反向代理),我redirect '/<path>'在 Sinatra 中使用语句。但是,当我在 https 下访问该站点时,这些重定向会将我发送到http://localhost/<path>而不是https://localhost/<path>按照应有的方式发送到。

目前,nginx 使用此命令将控制权传递给瘦身,其中proxy_pass http://thin_clusterthin_cluster

upstream thin_cluster { server unix:/tmp/thin.cct.0.sock; }

我怎样才能解决这个问题?

4

2 回答 2

22

为了让 Sinatra 正确组装用于重定向的 url,它需要能够确定请求是否使用 ssl,以便可以使用httphttps酌情进行重定向。

显然,对瘦的实际调用没有使用 ssl,因为这是由前端 Web 服务器处理的,并且代理请求是明确的。因此,我们需要一种方法来告诉 Sinatra 它应该将请求视为安全的,即使它实际上并未使用 ssl。

最终,确定请求是否应被视为安全的代码在Rack::Request#ssl?andRack::Request#scheme方法中。这些scheme方法检查env哈希以查看是否存在多个条目之一。其中之一是HTTP_X_FORWARDED_PROTO对应于X-Forwarded-ProtoHTTP 标头。如果设置了此项,则该值用作协议方案(httphttps)。

因此,如果我们在请求从 nginx 代理到后端时将这个 HTTP 标头添加到请求中,Sinatra 将能够正确确定何时重定向到https. 在 nginx 中,我们可以使用 向代理请求添加标头proxy_set_header,并且该方案在$scheme变量中可用。

所以添加行

proxy_set_header X-Forwarded-Proto $scheme;

行后的 nginx 配置proxy_pass应该使其工作。

于 2011-06-15T21:56:42.417 回答
1

您可以在 nginx 层强制所有链接转到 https。在 nginx.conf 中:

server{
   listen 80;
   server_name example.com;
   rewrite    ^(.*) https://$server_name$1 redirect;
}    

这也可以确保您的请求始终是 https

于 2011-06-14T21:29:31.487 回答