mod_rewrite:将现有文件重写为slu,,slu to现有文件

我的情况如下:我有我的本地服务器上的public/文件夹中的静态文件。 任何进来的请求应该被转发到该文件夹​​,但是如果该文件夹中的文件被直接访问,它应该是404或redirect到'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)以防止redirect循环
  3. 原始请求是以/public开头的吗?
  4. 如果(3)为真,并且原始请求匹配public/{request}.html/{request} ,则重写。 另外制作一个301头,告诉我的浏览器和抓取工具页面已经永久移动了。 请求将再次贯穿所有规则

所以,如果我们做了这两个要求:

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

到现在为止还挺好; 显示正确的文件与我想要的url。 请求编号2,它是对文件结构中存在的实际文件的请求:

 2. Request: /public/my-file.html 
  1. public/public/my-file.html.html评估为false,该文件不存在于我的文件夹中。
  2. 跳过
  3. 原始请求匹配:以/public开头
  4. public/my-file.html重写到/my-file ,然后从顶部开始。

现在,在第二个例子(4)之后,我会说请求匹配第一个例子,这意味着我正在寻找正确的URL(因为301)的页面。 但它不起作用:URL不变,我得到我正在寻找的页面,但不是URL(应该是/my-file )。

有没有人有指针? 我想我几乎在那里,但做链接或redirect错误。 谢谢!

编辑

在尝试了各种各样的东西之后,我终于决定,我想要的可能是不可能的。 我想redirect一个现有的文件( public/my-file.html )到一个不存在的文件( my-file )在视觉上 ,但内部我希望它请求现有的文件path。 这总是会导致一个redirect循环,因为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文件。

我把克里斯特·范·比西恩的答案标记为正确的,因为它指出我正确地指出了这一切。

编辑2

在后续问题中,使用%{THE_REQUEST}解决了问题: 请参阅此处

它不能按预期的方式工作与RewriteConds和RewriteRules的执行顺序有关。 RewriteRules在它们之前的RewriteConds之前被评估。 所以你处理/public/my-file.html的请求的/public/my-file.html是这样的:(我会保持你的编号)

  • 首先对照2的testing模式检查URL。 .*匹配任何东西..
  • 然后对RewriteCond 1进行评估。 由于这个失败,2中的replace不会被执行。
  • 将根据4的testing模式检查URI。由于您的URI以/开头,因此此testing模式不匹配。 规则失败,所以3的RewriteCond永远不会被评估。

RewriteConds(可以有几个)属于它们后面的RewriteRule,只有在RewriteCond中的模式匹配时才会被评估。 我知道这有点不直观。

阅读关于这里的语法: 在Apacheredirect,更改URL或redirectHTTP到HTTPS – 你想知道关于Mod_Rewrite规则的一切,但是不敢问

如何解决你的问题?

也许是这样的:

 RewriteRule ^/public/(.*)$ /$1 [R=301,L] RewriteRule ^(-*)$ /public/$1 

最后一个提示:启用重写日志。 你会学习一个包…

你可以检查真正的文件/文件夹,然后跳过

 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d 

规则之前可以有多个Cond。