我的情况如下:我public/
的本地服务器上的文件夹中有静态文件。任何传入的请求都应转发到该文件夹,但如果直接访问该文件夹中的文件,则应该出现 404 错误或重定向到“slug”。示例:
Request: /my-file
Should rewrite to: /public/my-file.html
URL should be: http://localhost/my-file
Request: /public/my-file.html
Should rewrite to: /public/my-file.html
URL should be: http://localhost/my-file
我的 中有以下规则和条件.htaccess
:
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI}.html -f
RewriteRule ^.*$ /public/$0.html [L,C]
RewriteCond %{REQUEST_URI} ^/public
RewriteRule ^public/(.+).html$ /$1 [R=301,L]
从上到下:
- 是
/public/{request}.html
文件吗? - 重写如果(1)为真:
/public/{request}.html
,并链接到(3)以防止重定向循环 - 原始请求是否以 开头
/public
? - 如果 (3) 为真,且原始请求匹配,则重写
public/{request}.html
:/{request}
。同时创建一个301
标头,告知我的浏览器和爬虫该页面已永久移动。该请求将再次运行所有规则
因此,如果我们提出这两个请求:
1. Request: /my-file
/public/my-file.html
计算结果为真;该文件存在于我的文件夹中。- 重写为:
/public/my-file.html
,链接到 3 - 原始请求不匹配。
- 已跳过
到目前为止一切顺利;正确的文件显示了我想要的 URL。请求 2,是对文件结构中存在的实际文件的请求:
2. Request: /public/my-file.html
public/public/my-file.html.html
计算结果为假,该文件不存在于我的文件夹中。- 已跳过
- 原始请求匹配:它以
/public
- 重写
public/my-file.html
为/my-file
,并从顶部开始。
现在,在第二个示例中的 (4) 之后,我会说请求与第一个示例匹配,这意味着我获得了我正在寻找的具有正确 URL 的页面(因为 301)。但它不起作用:URL 没有改变,我获得了我正在寻找的页面,但不是 URL(应该是/my-file
)。
有人能指点一下吗?我想我快到了,但是链接或重定向出了点问题。谢谢!
编辑
尝试了各种方法后,我最终决定,我想要的可能是不可能的。我想将现有文件 ( public/my-file.html
) 重定向到不存在的文件 ( my-file
)视觉上,但我希望它内部请求现有的文件路径。这必然会导致重定向循环,因为 mod_rewrite 无法以这种方式工作:
User typed: website.com/my-file
Rewrites to file path: .../wwwroot/public/my-file.html
Internal redirect
Rewriterule found: /public/my-file.html should redirect to my-file
See above.
我在 ServerFault 或 StackOverflow 上还没有遇到过任何类似的情况 - 通常重写会转到通用.php
文件,而不是现有.html
文件。
我将 Krist van Besien 的答案标记为正确答案,因为它为我指明了解决所有这一切的正确方向。
编辑2
在后续问题中,该问题通过使用以下方法解决%{THE_REQUEST}
:看这里
答案1
它无法按预期工作与 RewriteConds 和 RewriteRules 的执行顺序有关。RewriteRules 先于其之前的 RewriteConds 进行评估。因此,/public/my-file.html
处理您的请求的顺序如下:(我将保留您的编号)
- 首先根据 2 的测试模式检查 URL。并且匹配。
.*
毕竟匹配任何东西。 - 然后对 RewriteCond 1 进行评估。由于失败,因此不执行 2 中的替换。
- 根据测试模式 4 检查 URI。此测试模式不匹配,因为您的 URI 以 / 开头。规则失败,因此 3 处的 RewriteCond 永远不会被评估。
RewriteConds(您可以有多个)属于其后的 RewriteRule,并且只有当 RewriteCond 中的模式首先匹配时才会进行评估。我知道这有点违反直觉。
在此处阅读语法: 在 Apache 中重定向、更改 URL 或将 HTTP 重定向到 HTTPS - 您想了解但又不敢问的有关 Mod_Rewrite 规则的一切
如何解决你的问题?
也许是这样的:
RewriteRule ^/public/(.*)$ /$1 [R=301,L]
RewriteRule ^(-*)$ /public/$1
最后一条提示:启用重写日志。您将学到很多东西……
答案2
您可以只检查真实文件/文件夹并跳过..
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
规则前可以有多个条件。