Re: How do I create friendlier URLS?
by wfsp (Abbot) on Feb 22, 2007 at 11:25 UTC
|
http://www.mydomain.com/index.cgi/loadpage/10
A bit friendlier? | [reply] [d/l] [select] |
Re: How do I create friendlier URLS?
by rhesa (Vicar) on Feb 22, 2007 at 13:57 UTC
|
CGI::Application::Dispatch is awesome! This weekend, I built a REST interface to (parts of) our application, and it was a breeze.
Let's assume you have a CGI::Application module called My::App, and that your index.cgi looks like this:
#!/usr/bin/perl
use My::App;
My::App->new->run;
In this situation, you would need a new instance script for every new application module. CA::Dispatch takes that pain away by giving you the means to write a single dispatch script for all your appllications.
An example for your case might be:
#!/usr/bin/perl
use CGI::Application::Dispatch;
CGI::Application::Dispatch->dispatch(
prefix => 'My',
default => 'App',
);
If you save that script as index.cgi, your URL could become http://www.mydomain.com/index.cgi/loadPage?data=10.
By using more of CA::Dispatch's power, you can take that even further:
#!/usr/bin/perl
use CGI::Application::Dispatch;
CGI::Application::Dispatch->dispatch(
prefix => 'My',
table => [
'/:rm/:data?' => { app => 'App' },
],
);
This dispatch script would be able to map the following URL: http:://www.mydomain.com/index.cgi/loadPage/10. The runmode is taken from the first part of the PATH_INFO (that's what the ":rm" indicates), and the page number is captured by the ":data?". You can access the page number in your runmode with $self->param('data').
The final step would be to get rid of the "index.cgi" part in your URL, but for that you do need to edit your web server config. I generally use mod_rewrite (as I do a lot of mappings), but a suitable <Location> section would suffice as well. The CGI::Application::Dispatch documentation has some examples for you.
| [reply] [d/l] [select] |
|
By the true definition of REST, that's not a pure REST interface. One of the principles of REST is to not use any verbs in your resource name because the HTTP request is the verb.
To make your app truly RESTful, use page/10 instead of loadPage/10. An HTTP GET request should signify "load", HTTP DELETE for "delete", and so forth.
There is some dissonance on whether POST or PUT should be used for insert or update, but the idea is that the HTTP request provides the "verb", not the resource name.
And then, I haven't even touched on mime-types :)
Here's some more info: Wikipedia article on REST
| [reply] |
|
You're quite right about all of that, and I have applied those principles to my REST interface at work. But I didn't say the examples for the OP were REST :-)
CGI::Application::Dispatch has some extra features to make REST easier to implement (by attaching the HTTP verb to the runmode name, so you'd have page_GET, page_DELETE etc. as the real run modes, dispatched from the single /page url). I don't think it's relevant to the OP's question though, and would probably confuse the issue.
By the way, I really, really like the REST approach. It encourages a clear, uncluttered implementation on the backend, and it's very simple to integrate the resulting resources into other applications. Compared to SOAP, REST is a lot cleaner ;)
I also found the columns on xml.com helpful in gaining a more practical understanding of the REST philosophy.
| [reply] [d/l] [select] |
Re: How do I create friendlier URLS?
by shmem (Chancellor) on Feb 22, 2007 at 11:11 UTC
|
Without mod_rewrite it will be difficult to shoehorn a full path into a CGI invocation.
But you could use
http://www.mydomain.com/?loadPage/10/
and process $ENV{QUERY_STRING} yourself, after adding your cgi to DirectoryIndex.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] [select] |
Re: How do I create friendlier URLS?
by rkrieger (Friar) on Feb 22, 2007 at 13:20 UTC
|
Granted, I'm suggesting something else than CGI::Application about which I know little. I do not know the scope or size of what you already have running, so YMMV.
You could look into HTML::Mason and its concept of dhandlers and autohandlers.
Using a dhandler, you can use the URLs of the form you indicated, while passing parameters with those URLs to a single script/component. For example: a URL of the form http://example.com/archives/753/pdf only requires a suitable dhandler in /archives/ that obtains the document with ID 753 and displays the PDF file stored for it.
Update: Added simple day-to-day example
| [reply] |
|
I especially enjoy this aspect of Mason. Not the reason I'm using it, and I'm not sure the overhead would be worth it for just this feature, but it's worth a look.
Mason does this by jumping in and handling certain URLs, then parsing them to try and find the best match for the request. No need to state parameters explicitly with a ? or reveal the handler's name in the URL. It can even be configured in a local .htaccess file if you're working with apache in an environment where you don't have access to the httpd.conf.
Assuming apache, here's an example .htaccess:
order allow,deny
allow from all
Options -Indexes -ExecCGI
#Server root relevant path to handler script
Action my-handler /test/my_handler.pl
SetHandler my-handler
AddHandler default-handler .html .gif .jpg .png
<FilesMatch "my_handler.pl$">
Options +ExecCGI
SetHandler cgi-script
</FilesMatch>
And an example my_handler.pl- not very useful as is, but dispatch with your new parameters as you like:
#!/usr/bin/perl -wT
use strict;
print "Content-type: text/html\n\n";
print "<p>Request_URI contained: " . join( ' ', map {"[$_]"} split '/'
+, $ENV{REQUEST_URI}) . "</p>\n";
print "$_ => $ENV{$_}<br />\n" for sort keys %ENV;
Don't forget that the parameters will be encoded...
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?" - Henry David Thoreau, Walden
| [reply] [d/l] [select] |
Re: How do I create friendlier URLS?
by MikeDorset (Initiate) on Feb 22, 2007 at 23:27 UTC
|
On an Apache Server you can use REWRITE in an .htaccess file located in your www root directory.
file: .htaccess
#start the engine
RewriteEngine on
#this needs to be set to allow the URL manipulation
Options +FollowSymlinks
#the directory the manipulations will take place on
RewriteBase /
# mod_rewrite allows you to use Regular Expressions
# to define the manipulations
RewriteRule ^(.*\.html)$ cgi-bin/foo.cgi?call=$1
So http://www.mydomain.com/bar ends up as http://www.mydomain.com/cgi-bin/foo.cgi?call=bar.html
see:
http://httpd.apache.org/docs/2.0/misc/rewriteguide.html
| [reply] [d/l] [select] |
|
I know you can use mod_rewrite for this but I don't have access to it
| [reply] |
Re: How do I create friendlier URLS?
by zigdon (Deacon) on Feb 23, 2007 at 06:43 UTC
|
I think you can always just make your CGI the index.cgi in a directory, and then access the rest of the path supplied in the URL using CGI.pm:
In index.cgi:
...
my $q = new CGI;
my $path = $q->url(-relative => 1, -path=>1);
# $path = "index.cgi/loadPage/10"
| [reply] [d/l] |
Re: How do I create friendlier URLS?
by Anonymous Monk on Feb 23, 2007 at 08:28 UTC
|
Add the following line to your httpd.conf file. Be sure it is outside of any <directory> containers. Then restart the server:
ScriptAlias /loadpage "/absolute path from root to/index.cgi"
Now you can call urls as:
http://www.mydomain.com/loadpage?10
The 10 will be the value of $ENV{QUERY_STRING} in index.cgi
| [reply] [d/l] [select] |
Re: How do I create friendlier URLS?
by Anonymous Monk on Feb 23, 2007 at 10:17 UTC
|
Create .htaccess file in the document root directory i.e. the directory www.mydomain.com points to. Put the rewrite directives in .htaccess file. Use this method when you do not have access to the httpd.conf file.
Most web hosting servers have the mod_rewrite installed and running for this stituation. If not ask then to install it and set mod_rewrite directives in the .htaccess file.
| [reply] [d/l] [select] |