如何修复 nginx 下 Sinatra 重定向从 https 切换到 http?

如何修复 nginx 下 Sinatra 重定向从 https 切换到 http?

我在 nginx 中运行了一个 Sinatra 应用程序(使用 Thin 作为反向代理),并且我redirect '/<path>'在 Sinatra 中使用了语句。但是,当我通过 https 访问网站时,这些重定向会将我发送到 ,http://localhost/<path>而不是https://localhost/<path>它们应该发送到的 。

目前,nginx 使用此命令将控制权传递给 thin proxy_pass http://thin_clusterthin_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: httpsX-Forwarded-Proto: https应该也能正常工作。请注意,将方案设置为类似于的内容otherproto不适用于 Sinatra,因为它会检查它是否是 HTTPS,并根据该布尔值生成 URL,而不仅仅是复制方案。

如果您有兴趣自己查看代码,我建议您从这两个参考资料开始:

https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L284def urihttps://github.com/rack/rack/blob/master/lib/rack/request.rb#L199def scheme

答案2

尝试这个:

redirect "https://#{request.host}/<path>"

Sinatra 是轻量级的,我猜它默认没有任何检测。

答案3

你应该能够通过代理重定向指令。如果proxy_redirect default不起作用(这应该是默认设置),请尝试以下操作:

proxy_redirect http://localhost/ https://localhost/;

相关内容