【问题标题】:Apache2 replace substring in RewriteRule capture?Apache2 替换 RewriteRule 捕获中的子字符串?
【发布时间】:2021-12-05 07:28:56
【问题描述】:

我想知道 - 是否可以在 RewriteRule 捕获中替换(所有实例)子字符串?

这是一个示例,我已经在 https://htaccess.madewithlove.be/ 开始测试:

对于原始/输入网址:https://example.com/subfold/dl/testDir/subTestDir/test.png

我有规则:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/subfold/dl/
RewriteRule ^subfold/dl/(.*)/(.*)$ httpdocs__$1__$2 [NC,L]

...我得到输出 URL:https://example.com/httpdocs__testDir/subTestDir__test.png

所以,本质上,我将^subfold/dl 之后的整个子路径捕获到$1 变量中,并将文件名捕获到$2 中;所以在这种情况下:$1 = testDir/subTestDir$2 = test.png

所以我想要的是将$1 中的所有/(正斜杠)实例替换为%2F,然后再将其应用于输出URL -> 这样我最终将获得输出URL:@ 987654337@

有没有办法用 Apache2 RewriteRule's 来做到这一点 - 如果有,怎么做?


编辑:天哪:

... 至少在我第一次粘贴 mysite.com 时给我这条消息 - 现在我不得不浪费额外的时间来修改我的整个示例,因为我花了所有时间让它从 :( 开始...计算机永远不会让生活变得更轻松,是吗?只是更多的广告、垃圾和间谍活动......

【问题讨论】:

    标签: regex mod-rewrite url-rewriting apache2


    【解决方案1】:

    好的,找到了(另见一些相关的帖子Debugging Apache2 RewriteRule (with headers)?

    所以,我能找到的唯一有用的是Using RewriteMap - Apache HTTP Server Version 2.4。现在,由于我使用的是 Apache 的 Windows 版本,它变得有些棘手 - 但仍然可行。

    网上有很多关于如何使它工作的信息;重要信息在这里找到RewriteMap prg: issue on Windows - Apache Web Server forum at WebmasterWorld - By Pubcon

    如果“RewriteEngine On”指令在 OUTSIDE 之外,则 RewriteMap 程序启动,如下所示

    在我的例子中,当且仅当 RewriteMap 指令为 OUTSIDE <Location> 时,RewriteMap 程序才会启动;并且“RewriteEngine On”在 OUTSIDE <Location> - 在任何其他情况下,程序都不会启动。

    我们应该注意的第二件事是,来自https://httpd.apache.org/docs/2.4/rewrite/rewritemap.html

    当使用 prg 的 MapType 时,MapSource 是一个文件系统路径 将提供映射行为的可执行程序。这 可以是编译后的二进制文件,也可以是解释语言的程序 例如 Perl 或 Python。

    这个程序启动一次,当Apache HTTP Server启动时, 然后通过 STDIN 和 STDOUT 与重写引擎通信。 也就是说,对于每个映射函数查找,它需要一个参数 STDIN,并且应该返回一个换行符终止的响应字符串 标准输出。如果没有对应的lookup值,map程序 应该返回四个字符的字符串“NULL”来表明这一点。

    如果外部重写程序定义在 没有将 RewriteEngine 设置为 on 的上下文。

    换句话说 - 使用的程序必须打开它的 STDIN 和 STDOUT - AND必须 连续阻塞;即使你想做的是perl -i -pe's/SEARCH/REPLACE/',那种程序读取输入、处理、提供输出、然后退出——所以在这种情况下,它对我们没有任何好处。

    因此,根据 rewritemap.html 中给出的示例 - 这是一个 Perl 脚本,它用 %2F 替换正斜杠 (/),同时连续阻塞,称为 convslash.pl,保存在 C:\bin\Apache24\bin\

    #!C:/msys64/usr/bin/perl.exe
    $| = 1; # Turn off I/O buffering
    while (<STDIN>) {
        s|/|%2F|g; # Replace / with %2F
        print $_;
    }
    

    然后,我将其添加到我的httpd.conf

    # the below starts and runs ONLY if RewriteEngine On is outside of <Location>; also a cmd.exe window is started (plus another for perl!)
    #RewriteMap doprg "prg:c:/msys64/usr/bin/perl.exe c:/bin/Apache24/bin/dash2under.pl"
    
    # the below is slightly better - only one cmd.exe window is started:
    RewriteMap doprg "prg:c:/Windows/System32/cmd.exe /c start /b c:/msys64/usr/bin/perl.exe c:/bin/Apache24/bin/convslash.pl"
    
    # we MUST have RewriteEngine On here, outside of location - otherwise the RewriteMap program will never start:
    RewriteEngine On
    
    <Location /subfold/dl>
    
    Options -Multiviews
    RewriteEngine On
    RewriteOptions Inherit 
    
    # first RewriteCond - this is just so we can capture the relevant parts into environment variables:
    RewriteCond %{REQUEST_URI} ^/subfold/dl/(.*)/(.*)$
    RewriteRule ^ - [E=ONE:%1,E=TWO:%2,NE]
    
    # the above RewriteRule does not rewrite - but passes the input string further;
    # so here, let's have another such RewriteRule - just so we can set our processed/desired output to a variable, which we can "print" via headers:
    RewriteRule ^ - [E=MODDED:subfold/dl/${doprg:%{ENV:ONE}}/%{ENV:TWO},NE]
    
    # the original URL will finally pass through unmodified to the "file handler" which will attempt to map it to the filesystem, it will fail, and return 404.
    # the below headers should be returned along with that 404:
    
    Header always set X-ONE "%{ONE}e"
    Header always set X-TWO "%{TWO}e"
    Header always set X-INPUT "%{INPUT}e"
    Header always set X-MODDED "%{MODDED}e"
    Header always set X-REQ "expr=%{REQUEST_URI}"
    
    </Location>
    

    所以,现在我在本地启动服务器 (./bin/httpd.exe),为了测试这一点,我使用 curl 发出请求:

    $ curl -IkL http://127.0.0.1/subfold/dl/my/spec/test.html
    HTTP/1.1 404 Not Found
    Date: Mon, 18 Oct 2021 17:08:11 GMT
    Server: Apache/2.4.46 (Win32) OpenSSL/1.1.1j
    X-ONE: my/spec
    X-TWO: test.html
    X-INPUT: (null)
    X-MODDED: subfold/dl/my%2Fspec/test.html
    X-REQ: /subfold/dl/my/spec/test.html
    Content-Type: text/html; charset=iso-8859-1
    

    ...最后,我们可以在 X-MODDED 标头中看到,确实我们设法仅替换了重写 URL 中的子字符串 ...

    好吧,我希望以某种方式记录下来,而且我不必浪费 8 个小时的时间来解决这个问题 - 但谁在乎呢,几年后将会有新的服务器,其中所有这将是无关紧要的,因此将不得不浪费更多的时间——所有这些都是为了提供更多的废话、广告和间谍活动。

    【讨论】:

      猜你喜欢
      • 2015-06-13
      • 2018-06-26
      • 2020-04-05
      • 2012-04-03
      • 2013-07-23
      • 1970-01-01
      相关资源
      最近更新 更多