我在 nginx 中运行了一个 Sinatra 应用程序(使用 Thin 作为反向代理),并且我redirect '/<path>'
在 Sinatra 中使用了语句。但是,当我通过 https 访问网站时,这些重定向会将我发送到 ,http://localhost/<path>
而不是https://localhost/<path>
它们应该发送到的 。
目前,nginx 使用此命令将控制权传递给 thin proxy_pass http://thin_cluster
,thin_cluster
其中
upstream thin_cluster { server unix:/tmp/thin.cct.0.sock; }
我怎样才能解决这个问题?
答案1
url()
根据Sinatra::Request
类中的信息(从类派生而来)确定是使用 HTTP 还是 HTTPS Rack::Request
。当置于 Nginx 等反向代理之后时,反向代理必须注入一些标头,告诉 Rack(以及 Sinatra)世界如何看待它。遗憾的是,Nginx 默认不设置这些标头,因此我们必须手动设置。
让我们看一个有问题的配置示例。
# Bad configuration
location / {
proxy_pass http://127.0.0.1:9000;
}
Sinatra 不知道它位于反向代理后面,因此url('/robots.txt')
会生成http://127.0.0.1:9000/robots.txt
。Nginx 将尝试使用默认proxy_redirect
替换自动更正它,从而生成http://hostname/robots.txt
。
下面是我自己的 Nginx 配置中的一个代理子句示例。
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-SSL on;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://127.0.0.1:9000;
}
X-Forwarded-SSL: on
告诉 Sinatra 它位于 HTTPS 而不是 HTTP 后面,并且设置Host: $http_host
告诉 Sinatra 真实服务器的主机名。现在,url('/robots.txt')
将输出https://hostname/robots.txt
。由于我们不需要 Nginx 在我们的重定向上运行替换,因此我使用 明确关闭了它proxy_redirect off;
。(X-Forwarded-For
只是为了让 Sinatra 也能找出用户的 IP 地址。)
依靠 Sinatra 而不是 Nginx 的proxy_redirect
子句来正确完成所有操作的另一个好处是,您url()
也可以在视图等中使用该函数。
X-Forwarded-SSL
只是您可以设置的几个标头之一。HTTPS: on
、、X-Forwarded-Scheme: https
和X-Forwarded-Proto: https
应该也能正常工作。请注意,将方案设置为类似于的内容otherproto
不适用于 Sinatra,因为它会检查它是否是 HTTPS,并根据该布尔值生成 URL,而不仅仅是复制方案。
如果您有兴趣自己查看代码,我建议您从这两个参考资料开始:
https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L284(def uri
)
https://github.com/rack/rack/blob/master/lib/rack/request.rb#L199(def scheme
)
答案2
尝试这个:
redirect "https://#{request.host}/<path>"
Sinatra 是轻量级的,我猜它默认没有任何检测。
答案3
你应该能够通过代理重定向指令。如果proxy_redirect default
不起作用(这应该是默认设置),请尝试以下操作:
proxy_redirect http://localhost/ https://localhost/;