mod_rewrite:将现有文件重写为 slug,将 slug 重写为现有文件

mod_rewrite:将现有文件重写为 slug,将 slug 重写为现有文件

我的情况如下:我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]

从上到下:

  1. /public/{request}.html文件吗?
  2. 重写如果(1)为真:/public/{request}.html,并链接到(3)以防止重定向循环
  3. 原始请求是否以 开头/public
  4. 如果 (3) 为真,且原始请求匹配,则重写public/{request}.html/{request}。同时创建一个301标头,告知我的浏览器和爬虫该页面已永久移动。该请求将再次运行所有规则

因此,如果我们提出这两个请求:

1. Request: /my-file
  1. /public/my-file.html计算结果为真;该文件存在于我的文件夹中。
  2. 重写为:/public/my-file.html,链接到 3
  3. 原始请求不匹配。
  4. 已跳过

到目前为止一切顺利;正确的文件显示了我想要的 URL。请求 2,是对文件结构中存在的实际文件的请求:

2. Request: /public/my-file.html
  1. public/public/my-file.html.html计算结果为假,该文件不存在于我的文件夹中。
  2. 已跳过
  3. 原始请求匹配:它以/public
  4. 重写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

规则前可以有多个条件。

相关内容