mod_rewrite的RewriteMap prg仅对第一次请求有效

1 投票
1 回答
2131 浏览
提问于 2025-04-17 07:46

我正在创建一个简单的IP黑名单。每次请求都会检查是否在这个IP列表中,如果需要的话就返回403错误。我决定在Apache服务器上处理这个问题,使用了mod_rewrite、它的RewriteMap以及一个简单的Python脚本。

VirtualHost中:

<VirtualHost *:80>
    ...

    RewriteEngine On

    RewriteMap banip prg:/path/to/script.py
    RewriteCond ${banip:%{REMOTE_ADDR}} !=OK
    RewriteRule ^/.* - [F]
</VirtualHost>

script.py:

#!/usr/bin/python
import sys

sys.stdout.write('OK\n')
sys.stdout.flush()

现在有个奇怪的情况。在重启Apache后,只有第一次请求返回200,而后面的请求都返回403。我本以为所有请求都会返回200。每次重启Apache后,情况都是这样。

重启Apache后的重写日志:

# Very first request
127.0.0.1 - (2) init rewrite engine with requested uri /app_dev.php/
127.0.0.1 - (3) applying pattern '^/.*' to uri '/app_dev.php/'
127.0.0.1 - (5) map lookup OK: map=banip key=127.0.0.1 -> val=OK
127.0.0.1 - (4) RewriteCond: input='OK' pattern='!=OK' => not-matched
127.0.0.1 - (1) pass through /app_dev.php/

...

# Request after that
127.0.0.1 - (2) init rewrite engine with requested uri /static/css/grid.css
127.0.0.1 - (3) applying pattern '^/.*' to uri '/static/css/grid.css'
127.0.0.1 - (5) map lookup OK: map=banip key=127.0.0.1 -> val=
127.0.0.1 - (4) RewriteCond: input='' pattern='!=OK' => matched
127.0.0.1 - (2) forcing responsecode 403 for /static/css/grid.css

在第二次刷新时,它没有在重写日志中写入任何内容,直接就返回403了。

当我尝试RewriteCond OK !=OKRewriteCond NOTOK !=OK时,效果很好。你知道这是为什么吗?

我使用的是Xubuntu 11.10,Apache 2.2.20和Python 2.7.2。

1 个回答

4

我觉得你应该仔细看看RewriteMap的文档,特别是里面提到的内容:

这个程序在Apache服务器启动时只会运行一次,然后通过标准输入和标准输出与重写引擎进行通信。每次查找时,它会从标准输入接收到一个以换行符结束的字符串作为查找的关键字。接着,它需要把查找到的值以换行符结束的字符串形式返回到标准输出,如果查找失败(也就是说,没有找到对应的值),则返回一个四个字符的字符串“NULL”。

所以,你的程序只会启动一次,从Apache接收一个关键字,生成一个响应,然后退出。正如文档中所说的,它不会被重新启动

你的程序应该是一个循环,读取输入的一行,生成输出,然后等待更多的输入。链接中的文档里有一个非常简单的示例。

撰写回答