apache - Understanding `mod_rewrite`: internally redirect `foo.txt` to `foo.txt.cgi` where `foo.txt` doesn't exist? -
my goal serve .txt
files out of directory, particular .txt
file not exist, want perform internal redirect named .txt.cgi
script, if such script exists. question pertains why 1 approach seems work, 2 alternate approaches not work.
i have following directory structure (i.e., subdirectory somewhere in /var/www
or equivalent):
% 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
in each test{1,2,3}
subdirectory plain old text file.
test.txt.cgi
in each test{1,2,3}
subdirectory contains:
#!/usr/bin/env sh cat <<eof content-type: text/plain hi! i'm \`${0}\`! eof
test1/.htaccess
follows:
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
same test1/.htaccess
, moves +execcgi
top level (i 403
if use <files>
) , adds [h=cgi-script]
flag rewriterule
:
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]
the mod_rewrite
documentation h
flag suggests should work.
test3/.htaccess
same test1/.htaccess
, enables +multiviews
option:
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"
unsurprisingly, of other.txt
files resolve without issue:
% in 1 2 3 ; echo "----> ${i} <----" ; curl --location --post30{1,2,3} --silent "http://localhost/~posita/rewritecgi/test${i}/other.txt" ; done ----> 1 <---- plain old text file. ----> 2 <---- plain old text file. ----> 3 <---- plain old text file.
all 3 test.txt.cgi
scripts run when called explicitly:
% in 1 2 3 ; 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`!
however, http://localhost/~posita/rewritecgi/test1/test.txt
redirects cgi:
% in 1 2 3 ; 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 not found on 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 not found on server.</p> </body></html>
with rewriteloglevel 9
following log messages 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)$' 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 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 replace prefix /.../posita/public_html/rewritecgi/test2/ /~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 /~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 have 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 stat: redirect:/~posita/rewritecgi/test2/test.txt.cgi
and 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)$' 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 negotiated).
so gives? why adding [h=cgi-script]
cause test2
not call cgi? test3
, why enabling +multiviews
circumvent mod_rewrite
? know mod_rewrite
voodoo, want understand nuances between these situations.
multiviews option files in other directories if not found in current one. implies finding results not restricted same directory, not circumvents mod_rewrite. uses mod_negotiation. using option multiviews let server choose, based on pattern best file chose. not situation imo after when using .htaccess , mod_rewrite. never use it.
what noticed rewriteconds in .htaccess. not required. got working without them. more specify in .htaccess, more problems can have. (rewrite can voodoo indeed.) made .htaccess file without conditions , worked:
options +execcgi addhandler cgi-script .cgi rewriteengine on rewritebase /stackoverflowquestions/tests/cgi/ rewriterule ^(.*)\.txt$ $1.cgi [l]
that enough make working. rewriterule resolving same filename extension , not filename + extension. in handler tag [h...] need specify mime-type of cgi file. application/x-httpd-cgi, not cgi-script. not need specify h-flag when use addhandler.
Comments
Post a Comment