Shorter URL Cookbook
Different methods to hide
bin and
view etc. in the website URLs.
How to enable shorter URLs in Foswiki
This supplemental document describes how to enable shorter URLs on your Foswiki site. To do this, all you will need is access to your web server configuration file and direct access to LocalSite.cfg.
When implemented, this will change your view URLs from:
www.example.com/bin/view/Main/WebHome to
www.example.com/Main/WebHome.
If you're ready to tweak Foswiki.pm a bit, you can shorten links even more by dropping the default web name out of them, whether it's "Main" or not:
wiki.example.com/bin/view/DefaultWeb/NiceTopic to
wiki.example.com/NiceTopic.
All the hyperlinks on your Foswiki site which use the view script will also be displayed in this way.
It will
not change any other URLs (i.e edit, attach, oops, rdiff...). So the following
www.example.com/bin/edit/Main/WebHome will stay the same.
This might be seen as a limitation, however the main reason you would want this is so you can tell someone else how to get at a particular topic, without having to explain the
/bin/view bit. Also, this method is only three lines long, so you can't expect much more.
If you have to type
/bin/edit and other actions too often, you can shorten them, too. For example from
/bin/edit/ to
/e/.
Take a look at
Apache or
Ligghttpd sections bellow, depending on what web server you're using.
Apache
Option 1: Use overlapping aliases
This is the easiest solution with the least server impact but it does require a little twist in setting up Foswiki.
Normally, you would have these 2 lines (and directory settings) in your Apache configuration file:
ScriptAlias /URL/to/foswiki/bin "/path/to/server/foswiki-root/bin"
Alias /URL/to/foswiki "/path/to/server/foswiki-root"
/URL/to/foswiki could be an empty string, for when you want to serve just Foswiki on your (virtual) web server. The configuration would then be
ScriptAlias /bin "/path/to/server/foswiki-root/bin"
Alias / "/path/to/server/foswiki-root/"
The trick is to assume any URL under
/URL/to/foswiki is a Foswiki view URL, except for URLs under
/URL/to/foswiki/bin and
/URL/to/foswiki/pub. To do that, we
first define aliases for
bin and
pub, and
then specify that everything else is calling the view script:
ScriptAlias /URL/to/foswiki/bin "/path/to/server/foswiki-root/bin"
Alias /URL/to/foswiki/pub "/path/to/server/foswiki-root/pub"
Alias /URL/to/foswiki "/path/to/server/foswiki-root/bin/view"
<Directory "/path/to/server/foswiki-root/bin">
Options +ExecCGI
</Directory>
In case of a dedicated Foswiki web server, you'd write
ScriptAlias /bin "/path/to/server/foswiki-root/bin"
Alias /pub "/path/to/server/foswiki-root/pub"
Alias / "/path/to/server/foswiki-root/bin/view/"
<Directory "/path/to/server/foswiki-root/bin">
Options +ExecCGI
</Directory>
As you can see, it has a slightly counter-intuitive twist where the "regular" URLs are actually shortcuts for URLs under
bin.
This works without having to enable any special features in Apache, and has the added bonus of keeping any other Foswiki subdirectories out of the visible files on the web server.
Warning: There is a problem with this method if the prefix to your foswiki installation is the same as the name of a web. For example, you can't use
http://server/main/ as the short URL to your Foswiki installation. It will seem to work, but
http://server/main/Main/WebHome and any other topic under Foswiki won't work. The reason for this is rather technical: in
Foswiki.pm, the
PATH_INFO variable is stripped of the script name (in this case "/main") using a case-insensitive search.
- Moral: Don't use a prefix that is the same as the name of one of your webs. A "dedicated" setup is fine though.
Option 2: Use the URL rewrite engine
First, edit your httpd file and insert the following two lines somewhere:
RewriteEngine on
RewriteRule ^/([A-Z].*) /var/www/foswiki/bin/view/$1 [L] - Change /var/www/foswiki/bin/view to the path to your view script
This will check the incoming URL to see if it starts with an uppercase letter (i.e.
Main/WebHome). If it does, it will be rewritten to the view script (so
Main/WebHome becomes
/var/www/foswiki/bin/view/Main/WebHome). If it does not start with an uppercase letter (i.e.
bin/edit/Main/WebHome), nothing will be changed. Therefore, the original long view URLs (
www.example.com/bin/view/Main/WebHome) will still work as expected, not breaking any bookmarks.
Option 2a: Complete example with mod_rewrite
When you change this lines in your
LocalSite.cfg
$Foswiki::cfg{ScriptUrlPath} = '';
$Foswiki::cfg{ScriptUrlPaths}{view} = '';
and your rewrite rules to this
RewriteCond %{REQUEST_URI} !/foswiki/
RewriteRule ^/([a-z]*)/([A-Z].*) /foswiki/bin/$1/$2 [L,PT]
RewriteRule ^/([A-Z].*) /foswiki/bin/view/$1 [L,PT]
RewriteRule ^/$ /foswiki/bin/view [L,PT]
This version works on Dreamhost (it didn't like the initial '/') as well as works with config which caused an error with the above
RewriteRules:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !/foswiki/
RewriteRule ^([a-z][^/]*)(/[A-Z].*)? /foswiki/bin/$1$2 [L]
RewriteRule ^([A-Z].*) /foswiki/bin/view/$1 [L]
RewriteRule ^$ /foswiki/bin/view [L]
you can access your pages with short URL (just
http://wiki.example.com/Web/Topic). Other actions available on your site (all executable files in bin/ directory) can be called with URL like
http://wiki.example.com/action/Web/Topic, still preserving original (long) URL starting with
/foswiki/.
Option 2a: Complete example as .htaccess
Another version that works on Dreamhost, in a
.htaccess file in the site root.
Configure settings:
$Foswiki::cfg{ScriptUrlPath} = '/bin';
$Foswiki::cfg{ScriptUrlPaths}{view} = '';
.htaccess file:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^([^/.]+)$ /bin/xview/Main/$1 [L,NE]
RewriteRule ^Main/([^/.]+)$ http://site.com/$1 [L,NE]
RewriteRule ^(Sandbox|System|Trash|TWiki|MyWeb)/(.*?)$ /bin/xview/$1/$2 [L,NE]
# Special rule for Main
RewriteRule ^bin/view/Main/([^/.]+)$ http://site.com/$1 [L,NE]
RewriteRule ^bin/view$ http://site.com/ [L,NE]
# do not skip index.html - instead we are using a static (quickly loading) file
RewriteRule ^$ /bin/xview/Main/ [L,NE]
# test urls:
# http://site.com => http://site.com/
# http://site.com/Main/WebHome => http://site.com/WebHome
# http://site.com/bin/view => http://site.com/
# http://site.com/bin/view/Main/WebHome => http://site.com/WebHome
# http://site.com/bin/view/Sandbox/WebHome => http://site.com/Sandbox/WebHome
The file
bin/xview is a copy of
bin/view. For this specific site, Main web is the main public web with a special "root" url:
http://site.com/WebHome will access
http://site.com/bin/view/Main/WebHome.
Lighttpd
This example works for standard shortening, where links contain both web and topic names, like
http://wiki.example.com/WebName/TopicName:
server.modules += ( "mod_rewrite", "mod_cgi" )
$HTTP["host"] == "wiki.example.org" {
server.document-root = "/usr/local/www/foswiki"
url.rewrite-once = (
"^/e/([A-Z_].*)" => "/bin/edit/$1",
"^/([A-Z_].*)" => "/bin/view/$1",
"^/pub/System/(.*)" => "/pub/System/$1",
"^/pub/(.*?)/([^/]+)$" => "/bin/viewfile/$1?filename=$2" )
url.rewrite-repeat = ( "^/?(index.*)?$" => "/Main" )
$HTTP["url"] =~ "^/bin" { cgi.assign = ( "" => "" ) }
}
This example works for extra shortening, where links to topics within a particular "default" web do not contain web name, like
http://wiki.example.com/TopicName, but links to topics in other webs contain both web and topic names:
server.modules += ( "mod_rewrite", "mod_cgi" )
$HTTP["host"] == "wiki.example.org" {
server.document-root = "/usr/local/www/foswiki"
url.rewrite-once = (
"^/e/((WebName|Main|Sandbox|System).*)" => "/bin/edit/$1",
"^/((WebName|Main|Sandbox|System).*)" => "/bin/view/$1",
"^/e/([A-Z_].*)" => "/bin/edit/Default/$1",
"^/([A-Z_].*)" => "/bin/view/Default/$1",
"^/pub/System/(.*)" => "/pub/System/$1",
"^/pub/(.*?)/([^/]+)$" => "/bin/viewfile/$1?filename=$2" )
url.rewrite-repeat = ( "^/?(index.*)?$" => "/Main" )
$HTTP["url"] =~ "^/bin" { cgi.assign = ( "" => "" ) }
}
Changes to LocalSite.cfg
Next (for both options in the previous section), edit your LocalSite.cfg and add:
$Foswiki::cfg{ScriptUrlPaths}{view} = '';
Note the plural
Paths, it is a different hash key than
ScriptUrlPath. This cannot be done through
configure, so you will need to do it manually. If you want to shorten other actions, you can do it in a similar fashion:
$Foswiki::cfg{ScriptUrlPaths}{edit} = '/e';
Don't forget to tweak your web server configuration accordingly if you do this. Examples available for Lighttpd only, see above.
Changes to lib/Foswiki.pm - for extra shortening
This pseudo-patch should give the idea:
- $url .= urlEncode( '/'.$web.'/'.$topic );
+ if(($web eq "SomeDefaultWeb") && ($script eq "view")){
+ $url .= urlEncode( '/'.$topic );
+ }else{
+ $url .= urlEncode( '/'.$web.'/'.$topic );
+ }
Don't forget to tweak your web server configuration accordingly if you do this. Examples available for Lighttpd only, see above.
For Apache adding the following line in /etc/foswiki/apache.conf might do the job:
RewriteRule ^/([A-Z][^/][^/]*)$ /bin/view/Main/$1 [PT]
Finally...
Restart your web server, and then your done. Short URLs for all!
Accessing rewritten URLs
Foswiki has the
SCRIPTURL Macro to support rewriting rules for scripts for URLs in templates and in topics. See System.Macros#VarSCRIPTURL in your local Foswiki documentation for more information.
Advanced: redirecting long URLs to shorter ones, or how to prevent conflicting rules
Even if you've configured everything correctly, there's still a chance that the long URLs containing
/bin/view/ will be exposed on the Internet and generate some hits. You may want to generate 30x redirects for them, so that caches and search engines will be less confused.
This is easier to solve using
Apache's option 1. Add
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/+URL/+to/+foswiki/+bin/+view/+ [NC]
RewriteRule ^/+URL/+to/+foswiki/+bin/+view/+(.*) /URL/to/foswiki/$1 [L,R]
to Apache's configuration.
In other cases it is not that simple, since in a nutshell here's what you'll be trying to tell your web-server:
- when someone accesses
http://wiki/Main/Page, give them (rewrite to) http://wiki/bin/view/Main/Page
- when someone accesses
http://wiki/bin/view/Main/Page, redirect them to http://wiki/Main/Page
Depending on your web-server, you can get into an endless loop of rewrites and redirects. But there's a simple solution:
This way you'll avoid loops. Note that only
view action is shortened. Other actions are mostly interactive and don't raise concerns about caching and search indexing.
Lighttpd example
This configuration example works with extra shortening, with default web name
Cenkes dropped from links. E.g. both
http://wiki/bin/view/Cenkes/Page and
http://wiki/Cenkes/Page will always be shortened (redirected) to
http://wiki/Page.
url.rewrite-once = (
"^/((Main|Sandbox|System).*)" => "/bin/X-view/$1",
"^/e/((Cenkes|Main|Sandbox|System).*)" => "/bin/edit/$1",
"^/e/([A-Z].*)" => "/bin/edit/Cenkes/$1",
"^/([A-Z][^/]*(\?.*)?)$" => "/bin/X-view/Cenkes/$1",
"^/pub/System/(.*)" => "/pub/System/$1",
"^/pub/(.*?)/([^/]+)$" => "/bin/viewfile/$1?filename=$2" )
url.redirect = (
"^/Cenkes/(.*)" => "http://wiki.cenkes.org/$1",
"^/bin/view/(Cenkes/)?(.*)" => "http://wiki.cenkes.org/$2",)
See also...
ShorterCaseInsensitiveURLs
Is this a security risk to shorten the url from /wiki/bin/view/System/WebHome to just /wiki/System/WebHome ?
There is no security risk.
Script URL and pub URL
So, to clarify though, the script URL and pub URL should still be /foswiki/bin and /foswiki/pub respectively (on the configure screen)?
Yes, everything in
configure should stay the same, although you do need to set
$Foswiki::cfg{ScriptUrlPaths}{view} = ''; in
lib/LocalSite.cfg
Remark: I had another experience: only stripping '/foswiki' from the two variables in configure made my site work correctly.
--
Contributors: CrawfordCurrie,
AndrewJones,
TWiki:Main.WoutMertens,
GilmarSantosJr,
ArthurClemens
See topic history for excised comments (removed for clarity)