如何让 Symfony 请求上下文使用 IIS 重写规则中的 REQUEST_URI?
How can I get Symfony request context to use the REQUEST_URI from a IIS rewrite rule?
我在 IIS7 中为对 Symfony 的请求设置了反向代理重写规则。
它匹配模式并传递正确的请求详细信息,因此从技术角度来看它正在工作,但 Symfony 似乎没有使用正确的信息或者我希望它使用的信息。
在 app.php
中设置断点以查看 symfony 在 $_SERVER
中从其他服务器接收到的内容详细信息,相关参数是:
HTTP_X_ORIGINAL_URL="/foo/bar/foo/someCall/123456789"
REQUEST_URI="/bar/foo/someCall/123456789"
(与
重写规则中的模式)
已为 /bar/foo/someCall/{id}
设置路由,但请求上下文仅将 pathInfo
设置为 /foo/bar/foo/someCall/{id}
,这会导致 "No route exists ..." 错误。
我需要请求上下文(可能是路由侦听器等)才能使用 REQUEST_URI
中的内容。如果可能的话,如何才能做到这一点?
使用反向代理时,您不应更改您的应用程序以匹配您的代理 url(甚至请注意 运行 在代理后面)。相反,代理需要确保它向您的应用程序发送正确的信息。为此,您需要了解 Syfony 如何确定路由是否匹配。
Symfony 默认使用 REQUEST_URI
来确定路由。但它也支持 IIS 重写规则,然后覆盖 REQUEST_URI
值,可以在这里看到:https://github.com/symfony/symfony/blob/2.8/src/Symfony/Component/HttpFoundation/Request.php#L1684-L1717。所以只使用 REQUEST_URI
在这里是行不通的。
在这种情况下,有趣的部分是 Symfony 确定基数 URL (https://github.com/symfony/symfony/blob/2.8/src/Symfony/Component/HttpFoundation/Request.php#L1729-L1752) 的方式。由于您正在尝试重写 URL 的基础,因此最好的办法是操纵作为代理的一部分传递的脚本路径。我不是 IIS 方面的专家,也不了解它的重写规则是如何工作的,但是当使用 Nginx 作为反向代理时,您通常会将 X-SCRIPT-NAME
header 设置为您的基本路径,因此您可以尝试类似的方法在 IIS 中。
IIS 生成 header HTTP_X_ORIGINAL_URL
作为重写的一部分,不幸的是,由于 prepareRequestUri()
中 if ($this->headers->has('X_ORIGINAL_URL'))
的条件,Symfony 将覆盖 REQUEST_URI
] 函数。
从 Pierre 在他的回答中谈到的内容开始,他协助弄清楚如何解决这个问题。
我们必须调整我们的 nginx conf 文件以 'overwrite' HTTP_X_ORIGINAL_URL
为空,因此不满足条件并且 REQUEST_URI
不会被错误覆盖。
location ~^\/{url}\/? {
...
proxy_set_header X-ORIGINAL-URL "";
...
}
我在 IIS7 中为对 Symfony 的请求设置了反向代理重写规则。 它匹配模式并传递正确的请求详细信息,因此从技术角度来看它正在工作,但 Symfony 似乎没有使用正确的信息或者我希望它使用的信息。
在 app.php
中设置断点以查看 symfony 在 $_SERVER
中从其他服务器接收到的内容详细信息,相关参数是:
HTTP_X_ORIGINAL_URL="/foo/bar/foo/someCall/123456789"
REQUEST_URI="/bar/foo/someCall/123456789"
(与 重写规则中的模式)
已为 /bar/foo/someCall/{id}
设置路由,但请求上下文仅将 pathInfo
设置为 /foo/bar/foo/someCall/{id}
,这会导致 "No route exists ..." 错误。
我需要请求上下文(可能是路由侦听器等)才能使用 REQUEST_URI
中的内容。如果可能的话,如何才能做到这一点?
使用反向代理时,您不应更改您的应用程序以匹配您的代理 url(甚至请注意 运行 在代理后面)。相反,代理需要确保它向您的应用程序发送正确的信息。为此,您需要了解 Syfony 如何确定路由是否匹配。
Symfony 默认使用 REQUEST_URI
来确定路由。但它也支持 IIS 重写规则,然后覆盖 REQUEST_URI
值,可以在这里看到:https://github.com/symfony/symfony/blob/2.8/src/Symfony/Component/HttpFoundation/Request.php#L1684-L1717。所以只使用 REQUEST_URI
在这里是行不通的。
在这种情况下,有趣的部分是 Symfony 确定基数 URL (https://github.com/symfony/symfony/blob/2.8/src/Symfony/Component/HttpFoundation/Request.php#L1729-L1752) 的方式。由于您正在尝试重写 URL 的基础,因此最好的办法是操纵作为代理的一部分传递的脚本路径。我不是 IIS 方面的专家,也不了解它的重写规则是如何工作的,但是当使用 Nginx 作为反向代理时,您通常会将 X-SCRIPT-NAME
header 设置为您的基本路径,因此您可以尝试类似的方法在 IIS 中。
IIS 生成 header HTTP_X_ORIGINAL_URL
作为重写的一部分,不幸的是,由于 prepareRequestUri()
中 if ($this->headers->has('X_ORIGINAL_URL'))
的条件,Symfony 将覆盖 REQUEST_URI
] 函数。
从 Pierre 在他的回答中谈到的内容开始,他协助弄清楚如何解决这个问题。
我们必须调整我们的 nginx conf 文件以 'overwrite' HTTP_X_ORIGINAL_URL
为空,因此不满足条件并且 REQUEST_URI
不会被错误覆盖。
location ~^\/{url}\/? {
...
proxy_set_header X-ORIGINAL-URL "";
...
}