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 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:
  • access the foswiki file system and create a symlink (or a copy) from bin/view to bin/X-view:
       cd bin
       ln -s view /usr/local/www/foswiki/bin/X-view
    • Note: on Dreamhost you cannot create a symlink in the bin directory, so you need a copy: cp view /usr/local/www/foswiki/bin/X-view
  • rewrite URLs like http://wiki/Main/Page to http://wiki/bin/X-view/Main/Page
  • redirect URLs like http://wiki/bin/view/Main/Page to http://wiki/Main/Page
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

FAQ

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)

BasicForm edit

TopicClassification AdminTopic
Topic Summary How to enable shorter URLs in Foswiki
Interested Parties
Related Topics
Topic revision: r17 - 24 Aug 2010, ArthurClemens - This page was cached on 30 May 2016 - 05:14.

The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License