我有一个运行在nginx中的Sinatra应用程序(使用thin作为后台代理),并在Sinatra中使用redirect '/<path>'语句。 但是,当我通过https访问站点时,这些redirect将他们发送到http://localhost/<path>而不是https://localhost/<path> 。
目前,nginx使用此命令proxy_pass http://thin_cluster将控制proxy_pass http://thin_cluster控制为精简,其中thin_cluster是
upstream thin_cluster { server unix:/tmp/thin.cct.0.sock; }
我怎样才能解决这个问题?
尝试这个:
redirect "https://#{request.host}/<path>"
Sinatra是轻量级的,它没有任何检测这个默认情况下,我猜。
你应该能够通过proxy_redirect指令来实现这一点。 如果proxy_redirect default不起作用(它应该是默认设置),请尝试如下所示:
proxy_redirect http://localhost/ https://localhost/;
url()根据来自Rack::Request类的Sinatra::Request类的信息决定是否使用HTTP或HTTPS。 当被放在像Nginx这样的反向代理服务器上时,反向代理服务器必须向Rack(以及Sinatra)注入一些头文件,告诉他们世界如何看待它。 可惜的是,Nginx并没有默认设置这些标题,所以我们必须手动完成。
Rack根据Nginx发送的头文件确定它是否是HTTPS。 不幸的是,Nginx默认不会设置这些标题,所以你必须手动指定它们。
让我们来看一个例子,有问题的configuration。
# 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_redirectreplace自动更正它,导致http://hostname/robots.txt 。 我猜猜它不能解决这个问题的原因是因为有些人喜欢混合使用HTTP和HTTPS请求,但我不确定。
以下是我自己的Nginxconfiguration中的一个示例代理子句。
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在redirect上运行replace,所以我closuresproxy_redirect off; 。 ( X-Forwarded-For就是这样,Sinatra也可以计算出用户的IP地址。)
依靠Sinatra来正确执行所有操作而不是Nginx的proxy_redirect子句的另外一个好处就是你可以在视图内使用url()函数等等。
X-Forwarded-SSL只是您可以设置的less数标题之一。 HTTPS: on , X-Forwarded-Scheme: https和X-Forwarded-Proto: https也可以正常工作。 请注意,将该scheme设置为otherproto类的方法对于Sinatra将不起作用,因为它会检查它是否为HTTPS,并根据该布尔值生成URL,而不仅仅是复制该scheme。
如果您有兴趣自己查看代码,我推荐这两个参考作为起点:
https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L263 https://github.com/rack/rack/blob/master/lib/rack/request.rb#L184