CleanUrls
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:
- Turning, for example, ?n=Main.HomePage into /Main/HomePage .
- Removing the pmwiki.php part.
- 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]
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...
$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:
- The wikis in a WikiFarm are separate wikis.
- 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 byhttp://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:
See Also
- The CleanUrls-Talk page.
- The old Clean Urls page.
- The Apache mod_rewrite module's manual page
- The Apache mod_alias module's manual page
- The Apache .htaccess tutorial (Apache 1.3 version)
- For rewriting with the alternative web server Lighttpd, see the lighttpd wiki. (That recipe might not work well with internationalized character sets, or with page names that start with special characters.)
- GetRidOfMain
Contributors
- Hagan Fox (and many others who contributed to the old version of this page)
Comments
See discussion at CleanUrls-Talk
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.