Pretty URLs

Pretty URLs are URLs that make it clear to a human what resource is being accessed, rather than the URL revealing the implementation details for how the server will dredge it up for them. Studs goes about halfway in providing support for pretty URLs, so maybe it is appropriate to call them prettier URLs. The Studs configuration provides a mapping between paths and responding actions. The query string, unfortunately, cannot be eliminated using the Studs ActionServlet, though conceivably and extension could be written that behaves in this fashion.

Understanding .htaccess

Before we even get into to talking about how to implement pretty URLs, it is first necessary to cover how Studs is configured by default. Of course, Studs is nothing more than a PHP script, so technically it doesn’t need an .htaccess file at all to work. However, to enhance security, the .htaccess file can be utilitized to emulate some of the restrictions typically applied by a Java Servlet environment. Studs channels all requests through the controlling script index.php. To enforce this restriction, a couple of Apache directives are added to the .htaccess file that ships with Studs.

<FilesMatch "^.*$">
    deny from all
</FilesMatch>

<FilesMatch "index\.php$">
    allow from all
</FilesMatch>

<FilesMatch "^$">
    allow from all
</FilesMatch>

These directives essentially prevent access to any file except for index.php, the front controller. Just like the Java Servlet model, Studs will forward to (internally redirect) or include all other resources.

Ah, but you might be asking yourself, “What about graphics, javascript files and stylesheets?” At this point you must make a decision. Either you can have Studs serve up these assets, or you can allow direct access to them. Obviously, it is more performant to allow access to them, so you will need one more directive in your .htaccess file, which is also included in the default configuration.

<FilesMatch "^.*\.(gif|jpeg|jpg|png|css|js|pdf|doc)$">
    allow from all
</FilesMatch>

If this relaxed directive is not applied, it will be necessary to instruct Studs that it will need to deliver these resources. In order to do so, you would ensure the following context parameter is enabled in the WEB-INF/web.xml file.

<context-param>
    <!-- only set to true if NOT using the additional directive to enable access to static assets -->
    <param-name>controlAllResources</param-name>
    <param-value>true</param-value>
</context-param>

Understand that these directives are not absolutely necessary to run Studs. If you are experiencing problems, the first thing you should do is disable them so that you can get down to the real problem. On some installations of apache, the third FilesMatch directive is not interpretted correctly, preventing access to the application all together. As a result, a 404 error occurs.

For testing, there is no reason why you cannot just disable these apache directives until you are more familiar with Studs and would like to re-enable this security.

The Challenge

In order to emulate the Java servlet model, it is necessary to push all requests through a central controller script or fuse. Once inside that script, the framework can takeover in processing the request and serving up the appropriate resource. The alternative is to create a bunch of different PHP files and have them each include a core set global scripts. Studs does not follow this approach, and therefore it would appear (to statistic engines) that the user is only accessing a single URL, differing only by the query string and path info.

Studs leverages the PATH_INFO portion of the URL (everything after the script and before the query string) to contruct its paths. Consider the following URL:

http://localhost/app/index.php/example.do

The stratus servlet container interprets this URL as a request for the path /example.do, which is everything after the controller script, index.php. There are a couple of problems with constructing URLs with this syntax. First off, all links must be aware of this controller script and must include it when contructing the URLs. Additionally, the URL looks confusing to both end users and developers.

The Solution: mod_rewrite

mod_rewrite is an Apache module which allows you to intercept and process requests before they are executed. It is possible to use mod_rewrite to eliminate the controller script from view. Setting this up is a two step process.

Begin by opening the .htaccess file at the root of the application’s folder (assume for this example the folder name is /app/). Next, add the following lines at the bottom of that file:

RewriteEngine On
RewriteBase /app/

RewriteCond %{REQUEST_URI} !(index.php) [NC]
RewriteCond %{REQUEST_URI} .*\.(do|psp)$ [NC]
RewriteRule ^(.*)$ /app/index.php/$1 [L]

<FilesMatch "^.*\.(do|psp)">
    allow from all
</FilesMatch>

Note: It is necessary to “hardcode” the context path (the application’s folder) and the servlet mapping *.do into the directive, so be sure the configuration is consistent.

These directives enable the mod_rewrite engine and capture all request URIs that end in either *.do or *.psp and inserts the controller script, index.php, before doing an internal redirect (end user does not see a change).

The second step is to tell the application not to worry about the controller script and go about life as though it doesn’t exist. This setting is made near the top of the /WEB-INF/web.xml file underneath any existing <context-param> elements.

<context-param>
    <param-name>useRewrite</param-name>
    <param-value>true</param-value>
</context-param>

Now studs will generate URLs without the index.php part, and rely on apache to insert it back in on each request. The URLs are now as pretty (and an exact mirror) of those generated by Jakarta Struts.

The Result

Now that mod_rewrite is setup to capture the requests and the application is no longer worrying about the controller script, the following request will actually be channelled through the controller script by mod_rewrite and the end user will be unaware that PHP is even being used.

http://localhost/app/example.do
 
howto/pretty_urls.txt · Last modified: 2006/10/19 02:18 by 68.50.139.221 (dallen)
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki