2

[已解决:请参阅下面的解决方案。]

我在编写RewriteMap程序时遇到问题(使用 Python)。我有一个RewriteMap指向 Python 脚本的指令,该脚本确定请求的 URL 是否需要重定向到其他地方。

当脚本输出由换行符终止的字符串时,Apache 会相应地重定向。但是,当脚本输出NULL(没有换行符)时,Apache 挂起并且随后的 HTTP 请求被有效地忽略。

错误日志显示没有错误。重写日志仅在成功时显示 apass through后跟 a redirect,然后仅pass throughNULL脚本返回时显示。随后的请求也只显示pass through.

此外,替换stdoutos.fdopen(sys.stdout.fileno(), 'w', 0)将缓冲区长度设置为零也无济于事。

任何帮助将不胜感激。先感谢您。

/etc/apache2/httpd.conf

[...]
RewriteLock /tmp/apache_rewrite.lock

/etc/apache2/sites-available/default

<VirtualHost *:80>
  [...]
  RewriteEngine on
  RewriteLogLevel 1
  RewriteLog /var/www/logs/rewrite.log
  RewriteMap remap prg:/var/www/remap.py
  [...]
</VirtualHost>

/var/www/webroot/.htaccess

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*_.*) /${remap:$1} [R=301]

/var/www/remap.py

#!/usr/bin/python

import sys

def getRedirect(str):
  new_url = None
  # if url needs to be redirected, put this value in new_url
  # otherwise new_url remains None
  return new_url

while True:
  request = sys.stdin.readline().strip()
  response = getRedirect(request)
  if response:
    sys.stdout.write(response + '\n')
  else:
    sys.stdout.write('NULL')
  sys.stdout.flush()
4

2 回答 2

6

您必须返回一个换行符,而不是“NULL”。

Apache 等待换行符知道要重写的 URL 何时结束。如果您的脚本没有发送换行符,Apache 将永远等待。

所以只需更改return ('NULL')return ('NULL\n'),这将重定向到 /。如果您不希望发生这种情况,请让程序在地图中没有匹配项时返回您想要的 URL。

如果您不想在没有匹配项时重定向,我会:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond (${remap:$1}) !NULL
RewriteRule (.*_.*) /%1 [R=301]

在 RewriteCond 中使用匹配项(当然,这也适用于NULL)。但是鉴于您的问题,这看起来是正确的解决方案。

于 2009-10-16T22:52:05.727 回答
3

到目前为止,我想出的最佳解决方案是让 RewriteMap 脚本返回新的 url,或者'__NULL__\n'如果不需要重定向并将这个值存储在 ENV 变量中。然后,检查 ENV 变量!__NULL__并重定向。请参阅.htaccess下面的文件。

另外,如果有人打算做类似的事情,在 Python 脚本中,我将相当多的脚本包裹在 try/except 块中,以防止脚本死亡(在我的情况下,由于文件/数据库读取失败)和后续查询被忽略。

/var/www/webroot/.htaccess

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ - [E=REMAP_RESULT:${remap:$1},NS]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{ENV:REMAP_RESULT} !^__NULL__$
RewriteRule ^(.+)$ /%{ENV:REMAP_RESULT} [R=301,L]

/var/www/remap.py

#!/usr/bin/python

import sys

def getRedirect(str):
  try:  # to prevent the script from dying on any errors
    new_url = str
    # if url needs to be redirected, put this value in new_url
    # otherwise new_url remains None
    if new_url == str: new_url = '__NULL__'
    return new_url
  except:
    return '__NULL__'

while True:
  request = sys.stdin.readline().strip()
  response = getRedirect(request)
  sys.stdout.write(response + '\n')
  sys.stdout.flush()

Vinko,你绝对帮我解决了这个问题。如果我有更多的经验stackoverflow,你会收到^我的。谢谢你。

我希望这篇文章对将来处理类似问题的人有所帮助。

干杯,安德鲁

于 2009-10-18T04:57:33.163 回答