我们有一个服务器设置如下:
- 视窗 2012 R2
- Coldfusion 10,企业
- IIS,配置自定义 404 页面(在服务器上执行)
自定义 404 页面(一个 CFM 文件)处理丢失的 URL,并根据数据库中的自定义 URL 检查它们。如果找到匹配项,它将显示相关数据。当自定义 URL 映射到不存在的 CFM 文件时会出现问题;例如。
/home/map.cfm(不是真正的文件或目录)
现在,当用户请求此 URL 时,服务器会看到它是一个 CFM 文件并正确地将其传递给 ColdFusion(通过 ISAPI 重定向)。Tomcat 看到这个文件实际上并不存在,并返回一个 404。IIS 看到这个 404 消息并执行自定义错误页面(/errors/404.cfm)。
结果 CGI 变量实际上不允许我们检索原始 URL(将其映射到数据库中的虚拟 URL),通常作为 CGI.QUERY_STRING 变量的一部分提供。相反,QUERY_STRING 变量包含“jakarta”目录中“isapi_rewrite.dll”文件的路径。
在Tomcat为所述页面返回404错误之后,有什么方法可以保留最初请求的URL(CFM文件的)?
由 Thomas Gorgolione 启发,由我自己整理的解决方案
正如怀疑的那样,问题总是归结为被转发到 ISAPI_REDIRECT 模块的请求,即使相关文件不存在也是如此。
正如 Thomas 所建议的,一个优雅的解决方案是在将文件/目录传递给 ISAPI_REDIRECT 模块之前,利用重写来检查文件/目录是否确实存在。
虽然 Thomas 建议的软件可以解决问题,但我无法将其安装在 64 位 Windows 2012 R2 机器上。但是,我设法回退到使用 IIS8(可能还有早期版本)中包含的 URL 重写模块。
请参阅下面提供解决方案的我的 web.config 条目。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
</httpErrors>
<rewrite>
<rules>
<rule name="404 HTTP">
<match url="(.*)" />
<conditions>
<add input="{REQUEST_URI}" pattern="CFFileServlet/(.*)" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{SERVER_PORT_SECURE}" pattern="0" />
</conditions>
<action type="Rewrite" url="/404.cfm?404;http://{HTTP_HOST}:{SERVER_PORT}{REQUEST_URI}" />
</rule>
<rule name="404 HTTPS">
<match url="(.*)" />
<conditions>
<add input="{REQUEST_URI}" pattern="CFFileServlet/(.*)" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{SERVER_PORT_SECURE}" pattern="1" />
</conditions>
<action type="Rewrite" url="/404.cfm?404;https://{HTTP_HOST}:{SERVER_PORT}{REQUEST_URI}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
上面的配置文件同时考虑了 HTTP 和 HTTPS 请求。它还将考虑 CFFileServlet 目录,ColdFusion 使用该目录来托管临时图像和资产。如果 URL 以该目录开头,它将作为正常请求传递。
谢谢大家的意见。