为什么Directory可以使用RewriteRule,但DirectoryMatch却失败?

问题描述 投票:0回答:1

DirectoryMatch
指令通常对我来说效果很好。

但是,当与

RewriteRule
结合使用时,它可能会失败。我也不明白为什么。

现在,我并不是在寻求一种完全避免

DirectoryMatch
指令的解决方法,例如通过组合
Directory
Import
指令。

我的问题特别是关于

DirectoryMatch
指令。为了让它发挥作用,我缺少什么?我对此有什么不明白的地方?关于重写模块?还是别的什么?

顺便说一下,请注意,链接

RewriteRule
并不能使
DirectoryMatch
指令成功实现此目的。

不允许使用

.htaccess
文件。 (
/etc/apache2/apache2.conf
包含
AllowOverride None
指令。)

我已上传以下文件。它们已经被 gzip 压缩了:

$ ls -dlU `find test-{d,m}*`
drwxr-xr-x 2 root root 4096 Feb  9 06:07 test-directory
-rw-r--r-- 1 root root  439 Feb  8 14:17 test-directory/test.html.gz
drwxr-xr-x 2 root root 4096 Feb  9 06:06 test-match
-rw-r--r-- 1 root root  439 Feb  8 14:18 test-match/test.html.gz

我在

/etc/apache2/conf-available/local-settings.conf
中有这些设置:

RewriteEngine On
<Directory /var/www/html>
   Require all granted
</Directory>

<Directory /var/www/html/test-directory>
   LogLevel debug
   Header set Cache-Control no-store
   RewriteCond "%{REQUEST_FILENAME}.gz" -s
   RewriteRule ^test\.html$ $0.gz
   RewriteRule ^test\.html\.gz$ - [T=text/html,E=no-gzip:1]
</Directory>

<DirectoryMatch "^/var/www/html/test-match">
   LogLevel debug
   Header set Cache-Control no-store
   RewriteCond "%{REQUEST_FILENAME}.gz" -s
   RewriteRule ^test\.html$ $0.gz
   RewriteRule ^test\.html\.gz$ - [T=text/html,E=no-gzip:1]
</DirectoryMatch>

基本上,如果附加到请求的文件名时隐式

.gz
扩展名作为文件存在,则:

Append `.gz`;

Serve the correct media type; and

Prevent mod_deflate from double-gzipping.

导航至

test.html
下的
Directory
有效。但在
DirectoryMatch
下它会生成“404 Not Found”。错误日志显示:

$ sudo tail -n 1 /var/log/apache2/error.log
[{...}:07:45.669167 2024] [core:info] [pid 919696:tid 281473097625984] {...} AH00128: File does not exist: /var/www/html/test-match/test.html

那么为什么带有

DirectoryMatch
的版本找不到该文件?

现在在另一组测试目录中,我上传了以下文件。它们没有被 gzip 压缩:

$ ls -dlU `find test-simple*`
drwxr-xr-x 2 root root 4096 Feb 12 13:51 test-simple-dir
-rw-r--r-- 1 root root  778 Feb  8 14:17 test-simple-dir/test.html.new
drwxr-xr-x 2 root root 4096 Feb 12 13:51 test-simple-match
-rw-r--r-- 1 root root  778 Feb  8 14:17 test-simple-match/test.html.new

我在

/etc/apache2/conf-available/local-settings.conf
中有这些额外的、更简单的设置:

<Directory /var/www/html/test-simple-dir>
   LogLevel debug
   Header set Cache-Control no-store
   RewriteCond "%{REQUEST_FILENAME}.new" -s
   RewriteRule ^test\.html$ test.html.new [END]
</Directory>

<DirectoryMatch "^/var/www/html/test-simple-match">
   LogLevel debug
   Header set Cache-Control no-store
   RewriteCond "%{REQUEST_FILENAME}.new" -s
   RewriteRule ^test\.html$ test.html.new [END]
</DirectoryMatch>

基本上,如果附加到请求的文件名后的

.new
扩展名作为文件存在,则:

Append `.new`.

再次导航到

test.html
下的
Directory
有效。但在
DirectoryMatch
下它会生成“404 Not Found”。错误日志显示:

[{...}:29:30.136369 2024] [deflate:debug] [pid 919696:tid 281473122804096] mod_deflate.c(869): {...} AH01384: Zlib: Compressed 778 to 404 : URL /test-simple-dir/test.html.new
[{...}:29:47.041233 2024] [core:info] [pid 919696:tid 281473262170496] {...} AH00128: File does not exist: /var/www/html/test-simple-match/test.html

再说一次,为什么带有

DirectoryMatch
的版本找不到该文件?

增加到

LogLevel trace6
产生,在错误日志中:

$ sudo tail  /var/log/apache2/error.log
[{...}:03:10.217345 2024] [core:trace3] [pid 938032:tid 281473262170496] request.c(360): [client {...}:27372] request authorized without authentication by access_checker_ex hook: /test-simple-match/test.html
[{...}:03:10.217356 2024] [rewrite:trace3] [pid 938032:tid 281473262170496] mod_rewrite.c(487): [client {...}:27372] {...} - - [{...}/sid#ffff9b6c4208][rid#ffff984370a0/initial] [perdir ^/var/www/html/test-simple-match/] applying pattern '^test\\.html$' to uri '/var/www/html/test-simple-match/test.html'
[{...}:03:10.217362 2024] [rewrite:trace1] [pid 938032:tid 281473262170496] mod_rewrite.c(487): [client {...}:27372] {...} - - [{...}/sid#ffff9b6c4208][rid#ffff984370a0/initial] [perdir ^/var/www/html/test-simple-match/] pass through /var/www/html/test-simple-match/test.html
[{...}:03:10.217376 2024] [core:info] [pid 938032:tid 281473262170496] [client {...}:27372] AH00128: File does not exist: /var/www/html/test-simple-match/test.html

出于诊断目的,在简单的

Directory
DirectoryMatch
部分中,我在
RewriteCond
之后立即临时添加了这个
RewriteRule
:

RewriteRule (.*) https://example.com/?path=$1 [R,L]

Directory
下,结果是根据需要重定向到
https://example.com/?path=test.html

但是在

DirectoryMatch
之下,是为了
https://example.com/?path=/var/www/html/test-simple-match/test.html
。换句话说,到绝对文件路径。

那么,在

DirectoryMatch
下,使用
RewriteCond
RewriteRule
指令时如何访问相对文件路径?

Apache 版本:

$ /usr/sbin/apachectl -v
Server version: Apache/2.4.56 (Debian)
Server built:   2023-04-02T03:06:01

Debian 版本:

$ cat /etc/debian_version
11.9
apache mod-rewrite apache2 apache2.4
1个回答
0
投票

问题的根源在于您的替换(第二个参数)是相对路径。 mod_rewrite 做了一个微妙/脆弱的舞蹈来剥离和删除它认为引导您到达规则的前缀并将其添加回任何相对替换中。 当这是正则表达式时,它不能再根据映射文件名的内部概念添加/删除内容。

  • 如果您可以重写以斜杠开头的 URL 路径,请执行此操作。
  • 如果你可以添加 RewriteBase,就这样做
  • 如果您可以避免将规则放入任何非 VirtualHost 配置部分,请这样做(并修改它们以期望 URL 以 / 开头,而不是剩下的内容)
© www.soinside.com 2019 - 2024. All rights reserved.