我有一个.htaccess
文件:
RewriteEngine On
DirectorySlash Off
RewriteCond %{REQUEST_URI} !(\.css|\.js|\.png|\.jpg|\.mp4|\.ttf|\.eot|\.woff)$
RewriteRule ^(.*)$ ?page=$1 [NC,L,QSA]
ErrorDocument 404 /e404
ErrorDocument 403 /e404
ErrorDocument 500 /e500
还有一个 PHP 函数用于检查所请求的 URI 是否存在。如果数据库中存在该 URI,它将获取内容并呈现页面;如果不存在,它将获取 404 错误页面内容并呈现页面。(这里一切正常)
问题是当我使用带有RewriteCond
文件部分内部扩展名的 URI 时.htaccess
,例如example.com/file.css
。在这种情况下,页面被重定向到example.com/e404
(这就是我想要的)。这里的问题是:
我不知道如何获取重定向到之前使用的“错误 URI” example.com/e404
,因为在加载错误页面时,我在页面内部有一个函数可以将“错误的 URI”插入数据库中。
答案1
在旁边:您发布的指令会在任何默认的 Apache 安装上创建重写循环,所以也许您还有其他指令或不同的配置,而您没有在问题中披露这些配置?无论如何,暂时忽略这个问题,因为您似乎没有遇到这样的问题。
我不知道如何在重定向到之前获取使用的错误 URI
example.com/e404
...
但你需要得到这些信息吗前“重定向”?在 PHP 中,您只需检查$_SERVER['REQUEST_URI']
超全局变量即可获取此信息(导致 404 的 URL)。但是,请注意,这包含斜杠前缀和查询字符串(如果有),否则您的page
URL 参数不会包含这些内容。
另外,为了澄清术语,严格来说,这并不是“重定向”到example.com/e404
。“重定向”意味着外部 HTTP 重定向。Apache 发出内部子请求用于错误文档(类似于URL重写,但不完全一样)。
您的代码可能存在的一个问题是 404 响应是以一种相当迂回的方式提供的:
- 如果
file.css
不存在,那么 Apache 将触发内部子请求/e404
(这会触发另一轮处理......) - 由于
/e404
没有以所述文件扩展名之一结尾,因此它被进一步重写为?page=e404
(大概是index.php
?)。
由于(不必要的)第二次重写,其他服务器变量(例如REDIRECT_URL
和REDIRECT_QUERY_STRING
(也传递到 PHP$_SERVER
超全局变量))未按预期设置。通常,这些变量将被设置为“错误的 URI”(即触发 404 的请求 URL),但它们却包含错误文档本身的详细信息。
您应该一步完成上述操作,避免第二次重写。例如(假设index.php
是处理请求的文件),错误文档应设置为所需的最终结果:
ErrorDocument 404 /index.php?page=e404
顺便说一句,您不一定需要e404
在 URL 中明确传递 HTTP“错误状态”(即),因为这在 PHP 的$_SERVER['REDIRECT_STATUS']
超全局变量中可用。
RewriteRule ^(.*)$ ?page=$1 [NC,L,QSA]
我假设您正在重写index.php
(已注册的 DirectoryIndex)?您不应该让 mod_dir 为 DirectoryIndex 发出额外的子请求,而应该明确说明并将您要重写的文件包含在代换。 例如:
RewriteRule ^(.*)$ index.php?page=$1 [QSA,L]
(NC
这里的旗帜是多余的。)
我不知道如何在重定向到之前获取使用的错误 URI
example.com/e404
...
退一步来再次回答你最初的疑问(作为学术练习)。你可以在 Apache 2.4.13+ 上执行此操作(尽管我不认为你需要至)。在 Apache 2.4.13+ 上,您可以使用 Apache 表达式创建动态 ErrorDocument。
例如,为了在错误文档本身的 URL 中明确传递导致 404 错误的 URL 路径,您可以执行以下操作:
ErrorDocument 404 /index.php?page=%{escape:%{REQUEST_URI}}&error=404
然后URL 参数page
包含 URL 路径(其中包括斜杠前缀,而重写则不包括它)。附加error
URL 参数发送 HTTP 状态(尽管如上所述,这不是绝对必要的)。