好的,设法进一步了解这一点。
首先,让我们考虑一下httpd.confsn-p:
<Location /subfold/dl>
RewriteEngine On
RewriteOptions AllowAnyURI
RewriteCond %{REQUEST_URI} ^/subfold/dl/
#RewriteRule subfold/dl/(.*)/(.*)$ httpdocs__$1__$2
RewriteRule (.*) - [E=RSLT:$1,CO=;frontdoor;yes_"$1";127.0.0.1;1440;/,NE,PT,L]
SetEnvIf Request_URI "^/subfold/dl/" REWRGO=Yes
# "without 'always' your additions will only go out on succesful responses"
SetEnvIf Cookie "frontdoor=([^;]+)" MyFrontDoor=%1
Header always set X-REWRGO "%{REWRGO}e"
Header always set X-RSLT "%{RSLT}e"
Header always set X-FRONTDOOR "%{MyFrontDoor}e"
Header always set X-Request_URI1 "%{REQUEST_URI}e"
Header always set X-Request_URI2 "expr=%{REQUEST_URI}"
</Location>
当我在我的httpd.conf 中有这个,我启动 Apache httpd.exe,然后我发出一个请求,这就是我现在得到的:
$ curl -IkL http://127.0.0.1/subfold/dl/my/test.html
HTTP/1.1 404 Not Found
Date: Mon, 18 Oct 2021 12:35:36 GMT
Server: Apache/2.4.46 (Win32) OpenSSL/1.1.1j
X-REWRGO: Yes
X-RSLT: C:/bin/Apache24/htdocs/subfold/dl/my/test.html
X-FRONTDOOR: (null)
X-Request_URI1: (null)
X-Request_URI2: /subfold/dl/my/test.html
Set-Cookie: frontdoor=yes_"C:/bin/Apache24/htdocs/subfold/dl/my/test.html"; path=/; domain=127.0.0.1; expires=Tue, 19-Oct-2021 12:35:36 GMT
Content-Type: text/html; charset=iso-8859-1
所以,有些东西开始起作用了……我从中收集到了什么:
首先,这里不需要AllowAnyURI - 我认为这是因为https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html 说:
当 RewriteRule 用于 VirtualHost 或 httpd 2.2.22 或更高版本的服务器上下文时,如果请求 URI 是 URL-path,mod_rewrite 将只处理重写规则。
我担心我的请求 URI 可能无法被识别,所以我启用了 AllowAnyURI - 但这似乎不是这里的问题。
这就是这个测试的内容:RewriteRule (.*) - 我们基本上有一个“passthrough”——原始请求不会被重写;再次https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html:
替换可能是:...
-(破折号)
破折号表示不应执行替换(现有路径通过未触及)。当需要在不更改路径的情况下应用标志(见下文)时使用此选项。
... 我们也有相应的 [PT] 标志。然后,由于整个匹配请求都在括号中 (.*) 并因此被捕获,我们可以在同一行中将其与 $1 一起输出;最后,我们都为此设置了一个环境变量 RSLT,以及一个 cookie。
现在让我感到惊讶的是:重写规则的“模式”部分的结果是不是原始 URL - 这是 Apache 将这个 URL 翻译成本地文件系统!!!
当我得到 cookie 的拆分值时,我第一次注意到这一点,因为它总是在冒号上拆分 (:) - 即使它是变量中的字符串数据(但确实包含 C:/..,这就是最终被分裂)!因此我尝试使用双引号,但这不起作用 - 最终起作用的是https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_co:
如果任何 cookie 字段中需要文字“:”字符,则可以使用替代语法。要选择替代语法,cookie“名称”应以';'开头字符,字段分隔符应指定为';'。
无论如何,我们已经有了:
-
http://127.0.0.1 /subfold/dl/my/test.html - 原始请求
-
C:/bin/Apache24/htdocs /subfold/dl/my/test.html - Apache 在本地文件系统中将该请求映射到什么
本质上,这是 OP 中代码的问题:RewriteRule ^subfold/dl/(.*)/(.*)$ ... 意味着:替换以 subfold... 开头的字符串 - 但是,字符串 ``C:/bin/...` 肯定可以不是这样开始的,所以 RewriteRule 永远不会匹配,也不会执行!
我想,我的另一个困惑是,(.*) 作为 RewriteRule 中的模式(第一个参数),通常看起来像 REQUEST_URI - 但它位于目录中的 .htaccess 中;再次https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html:
-
在 VirtualHost 上下文中,Pattern 最初将与主机名和端口之后、查询字符串之前的 URL 部分匹配(例如“/app1/index.html”)。这是(% 解码的)URL 路径。
-
在每个目录上下文(目录和 .htaccess)中,模式与仅部分路径匹配,例如“/app1/index.html”的请求可能会导致与“app1/index.html”或“index.html”取决于定义 RewriteRule 的位置。
...在哪里
REQUEST_URI
请求的 URI 的路径组件,例如“/index.html”。这特别排除了查询字符串,该字符串可作为其自己的名为 QUERY_STRING 的变量使用
所以,我的坏处是,我假设 (.*) 作为 RewriteRule 中的 Pattern 将匹配到路径组件(REQUEST_URI-like)并且我尝试匹配;而在这种情况下,它实际上是完整的文件系统路径,以 C:/...! 开头!
话虽如此,我们现在可以在上面的 sn-p 中取消注释 RewriteRule subfold/dl/(.*)/(.*)$ httpdocs__$1__$2 行 - 意识到这次比赛没有起始插入符号(^),这意味着“匹配字符串”:
<Location /subfold/dl>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/subfold/dl/
RewriteRule subfold/dl/(.*)/(.*)$ httpdocs__$1__$2
RewriteRule (.*) - [E=RSLT:$1,CO=;frontdoor;yes_"$1";127.0.0.1;1440;/,NE,PT,L]
SetEnvIf Request_URI "^/subfold/dl/" REWRGO=Yes
# "without 'always' your additions will only go out on succesful responses"
SetEnvIf Cookie "frontdoor=([^;]+)" MyFrontDoor=%1
Header always set X-REWRGO "%{REWRGO}e"
Header always set X-RSLT "%{RSLT}e"
Header always set X-FRONTDOOR "%{MyFrontDoor}e"
Header always set X-Request_URI1 "%{REQUEST_URI}e"
Header always set X-Request_URI2 "expr=%{REQUEST_URI}"
</Location>
...对此的回应是:
$ curl -IkL http://127.0.0.1/subfold/dl/my/test.html
HTTP/1.1 404 Not Found
Date: Mon, 18 Oct 2021 13:18:33 GMT
Server: Apache/2.4.46 (Win32) OpenSSL/1.1.1j
X-REWRGO: Yes
X-RSLT: C:/bin/Apache24/htdocs/subfold/dl/httpdocs__my__test.html
X-FRONTDOOR: (null)
X-Request_URI1: (null)
X-Request_URI2: /subfold/dl/httpdocs__my__test.html
Set-Cookie: frontdoor=yes_"httpdocs__my__test.html/dl/my/test.html"; path=/; domain=127.0.0.1; expires=Tue, 19-Oct-2021 13:18:33 GMT
Content-Type: text/html; charset=iso-8859-1
所以,是的 - 最后我可以在标题中看到预期的 mod_rewrite 字符串替换/替换,即使重写的 URI 不正确(即没有正确映射到现有的本地文件系统数据) - 这是我想要实现的。
为了好玩,这是 Apache 错误(即 mod_rewrite)日志的结果:
[Mon Oct 18 15:21:55.007369 2021] [rewrite:trace2] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] init rewrite engine with requested uri /subfold/dl/my/test.html
[Mon Oct 18 15:21:55.007369 2021] [rewrite:trace1] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] pass through /subfold/dl/my/test.html
[Mon Oct 18 15:21:55.008369 2021] [setenvif:trace2] [pid 15508:tid 1936] mod_setenvif.c(630): [client 127.0.0.1:12206] Setting REWRGO
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] add path info postfix: C:/bin/Apache24/htdocs/subfold -> C:/bin/Apache24/htdocs/subfold/dl/my/test.html
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] applying pattern 'subfold/dl/(.*)/(.*)$' to uri 'C:/bin/Apache24/htdocs/subfold/dl/my/test.html'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace4] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] RewriteCond: input='/subfold/dl/my/test.html' pattern='^/subfold/dl/' => matched
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace2] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] rewrite 'C:/bin/Apache24/htdocs/subfold/dl/my/test.html' -> 'httpdocs__my__test.html'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] add per-dir prefix: httpdocs__my__test.html -> /subfold/dl/httpdocs__my__test.html
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] add path info postfix: /subfold/dl/httpdocs__my__test.html -> /subfold/dl/httpdocs__my__test.html/dl/my/test.html
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] strip per-dir prefix: /subfold/dl/httpdocs__my__test.html/dl/my/test.html -> httpdocs__my__test.html/dl/my/test.html
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] applying pattern '(.*)' to uri 'httpdocs__my__test.html/dl/my/test.html'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace5] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] setting env variable 'RSLT' to 'httpdocs__my__test.html/dl/my/test.html'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace5] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] setting cookie 'frontdoor=yes_"httpdocs__my__test.html/dl/my/test.html"; path=/; domain=127.0.0.1; expires=Tue, 19-Oct-2021 13:21:55 GMT'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace2] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] forcing '/subfold/dl/httpdocs__my__test.html' to get passed through to next API URI-to-filename handler
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace2] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] trying to replace context docroot C:/bin/Apache24/htdocs with context prefix
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace1] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b22d90/initial] [perdir /subfold/dl/] internal redirect with /subfold/dl/httpdocs__my__test.html [INTERNAL REDIRECT]
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace2] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] init rewrite engine with requested uri /subfold/dl/httpdocs__my__test.html
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace1] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] pass through /subfold/dl/httpdocs__my__test.html
[Mon Oct 18 15:21:55.008369 2021] [setenvif:trace2] [pid 15508:tid 1936] mod_setenvif.c(630): [client 127.0.0.1:12206] Setting REWRGO
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] [perdir /subfold/dl/] add path info postfix: C:/bin/Apache24/htdocs/subfold -> C:/bin/Apache24/htdocs/subfold/dl/httpdocs__my__test.html
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] [perdir /subfold/dl/] applying pattern 'subfold/dl/(.*)/(.*)$' to uri 'C:/bin/Apache24/htdocs/subfold/dl/httpdocs__my__test.html'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] [perdir /subfold/dl/] add path info postfix: C:/bin/Apache24/htdocs/subfold -> C:/bin/Apache24/htdocs/subfold/dl/httpdocs__my__test.html
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace3] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] [perdir /subfold/dl/] applying pattern '(.*)' to uri 'C:/bin/Apache24/htdocs/subfold/dl/httpdocs__my__test.html'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace5] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] setting env variable 'RSLT' to 'C:/bin/Apache24/htdocs/subfold/dl/httpdocs__my__test.html'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace5] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] skipping already set cookie 'frontdoor'
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace2] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] [perdir /subfold/dl/] forcing 'C:/bin/Apache24/htdocs/subfold' to get passed through to next API URI-to-filename handler
[Mon Oct 18 15:21:55.008369 2021] [rewrite:trace1] [pid 15508:tid 1936] mod_rewrite.c(483): [client 127.0.0.1:12206] 127.0.0.1 - - [127.0.0.1/sid#f88ee0][rid#6b1a020/initial/redir#1] [perdir /subfold/dl/] initial URL equal rewritten URL: C:/bin/Apache24/htdocs/subfold [IGNORING REWRITE]
最后,请注意:
- 现在我们的 RewriteRule 不坚持字符串的 ^start,cookie 值不再像以前那样包含绝对路径的起始部分
- 但是,我们仍然有 RSLT 的绝对本地 (
C:/...) 路径 - 即使我们将 [P](用于代理)或 [R=302](用于重定向)标志添加到 RewriteRule (行为不会发生变化,因为页面无论如何都会返回 404)
- 出于某种原因,
SetEnvIf Cookie 与 cookie 不匹配,即使 cookie 被写出
- 即使
%{REQUEST_URI} 确实存在,它也不会通过"%{REQUEST_URI}e" 语法在标头中输出 - 它只能通过"expr=%{REQUEST_URI}" 语法输出,我猜这是ap_expr