我的目标是从目录中提供.txt
个文件,但如果某个.txt
文件不存在,我想执行 内部 < / strong>重定向到类似名称的.txt.cgi
脚本,如果存在这样的脚本。这个问题涉及为什么一种方法似乎有效,但两种替代方法 工作。
我有以下目录结构(即,作为/var/www
中的某个子目录或等效目录):
% ls -ARl rewritecgi
total 0
drwxr-sr-x 2 posita posita 170 Mar 16 14:36 test1
drwxr-sr-x 2 posita posita 170 Mar 16 14:38 test2
drwxr-sr-x 2 posita posita 170 Mar 16 14:38 test3
rewritecgi/test1:
total 24
-rw-r--r-- 1 posita posita 288 Mar 16 14:36 .htaccess
-rw-r--r-- 1 posita posita 28 Mar 16 14:34 other.txt
-rwxr-xr-x 1 posita posita 143 Mar 16 14:20 test.txt.cgi
rewritecgi/test2:
total 24
-rw-r--r-- 1 posita posita 301 Mar 16 14:38 .htaccess
-rw-r--r-- 1 posita posita 28 Mar 16 14:34 other.txt
-rwxr-xr-x 1 posita posita 143 Mar 16 14:19 test.txt.cgi
rewritecgi/test3:
total 24
-rw-r--r-- 1 posita posita 288 Mar 16 14:38 .htaccess
-rw-r--r-- 1 posita posita 28 Mar 16 14:34 other.txt
-rwxr-xr-x 1 posita posita 143 Mar 16 14:20 test.txt.cgi
每个other.txt
子目录中的 test{1,2,3}
只是一个普通的旧文本文件。
test.txt.cgi
子目录中的 test{1,2,3}
包含:
#!/usr/bin/env sh
cat <<EOF
Content-Type: text/plain
Hi! I'm \`${0}\`!
EOF
test1/.htaccess
如下:
Options +FollowSymlinks -Indexes -MultiViews
AddHandler cgi-script .cgi
RewriteEngine on
RewriteBase /~posita/rewritecgi/test1/
<Files ~ "\.cgi$">
Options +ExecCGI
</Files>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule "^(.*\.txt)$" "$1.cgi"
test2/.htaccess
与test1/.htaccess
相同,但会将+ExecCGI
移至顶层(如果我使用403
,我会获得<Files>
)并添加[H=cgi-script]
的{{1}}标记:
RewriteRule
mod_rewrite
documentation for the H
flag表明这应该有用。
Options +ExecCGI +FollowSymlinks -Indexes -MultiViews
AddHandler cgi-script .cgi
RewriteEngine on
RewriteBase /~posita/rewritecgi/test2/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule "^(.*\.txt)$" "$1.cgi" [H=cgi-script]
与test3/.htaccess
相同,但启用test1/.htaccess
选项:
+MultiViews
不出所料,所有Options +FollowSymlinks -Indexes +MultiViews
AddHandler cgi-script .cgi
RewriteEngine on
RewriteBase /~posita/rewritecgi/test3/
<Files ~ "\.cgi$">
Options +ExecCGI
</Files>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule "^(.*\.txt)$" "$1.cgi"
个文件都没有问题解决:
other.txt
显式调用时,所有三个% for i in 1 2 3 ; do echo "----> ${i} <----" ; curl --location --post30{1,2,3} --silent "http://localhost/~posita/rewritecgi/test${i}/other.txt" ; done
----> 1 <----
Just a plain old text file.
----> 2 <----
Just a plain old text file.
----> 3 <----
Just a plain old text file.
脚本都正常运行:
test.txt.cgi
但是,只有% for i in 1 2 3 ; do echo "----> ${i} <----" ; curl --location --post30{1,2,3} --silent "http://localhost/~posita/rewritecgi/test${i}/test.txt.cgi" ; done
----> 1 <----
Hi! I'm `/.../posita/public_html/rewritecgi/test1/test.txt.cgi`!
----> 2 <----
Hi! I'm `/.../posita/public_html/rewritecgi/test2/test.txt.cgi`!
----> 3 <----
Hi! I'm `/.../posita/public_html/rewritecgi/test3/test.txt.cgi`!
重定向到CGI:
http://localhost/~posita/rewritecgi/test1/test.txt
使用% for i in 1 2 3 ; do echo "----> ${i} <----" ; curl --location --post30{1,2,3} --silent "http://localhost/~posita/rewritecgi/test${i}/test.txt" ; done
----> 1 <----
Hi! I'm `/.../posita/public_html/rewritecgi/test1/test.txt.cgi`!
----> 2 <----
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /~posita/rewritecgi/test2/test.txt was not found on this server.</p>
</body></html>
----> 3 <----
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /~posita/rewritecgi/test3/test.txt was not found on this server.</p>
</body></html>
,我收到RewriteLogLevel 9
的以下日志消息:
http://localhost/~posita/rewritecgi/test2/test.txt
对于==> /var/log/apache2/rewrite_log <==
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (3) [perdir /.../posita/public_html/rewritecgi/test2/] strip per-dir prefix: /.../posita/public_html/rewritecgi/test2/test.txt -> test.txt
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (3) [perdir /.../posita/public_html/rewritecgi/test2/] applying pattern '^(.*\\.txt)$' to uri 'test.txt'
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (4) [perdir /.../posita/public_html/rewritecgi/test2/] RewriteCond: input='/.../posita/public_html/rewritecgi/test2/test.txt' pattern='!-f' => matched
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (4) [perdir /.../posita/public_html/rewritecgi/test2/] RewriteCond: input='/.../posita/public_html/rewritecgi/test2/test.txt' pattern='!-d' => matched
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (2) [perdir /.../posita/public_html/rewritecgi/test2/] rewrite 'test.txt' -> 'test.txt.cgi'
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (3) [perdir /.../posita/public_html/rewritecgi/test2/] add per-dir prefix: test.txt.cgi -> /.../posita/public_html/rewritecgi/test2/test.txt.cgi
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (2) [perdir /.../posita/public_html/rewritecgi/test2/] remember /.../posita/public_html/rewritecgi/test2/test.txt.cgi to have Content-handler 'cgi-script'
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (2) [perdir /.../posita/public_html/rewritecgi/test2/] trying to replace prefix /.../posita/public_html/rewritecgi/test2/ with /~posita/rewritecgi/test2/
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (5) strip matching prefix: /.../posita/public_html/rewritecgi/test2/test.txt.cgi -> test.txt.cgi
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (4) add subst prefix: test.txt.cgi -> /~posita/rewritecgi/test2/test.txt.cgi
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (1) [perdir /.../posita/public_html/rewritecgi/test2/] internal redirect with /~posita/rewritecgi/test2/test.txt.cgi [INTERNAL REDIRECT]
127.0.0.1 - - [16/Mar/2015:15:30:42 --0700] [localhost/sid#7fb378812308][rid#7fb3788abea0/initial] (1) force filename redirect:/~posita/rewritecgi/test2/test.txt.cgi to have the Content-handler 'cgi-script'
==> /var/log/apache2/access_log <==
127.0.0.1 - - [16/Mar/2015:15:30:42 -0700] "GET /~posita/rewritecgi/test2/test.txt HTTP/1.1" 404 229
==> /var/log/apache2/error_log <==
[Mon Mar 16 15:30:42 2015] [error] [client 127.0.0.1] script not found or unable to stat: redirect:/~posita/rewritecgi/test2/test.txt.cgi
:
http://localhost/~posita/rewritecgi/test3/test.txt
那是什么给出的?为什么添加==> /var/log/apache2/rewrite_log <==
127.0.0.1 - - [16/Mar/2015:15:35:47 --0700] [localhost/sid#7fb378812308][rid#7fb37889aea0/subreq] (3) [perdir /.../posita/public_html/rewritecgi/test3/] strip per-dir prefix: /.../posita/public_html/rewritecgi/test3/test.txt.cgi -> test.txt.cgi
127.0.0.1 - - [16/Mar/2015:15:35:47 --0700] [localhost/sid#7fb378812308][rid#7fb37889aea0/subreq] (3) [perdir /.../posita/public_html/rewritecgi/test3/] applying pattern '^(.*\\.txt)$' to uri 'test.txt.cgi'
127.0.0.1 - - [16/Mar/2015:15:35:47 --0700] [localhost/sid#7fb378812308][rid#7fb37889aea0/subreq] (1) [perdir /.../posita/public_html/rewritecgi/test3/] pass through /.../posita/public_html/rewritecgi/test3/test.txt.cgi
==> /var/log/apache2/access_log <==
127.0.0.1 - - [16/Mar/2015:15:35:47 -0700] "GET /~posita/rewritecgi/test3/test.txt HTTP/1.1" 404 229
==> /var/log/apache2/error_log <==
[Mon Mar 16 15:35:47 2015] [error] [client 127.0.0.1] Negotiation: discovered file(s) matching request: /.../posita/public_html/rewritecgi/test3/test.txt (None could be negotiated).
会导致[H=cgi-script]
不调用CGI?对于test2
,为什么启用test3
规避+MultiViews
?我知道mod_rewrite
is voodoo,但我确实想了解这些情况之间的细微差别。
答案 0 :(得分:2)
如果在当前目录中找不到文件,则会在其他目录中查找文件。这意味着它找到结果并不局限于同一目录,而不是它绕过mod_rewrite。它使用mod_negotiation。使用Multiviews选项,服务器可以根据模式选择要选择的最佳文件。这不是你在使用.htaccess和mod_rewrite时所处的情况。我从不使用它。
我注意到你的.htaccess里有RewriteConds。它们不是必需的。我没有它就让它工作。你在.htaccess中指定的越多,你可以遇到的问题就越多。 (重写可能确实是伏都教。) 我在没有这些条件的情况下创建了一个.htaccess文件,它起作用了:
Options +ExecCGI
AddHandler cgi-script .cgi
RewriteEngine on
RewriteBase /StackoverflowQuestions/tests/cgi/
RewriteRule ^(.*)\.txt$ $1.cgi [L]
这足以让它发挥作用。现在,RewriteRule只解析了相同的文件名,而不是文件名+扩展名。 在处理程序标签[H ...]中,您需要指定cgi文件的mime类型。那是application / x-httpd-cgi,而不是cgi-script。但是在使用AddHandler时不需要指定H标志。