CleanUrls

Summary: Enable URLs that are shorter (without .php) and/or look like paths to wiki pages.
Version: 2007-04-11
Prerequisites: pmwiki-2.0.0
Maintainer: Hagan Fox
Discussion: CleanUrls-Talk
Users: +7 (View / Edit)
Categories: Administration, PHP72

Questions answered by this recipe

  • How do I enable "Clean URLs" that are shorter and look like paths to my wiki pages?
  • How do I configure PmWiki so it runs from my web server's document root (/)?

Here's what I have now:

http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage

I'd rather have one of these:

http://www.example.com/~someuser/pmwiki/Main/HomePage
http://www.example.com/~someuser/Main/HomePage
http://www.example.com/Main/HomePage

If that's not possible on my server, I'd like to have one of these:

http://www.example.com/~someuser/pmwiki/?n=Main.HomePage
http://www.example.com/~someuser/?n=Main.HomePage
http://www.example.com/?n=Main.HomePage

Discussion

(Too impatient for background information? Skip right to some examples.)

Shortening your URLs can be separated into three issues:

  1. Turning, for example, ?n=Main.HomePage into /Main/HomePage .
  2. Removing the pmwiki.php part.
  3. Removing portions of the path, even all the way up to the server's document root.

This page offers three approaches to URL-shortening. The first two approaches address all three issues on an Apache server. The third approach is for any server, addressing issue #2 and issue #3 without requiring any extra server configuration.

  • URL Rewriting (mod_rewrite + .htaccess (or httpd.conf, or apache2.conf))
    • Most popular approach.
    • Addresses all three issues.
    • Requires Apache's mod_rewrite module.
    • Requires server configuration using .htaccess (or httpd.conf, or apache2.conf).
  • Aliases (mod_alias + httpd.conf or apache2.conf)
    • Server-administrator experience is highly recommended.
    • Addresses all three issues.
    • Requires Apache's mod_alias module.
    • Requires server configuration via httpd.conf or apache2.conf with a restart.
  • An Index File (index.php wrapper script)
    • Addresses issue #2 and issue #3.
    • Rarely requires extra server configuration.
  • Wrapper using MultiViews (a variation on the previous solutions)
    • An alternative for hosted PmWikis where Apache Rewrite Rules are not available
    • Addresses the first two issues
    • Does not require an .htaccess file
    • Does not require mod_rewrite nor mod_alias
    • Requires that Apache Multiviews are turned on (which is true by default)

URL Rewriting (mod_rewrite + .htaccess)

URL rewriting requires Apache's mod_rewrite module (otherwise see this section). Your server must also allow you to override default settings using a .htaccess file. (See this note if it's not enabled).

If you use the Windows internet server, IIS, instead of Apache, see this example.

The Apache (.htaccess) and PmWiki (local/config.php) configurations must match one another. In .htaccess you'll define some rewrite rules so requests for pages will be properly delivered to pmwiki.php. In local/config.php you'll turn on $EnablePathInfo and define the $ScriptUrl so PmWiki will generate properly-formatted links.

The following three examples are all for the same PmWiki installation. You'll place the .htaccess file in the directory that will correspond the shortest URL that will reach the wiki.

  Wiki's directory:  /home/someuser/public_html/pmwiki/
Wiki's Default URL:  http://www.example.com/~someuser/pmwiki/pmwiki.php
       Example One:  http://www.example.com/~someuser/pmwiki/.htaccess
       Example Two:  http://www.example.com/~someuser/.htaccess
     Example Three:  http://www.example.com/.htaccess

These examples don't require an index.php file.

Example One: .htaccess and pmwiki.php in the Same Directory

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/~someuser/pmwiki/Main/HomePage

Here's the .htaccess file. For this example it goes in the same directory as pmwiki.php:

# Use mod_rewrite to enable "Clean URLs" for a PmWiki installation.
RewriteEngine On
# Define the rewrite base.
RewriteBase /~someuser/pmwiki
# Send requests without parameters to pmwiki.php.
RewriteRule ^$           pmwiki.php  [L]
# Send requests for index.php to pmwiki.php.
RewriteRule ^index\.php$ pmwiki.php  [L]
# Send requests to pmwiki.php, appending the query string part.
RewriteRule ^([A-Z0-9\xa0-\xff].*)$ pmwiki.php?n=$1  [QSA,L]
Note: The RewriteBase line may not be required in some setups, so one can omit it.

Also, some installations may need to use [B,QSA,L] on the last line.

Here's the matching local/config.php file:

<?php if (!defined('PmWiki')) exit();
## Use "Clean URLs".
$EnablePathInfo = 1;
$ScriptUrl = "http://www.example.com/~someuser/pmwiki";
## more configuration settings...
Note: For wikis serving content via HTTP and HTTPS it's better to use this $ScriptUrl:
$ScriptUrl = $UrlScheme.'://'.$_SERVER['HTTP_HOST'].'/~someuser/pmwiki';

Example Two: .htaccess in the Directory Above the Wiki's Directory

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/~someuser/Main/HomePage

Here's the .htaccess file. In this example it goes in the directory above the one that contains pmwiki.php.

# Use mod_rewrite to enable "Clean URLs" for a PmWiki installation.
RewriteEngine On
# Define the rewrite base.  It's not necessarily PmWiki's directory.
RewriteBase /~someuser
# Send requests without parameters to pmwiki.php.
RewriteRule ^$           pmwiki/pmwiki.php  [L]
# Send requests for index.php to pmwiki.php.
RewriteRule ^index\.php$ pmwiki/pmwiki.php  [L]
# Send requests to pmwiki.php, appending the query string part.
RewriteRule ^([A-Z0-9\xa0-\xff].*)$ pmwiki/pmwiki.php?n=$1  [QSA,L]

Note, some installations may need to use [B,QSA,L] on the last line.

Here's the matching local/config.php file:

<?php if (!defined('PmWiki')) exit();
## Use "Clean URLs".
$EnablePathInfo = 1;
$ScriptUrl = "http://www.example.com/~someuser";
## more configuration settings...

Example Three: .htaccess in the Site's Document Root

(Chances are you won't want to actually install PmWiki in the document root directory.)

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/Main/HomePage

Here's the .htaccess file. In this example it goes in the web document root directory.

# Use mod_rewrite to enable "Clean URLs" for a PmWiki installation.
RewriteEngine On
# The rewrite base will be the document root.
RewriteBase /
# Send requests without parameters to pmwiki.php.
RewriteRule ^$           ~someuser/pmwiki/pmwiki.php  [L]
# Send requests for index.php to pmwiki.php.
RewriteRule ^index\.php$ ~someuser/pmwiki/pmwiki.php  [L]
# Send requests to pmwiki.php, appending the query string part.
RewriteRule ^([A-Z0-9\xa0-\xff].*)$ ~someuser/pmwiki/pmwiki.php?n=$1  [QSA,L]

Note, some installations may need to use [B,QSA,L] on the last line.

Here's the matching local/config.php file:

<?php if (!defined('PmWiki')) exit();
## Use "Clean URLs".
$EnablePathInfo = 1;
$ScriptUrl = "http://www.example.com";
## more configuration settings...

Serving Existing Content

The final rewrite rule in the examples above sends any request that begins with other than a lower-case letter to PmWiki, which may interfere with delivering some of your site's existing content. You can insert the following lines directly above the final RewriteRule and its comment to restore the ability to serve the existing content directly:

# Don't rewrite requests for any files, directories, or symbolic
# links (shortcuts) that exist on the filesystem.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l

Example Four: Using Internet Information Server (IIS)

Andrew Janke contributed this example for IIS 7.5:

Put the following as Web.config in your website base directory. Note that the ignoreCase="false" is especially important and by default the rules seem to have this on. This of course doesn't work as things like /pub/uploads also get rewritten and you don't want that. In theory you only need the last rule (rule 4L) but the others will likely be useful as well for a standard pmwiki install

   <?xml version="1.0" encoding="utf-8"?>
   <configuration>
      <system.webServer>
         <rewrite>
         <rules>

         <!-- for favicon.ico -- not strictly needed -->
         <rule name="rule 1L" stopProcessing="true">
            <match url="^favicon\.ico$" ignoreCase="false" />
            <action type="Rewrite" url="/pub/favicon.ico" logRewrittenUrl="false" />
         </rule>

         <!-- Send requests for blank to pmwiki.php -->
         <rule name="rule 2L" stopProcessing="true">
            <match url="^$" ignoreCase="false" />
            <action type="Rewrite" url="/pmwiki.php" logRewrittenUrl="false" />
         </rule>

         <!-- Send requests for index.php to pmwiki.php -->
         <rule name="rule 3L" stopProcessing="true">
            <match url="^index\.php" ignoreCase="false" />
            <action type="Rewrite" url="/pmwiki.php" logRewrittenUrl="false" />
         </rule>

         <!-- Send requests for pages to pmwiki.php -->
         <rule name="rule 4L" stopProcessing="true">
            <match url="^([A-Z].*)" ignoreCase="false" />
            <action type="Rewrite" url="/pmwiki.php?n={R:1}" appendQueryString="true" logRewrittenUrl="false" />
         </rule>

         </rules>
         </rewrite>
      </system.webServer>
   </configuration>

Aliases (mod_alias + .httpd.conf)

If you want to have Clean URLs without using mod_rewrite you can use mod_alias instead. if you can't use either mod_rewrite or mod_alias, try using an index.php wrapper script.

Aliases are configured in the main Apache configuration file (typically named httpd.conf). You probably shouldn't modify that file unless you know what you are doing. If you do, remember to restart your server after each change.

Here are examples that for PmWiki file locations similar to the other examples on this page.

One Alias

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/wiki/Main/HomePage

Place the following lines in your httpd.conf file:

<IfModule mod_alias.c>
  Alias /wiki /home/someuser/public_html/pmwiki/pmwiki.php
</IfModule>

Here's the matching local/config.php file:

<?php if (!defined('PmWiki')) exit();
## Use "Clean URLs".  Match the following in "httpd.conf":
##   Alias /wiki /home/someuser/public_html/pmwiki/pmwiki.php
$EnablePathInfo = 1;
$ScriptUrl = "http://www.example.com/wiki";
$PubDirUrl = "http://www.example.com/~someuser/pmwiki/pub";
$UploadDir = "/home/someuser/public_html/pmwiki/uploads";
$UploadUrlFmt = "http://www.example.com/~someuser/pmwiki/uploads";
## more configuration settings...

Two Aliases

You can configure a second alias that will map to your site's directory. To do that, place the following lines in your httpd.conf file:

<IfModule mod_alias.c>
  Alias /wiki   /home/someuser/public_html/pmwiki/pmwiki.php
  Alias /files/ /home/someuser/public_html/pmwiki/
</IfModule>

Here's the matching local/config.php file:

<?php if (!defined('PmWiki')) exit();
## Use "Clean URLs".  Match the following in "httpd.conf":
##   Alias /wiki    /home/someuser/public_html/pmwiki/pmwiki.php
##   Alias /files/  /home/someuser/public_html/pmwiki/
$EnablePathInfo = 1;
$ScriptUrl = "http://www.example.com/wiki";
$PubDirUrl = "http://www.example.com/files/pub";
$UploadDir = "/home/someuser/public_html/pmwiki/uploads";
$UploadUrlFmt = "http://www.example.com/files/uploads";
## more configuration settings...

Using an Index File (index.php Wrapper Script)

You can shorten your site's URLs without $EnablePathInfo by adding an index.php file and configuring your site so neither pmwiki.php nor index.php appears in URLs.

Eliminating "pmwiki.php" From URLs

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/~someuser/pmwiki/?n=Main.HomePage

Here's an index.php file that belongs in the directory with pmwiki.php:

<?php include_once('pmwiki.php');

Here's the matching local/config.php file:

<?php if (!defined('PmWiki')) exit();
## Eliminate "pmwiki.php" from URLs.
$EnablePathInfo = 0;
$ScriptUrl = "http://www.example.com/~someuser/pmwiki/";
## more configuration settings...

Shortening or Altering the Path and Eliminating "pmwiki.php"

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/~someuser/?n=Main.HomePage

Here's an index.php file for the directory that will correspond to shortest URL that will reach the wiki (/home/someuser/public_html/ in this example):

<?php chdir('pmwiki'); include_once('pmwiki.php');

Here's the matching local/config.php file, which sets some extra paths because index.php and pmwiki.php are not in the same directory:

<?php if (!defined('PmWiki')) exit();
## Shorten the path and eliminate "pmwiki.php" from URLs.
$EnablePathInfo = 0;
$ScriptUrl = "http://www.example.com/~someuser/";
$PubDirUrl = "http://www.example.com/~someuser/pmwiki/pub";
$UploadDir = "/home/someuser/public_html/pmwiki/uploads";
$UploadUrlFmt = "http://www.example.com/~someuser/pmwiki/uploads";
## more configuration settings...

You can put an index file in any directory, including the document root, as long as the path in the index file points to your wiki's directory and the $ScriptUrl in config.php matches.

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/~someuser/wiki/?n=Main.HomePage

Here's an index.php file for the corresponding directory (/home/someuser/public_html/wiki/ in this example):

<?php chdir('../pmwiki'); include_once('pmwiki.php');

Other than (obviously) $ScriptUrl, the config.php example would be the same as above.

Lighttpd

Before: http://www.example.com/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/wiki/Main/HomePage 

1. Add the following to lighttpd.conf

url.rewrite-once = ( "^/wiki/?([^?]*)$" => "/pmwiki.php?n=$1",
"^/wiki/?([^?]*)[?](.*)$" => "/pmwiki.php?n=$1&$2",
 )

2. Modify your local/config.php:

<?php
  $EnablePathInfo = 1;
  $ScriptUrl      = "http://$_SERVER[HTTP_HOST]/wiki";
  ...

WorksForMe(TM). Remember that "/wiki" is a virtual path now, so don't have anything, i.e. catalogs or files that starts with wiki or you will get a collision.

Wrapper using Apache MultiViews

Some hosts (e.g. http://www.free.fr/) do not allow Rewrite Rules in .htaccess, but you can take advantage of Multiviews to simulate them. The following recipe will allow you to change the urls like this:

Before: http://www.example.com/~someuser/pmwiki/pmwiki.php?n=Main.HomePage
 After: http://www.example.com/~someuser/wiki/Main/HomePage 

1. Create a wiki.php file at the same level as your pmwiki/ directory:

<?php chdir('pmwiki'); include_once('pmwiki.php');

2. Modify your local/config.php:

<?php
  $EnablePathInfo = 1;
  $ScriptUrl      = "http://$_SERVER[HTTP_HOST]/~someuser/wiki";
  $PubDirUrl      = "http://$_SERVER[HTTP_HOST]/~someuser/pmwiki/pub";
  ...

That's all folks! Beware that your .php wrapper's name does not collide with any directory name.
E.g.: if you name it pmwiki.php, the directory will take precedence and the trick won't work.
And no, it doesn't work with Lighttpd (yet)

Notes

Other Path-related Settings

Sometimes it's not easy for PmWiki to guess all of your path locations and base URLs. You can set them in config.php using various variables such as $PubDirUrl, $UploadDir, and $UploadUrlFmt. Here are a few settings that might have been shown to the config.php examples above:

$PubDirUrl = "http://www.example.com/~someuser/pmwiki/pub";
$UploadDir = "/home/someuser/public_html/pmwiki/uploads";
$UploadUrlFmt = "http://www.example.com/~someuser/pmwiki/uploads";

Enabling .htaccess

If you want to enable the use of .htaccess in a /var/www/wiki directory, use the following in your Apache configuration file (typically named httpd.conf):

AccessFileName .htaccess
<Directory /var/www/wiki>
  AllowOverride FileInfo AuthConfig Limit
</Directory>

Instead of enabling .htaccess, the main Apache configuration file (typically httpd.conf) can be used to control Apache's rewriting engine, although you probably shouldn't try it unless you know what you are doing. If you want to try it, here's an example to get you started:

<IfModule mod_rewrite.c>
  <Directory /var/www/wiki>
    # Use mod_rewrite to enable "Clean URLs" for a PmWiki installation.
    [...the other lines...]
  </Directory>
</IfModule>

About the Regular Expression

The regular expression ^([A-Z0-9\xa0-\xff].*)$ used in the URL rewriting examples matches any path that starts with a capital letter, digit or UTF-8 character. It allows rewriting (passing to PmWiki) URLs like this one

http://www.example.com/Group/PageName

URLs like this one fall through so they're handled by Apache in the normal manner

http://www.example.com/pub/skins/pmwiki/pmwiki.css

Without this sort of restriction, all URLs would end up being rewritten and passed to PmWiki.

Another valid regular expression might be ([^/a-z].*) which matches any path that does not start with a lower-case letter or backslash.

Wiki Farms

Here are two important things to review about Wiki Farms:

  1. The wikis in a WikiFarm are separate wikis.
  2. The directory where PmWiki is installed doesn't need to be reachable via URL.

A URL for a wiki in a farm works the same as a URL for a stand-alone wiki. Rewrite rules work in the exact same manner except they point to the index.php wrapper script (or field.php in some older installations) instead of pmwiki.php. The .htaccess file for each wiki goes in the directory (filesystem location) that corresponds to the shortest URL that will reach that wiki..

Installing PmWiki in the document root's directory

document root
The "topmost" directory on your server's filesystem that is designated for holding web content. It's the directory where files are stored that are addressed by a "plain" URL. For example the file pmwiki.php in the document root would be addressed by http://www.example.com/pmwiki.php.

Generally speaking, it's usually best not to install the software in your server's web document root directory unless you have a specific reason. This is because installing PmWiki in your server's document root often complicates matters more it simplifies them. Upgrading could be less straightforward, it may not be obvious which subdirectories belong to PmWiki and which do not, and there are a few other concerns (backups, security, future expansion).

Fortunately, you can run PmWiki from the document root without installing it there.

Apache on Windows

TonyColley left this note about URL Rewriting Example Two for Apache-on-Windows users:

If you are using Apache on Windows, the above will work fine UNLESS your PmWiki is installed in a directory called "pmwiki" (with any or none of those letters capital letters). In that case, you will get a 404 (file not found) when you try to access any page in the PmWiki group (e.g. http://www.example.com/~someuser/PmWiki/InitialSetupTasks). There may be a way to fix the .htaccess file to eliminate this problem, but I simply renamed my "pmwiki" directory to "wiki" and everything works fine.

See Also

Contributors

Comments

See discussion at CleanUrls-Talk


Category: Administration

User notes : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.