Apache:RewriteRule会导致段错误

时间:2009-11-05 13:08:50

标签: apache mod-rewrite

我使用RewriteRule用下划线替换我的URL中的所有空格(又名%20):

RewriteRule (.*)[\ ](.*) $1_$2 [N]

[N]标志再次开始重写过程,直到没有剩余空间(希望如此)。现在,当一个文件在另一边等待时,一切都很顺利,即请求:

/This is an example.html

和文件:

This_is_an_example.html

但是当没有匹配的文件时,Apache会以500内部错误退出。错误日志表示段错误,重写日志显示重写引擎疯狂尝试重定向到

/This is an_example.html/This is an_example.html/This is an_example.html/...

等等,直到segfault(注意, last 空间被转换,但没有其他)。

有没有人知道,为什么RewriteRule在为现有文件工作时会如此悲惨地失败?

更新:只有在请求的URI中有额外的“/”时才会发生段错误,例如

/virtual-directory/This is an example.html

更新2:此声明中有 RewriteCond。在我看来,它应该没有。问题是,为什么不呢。 htaccess的:

RewriteEngine On
RewriteBase /test/

RewriteRule (.*)[\ ](.*) $1_$2 [N]

更新3:有问题的.htaccess文件:

AddType application/xhtml+xml .xhtml
AddEncoding x-gzip .gz

ExpiresActive On
ExpiresByType application/xhtml+xml "access plus 1 year"

ErrorDocument 404 /test/index.php?error=404

RewriteEngine On

RewriteBase /test/

# replace spaces with underscores
RewriteCond %{REQUEST_FILENAME} .*[\ ].*
RewriteRule (.*)[\ ](.*) $1_$2 [N]

# the index.php
RewriteRule ^index.php - [L]

# language tag
RewriteRule ^([a-z]{2})$ index.php?lang=$1&url= [L,QSA]
RewriteRule ^$ en [R=301,L]

# add .xhtml
RewriteCond %{REQUEST_FILENAME}.xhtml -s [OR]
RewriteCond %{REQUEST_FILENAME}.xhtml.gz -s
RewriteRule ^(.+) $1.xhtml

# add .gz
RewriteCond %{HTTP:Accept-Encoding} .*gzip.*
RewriteCond %{REQUEST_FILENAME}.gz -s
RewriteRule ^(.+) $1.gz

# send correct mime type
#RewriteCond %{REQUEST_FILENAME} -s
RewriteRule \.xhtml\.gz$  - [L,T=application/xhtml+xml]

rewriteLog语句太大而无法粘贴。单个请求用13MB的数据填充文件。这是摘要:

(IP) - - [date] [host] (3) [perdir /htdocs/test/] add path info postfix: /htdocs/test/de -> /htdocs/test/de/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] strip per-dir prefix: /htdocs/test/de/This is a test -> de/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] applying pattern '(.*)[\ ](.*)' to uri 'de/This is a test'
(IP) - - [date] [host] (2) [perdir /htdocs/test/] rewrite 'de/This is a test' -> 'de/This is a_test'
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add per-dir prefix: de/This is a_test -> /htdocs/test/de/This is a_test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add path info postfix: /htdocs/test/de/This is a_test -> /htdocs/test/de/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] strip per-dir prefix: /htdocs/test/de/This is a_test/This is a test -> de/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] applying pattern '(.*)[\ ](.*)' to uri 'de/This is a_test/This is a test'
(IP) - - [date] [host] (2) [perdir /htdocs/test/] rewrite 'de/This is a_test/This is a test' -> 'de/This is a_test/This is a_test'
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add per-dir prefix: de/This is a_test/This is a_test -> /htdocs/test/de/This is a_test/This is a_test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add path info postfix: /htdocs/test/de/This is a_test/This is a_test -> /htdocs/test/de/This is a_test/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] strip per-dir prefix: /htdocs/test/de/This is a_test/This is a_test/This is a test -> de/This is a_test/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] applying pattern '(.*)[\ ](.*)' to uri 'de/This is a_test/This is a_test/This is a test'
(IP) - - [date] [host] (2) [perdir /htdocs/test/] rewrite 'de/This is a_test/This is a_test/This is a test' -> 'de/This is a_test/This is a_test/This is a_test'
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add per-dir prefix: de/This is a_test/This is a_test/This is a_test -> /htdocs/test/de/This is a_test/This is a_test/This is a_test
... and so on ad infinitum

坏人是第6行:“添加路径信息后缀”。

3 个答案:

答案 0 :(得分:2)

<强>更新

查看更新3 (有用,谢谢),我想到了另外两个想法:

  1. 有一个apache问题:mod_rewrite adds path info postfix after a substitution occured,看起来与你的相似。这是fixed in 2.2.12引入的discardpathinfo|DPI RewriteRule flag。尝试将此标记添加到RewriteRule

    RewriteRule (.*)[\ ](.*) $1_$2 [N,DPI]
    

    看看是否能解决问题。需要apache 2.2.12。

  2. 您是否恰好mod_dir启用了DirectorySlash On?尝试禁用它。

  3. 更新结束

    您的设置:

    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} .*[\ ].*
    RewriteRule (.*)[\ ](.*) $1_$2 [N]
    

    适合我(http://localhost/test/This is an example.html,在VirtualHost config,apache 2.2.14中重写规则。这是我的RewriteLogRewriteLogLevel 2}:

    init rewrite engine with requested uri /test/This is an example.html
    rewrite '/test/This is an example.html' -> '/test/This is an_example.html'
    rewrite '/test/This is an_example.html' -> '/test/This is_an_example.html'
    rewrite '/test/This is_an_example.html' -> '/test/This_is_an_example.html'
    local path result: /test/This_is_an_example.html
    prefixed with document_root to D:/var/www/test/This_is_an_example.html
    go-ahead with D:/var/www/test/This_is_an_example.html [OK]
    

    D:/var/www/test/This_is_an_example.html不存在时,我得到404 - 但没有段错误。

    你能发布RewriteLog吗?你把重写规则放在哪里?变成.htaccess?你有任何指令(AliasMatch等)也适用于你的网址吗?

答案 1 :(得分:0)

尝试绝对替代:

RewriteRule ^([^\ ]*)\ (.*) /$1_$2 [N]

答案 2 :(得分:0)

总的来说,如果提供可重复的测试用例,Apache开发人员将非常认真地对待httpd中的SIGSEGV。如果您附加调试器并捕获回溯,则更是如此。