你必须要小心一点,因为有一些微妙的潜在陷阱。这Rack::Request
门课在这里可能会有所帮助。
首先,您无法真正获取应用程序的 url ,因为它可能会响应多个 url(通过 Rack 路由、Apache 配置等),因此您正在查看获取特定请求的 url 。如果您只提供来自一个 url 的请求,这无关紧要。
请求的方案在env
下的哈希中rack.url_scheme
,但这仅适用于请求的“最后一站”。如果您的应用程序位于某种代理(Nqinx、Apache 等)之后,那么您想要获取真实请求的方案,而不是从代理到运行您的应用程序的机器的请求。如果您正确配置了代理,它应该设置一个标头,这样您就可以知道原始方案是什么。Rack::Request
有一种scheme
将这些标头考虑在内的方法。
url 的主机可能在keyenv
下的 hash 中HTTP_HOST
,但是这个 header 不一定存在(诚然,现在这不太可能)。你应该依靠SERVER_NAME
and SERVER_PORT
。此外还有处理代理请求的问题,您需要原始请求的主机名,而不是后端服务器。再次,Rack::Request
提供处理这些问题的方法host_with_port
。host
Rack::Request
还提供了一种结合方案和主机的base_url
方法,如果与默认值(80 或 443)不同,则仅包含端口。
您的应用程序的挂载位置位于键env
下的哈希中SCRIPT_NAME
。这将/game
在您的第二个示例中,如果您的应用程序安装在服务器的根目录中,则可以为空。同样,Rack::Request
提供了一个script_name
方法,虽然这个方法只是简单地返回env
散列中条目的值。
所以,总而言之,你可能想要使用这样的东西:
req = Rack::Request.new env
url = req.base_url + req.script_name
这看起来很简单,但正在为您处理各种可能性。
此外,您可能会发现Rack 规范对阅读很有用,它包含应该在env
散列中的各种条目的详细信息。