http://qs1969.pair.com?node_id=290877

xiper has asked for the wisdom of the Perl Monks concerning the following question:

Please excuse the slightly off-topic post...

How do i set up a unix webserver so all accesses to a particular directory (and below) get *handled* by a perl script? (ie, similar to the way java servlet's can act)

For example:

http://www.domain.com/thedirectory/ => /cgi-bin/path/myscript.pl ('/') http://www.domain.com/thedirectory/foo => /cgi-bin/path/myscript.pl ('/foo') http://www.domain.com/thedirectory/foo/bar => /cgi-bin/path/myscript.pl ('/foo/bar')
or something to that effect.

Note that i dont want a simple redirection because that changes the url in the address bar, and doesn't give me access to the original path requested. Also, i need to do things like return images and http redirects so just inserting text into a shtml doc isn't likely to work. And, just to make things tricky, i don't have root access to this particular server...

Any comments appreciated!

- ><iper

my JAPH: print"Just another Perl hacker\n"; # ^ look, no space! pretty tricky huh?

Replies are listed 'Best First'.
Re: Perl script to handle requests to a http://.../path/*
by submersible_toaster (Chaplain) on Sep 12, 2003 at 01:33 UTC

    When writing a prototype web application I ran into a similar issue, for me paths were the crux of the matter, and urls like http://my.test.server/webapp/path/to/my/favorites to be much more sensible than http://my.test.server/cgi-bin/webapp.pl?path=/path/to/my/favorites

    The modperl pages are a wonderful resource. Specifically you might like to look at Location & SetHandler which can do what you need. Getting your admins to hack on the httpd.conf for you is an excersise for the reader :).


    I can't believe it's not psellchecked
Re: Perl script to handle requests to a http://.../path/*
by BigLug (Chaplain) on Sep 12, 2003 at 02:10 UTC
    A couple of ways:
    The 404 Error
    Apache lets you set a custom script to handle 404 errors. Just get all 404s sent to your perl script. They you can get the requested path from the ENV vars. Unfortunately this will make an entry in your error log every time.
    The DirectoryIndex
    Set the DirectoryIndex on the root directory to a perl script called thedirectory and set this to execute. The rest of the URL can then be read from the PATH_INFO env var. (I can't think quickly how to make thedirectory have a cgi flag though ...)
    ModRewrite
    Apache has a module ModRewrite that allows you to rewrite a request on the fly. It's not a relocate that changes the address in the user's browser but an actual server-side rewrite of the path. See http://httpd.apache.org/docs/misc/rewriteguide.html for examples.
Re: Perl script to handle requests to a http://.../path/*
by tachyon (Chancellor) on Sep 12, 2003 at 06:23 UTC

    You need mod_rewrite. If you have a stock RH 7.x apache you will have it already. If the fragment presented chokes (because mod_rewrite is not installed) you will need to recompile apache. From memory if you just want mod_rewrite you have to pass these flags to configure:

    ./configure --enable-module=rewrite --enable-shared=rewrite

    As always RTFM. Speaking of which if you want ssl, mod perl and mod_rewrite you will find a good description at http://perl.apache.org/docs/1.0/guide/install.html Note that you don't get the http://www.domain.com bit passed to mod_rewrite just /thedirectory/blah. We implement it like this using a VH container. We had some issues with it outside a VH container, even though the server is a dedicated one (no virtual hosts)

    <VirtualHost *> ServerName your.domain.com RewriteEngine on RewriteLog /var/log/httpd/rewrite.log RewriteLogLevel 1 RewriteRule ^/thedirectory(.*)$ http://your.domain.com/cgi-bin/scrip +t.pl?$1 </VirtualHost>

    In the rewrite rule we capture the bit after thedirectory in $1 to pass to our script. You can use a full http:// or a partial /cgi-bin rewrite path which will result in the user seeing or not seeing the redirect respectively (also from memory) We use the full path exteernal redirect for reasons that currently elude me ;-)

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      I've been playing around with mod_rewrite and it seems to be able to achieve what i'm after. That is, if i could get it working properly... :)

      At the risk of being flamed for pushing this thread further off-topic, could someone help me out with this?

      What i actually want to achieve is to redirect all accesses, using mod_rewrite, to a perl script, so: http://www.domain.com/foo/bar gets sent transparently to: /cgi-bin/myscript.pl?foo/bar

      What i have at the moment is a .htaccess (no root, remember) that contains:

      RewriteRule ^(.*)$ /cgi-bin/myscript.pl?$1 [L]
      However, this gets caught in a loop, despite the [L], giving a 500 with:
      mod_rewrite: maximum number of internal redirects reached. Assuming co +nfiguration error. Use 'RewriteOptions MaxRedirects' to increase the +limit if neccessary.
      It was my understanding (from RTFMing!) that [L] is meant to avoid this?!? Where have i gone wrong?

      Update: found a solution, chain a neg regex in front

      RewriteRule !^/cgi-bin - [C] RewriteRule ^(.*)$ /cgi-bin/myscript.pl?$1 [L]

      - ><iper

      my JAPH: print"Just another Perl hacker\n"; # ^ look, no space! pretty tricky huh?

        Just apply a RewriteCond that says NOT /cgi-bin/blah first. Then the RewriteRule will only get invoked on the first pass, not once it has been done (untested)...

        There are also other hooks to prevent looping (they let you see it this request is a subrequest of the original) but that should do the trick.

        RewriteCond ! ^/cgi-bin/myscript.pl.*$ RewriteRule ^(.*)$ /cgi-bin/myscript.pl?$1

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Perl script to handle requests to a http://.../path/*
by The Mad Hatter (Priest) on Sep 12, 2003 at 00:51 UTC
    To use your example...

    If you call the CGI script thedirectory.cgi, you should be able to configure Apache (it may be enabled by default even) to execute it when called as "thedirectory/foo/bar/baz". Once that is working, check out the path_info method of CGI.pm; it should let you fetch the last bit of the URL the script was called with (ex/ "/foo/bar/baz") so it can act accordingly.

Re: Perl script to handle requests to a http://.../path/*
by revdiablo (Prior) on Sep 12, 2003 at 02:24 UTC

    You might want to look into mod_rewrite for apache. It will do what you want and more. It's pretty neat -- you can transparently apply regular expressions to urls to rewrite them to whatever you want. So you could, for example, match /thedirectory/(.*) and rewrite it as some.cgi?blah=$1. The user sees a pretty url, and you get to use an arbitrary CGI. Very handy.

Re: Perl script to handle requests to a http://.../path/*
by BrowserUk (Patriarch) on Sep 12, 2003 at 02:39 UTC

    Webserver foo isn't my thing, but as noone else has mentioned this. Can't you add something like index.pl to the DirectoryIndex configuration option in the Apache httpd.conf file and have it invoke a script of that name (from the named directory) if a path is supplied without a specific document being named?

    You have to also enable the .pl as a CGI handler, but presumably this is already done.

    Thinking about it, maybe the "I don't have root access" stops you from taking this option, but I'm not sure, so I'll post this anyway.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

      Thinking about it, maybe the "I don't have root access" stops you from taking this option, but I'm not sure, so I'll post this anyway.
      Most ISPs let you create .htaccess files in each directory. Just put the DirectoryIndex option into the root .htaccess and you're on your way. The trickier thing is getting it to recognise files with no extension as CGI scripts.