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.

When implemented, this will change your view URLs from:

www.example.com/bin/view/Main/WebHome to www.example.com/Main/WebHome.

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.

ALERT! This example no longer works on Foswiki 2.x. It also requires that valid web names be listed in the .htaccess file. It does this to accomplish an extreme level of URL shortening, where the web name is also dropped from the URL. This is not a recommended configuration.

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

Foswiki 2.x supports Shorter URL configurations directly in bin/configure. If the short URLs are active before running the initial "Bootstrap" configuration, then the correct settings should be automatically discovered. If you wish to enabling short URLs later the following configuration key should be

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

This advanced solution requires copying and editing of the 'view' script shipped with Foswiki.

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:
On Foswiki 2.x, the below "xview" script requires changes to be functional. Without these changes, all requests will return 404 URL not found errors.
diff --git bin/view bin/view
index 16914df..02b19b1 100755
--- bin/view
+++ bin/view
@@ -20,7 +20,7 @@ BEGIN {
     my $setlib = File::Spec->catpath( $volume, $binDir, 'setlib.cfg' );
     @INC = ( '.', grep { $_ ne '.' } @INC ) unless $binDir;
     require $setlib;
-    $action =~ s/\..*$//;    # Remove eventual file extension
+    $action =~ 'view'; 
     $ENV{FOSWIKI_ACTION} = $action;
 }
 

  • access the foswiki file system and create a symlink (or a copy) from bin/view to bin/xview:
       cd bin
       ln -s view /usr/local/www/foswiki/bin/xview
    • Note: on Dreamhost you cannot create a symlink in the bin directory, so you need a copy: cp view /usr/local/www/foswiki/bin/xview
  • rewrite URLs like http://wiki/Main/Page to http://wiki/bin/xview/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/xview/$1",
   "^/e/((Cenkes|Main|Sandbox|System).*)" => "/bin/edit/$1",
   "^/e/([A-Z].*)" => "/bin/edit/Cenkes/$1",
   "^/([A-Z][^/]*(\?.*)?)$" => "/bin/xview/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)?

No. Let "Bootstrap" set the correct values. But generally, if a prefix (such as /foswiki/ is in use, then it will always be part of the URL, even the shortened URLs. However it is not required. If the web server configuration does not require the /foswiki prefix, then it won't be needed anywhere.

-- Contributors: CrawfordCurrie, AndrewJones, TWiki:Main.WoutMertens, GilmarSantosJr, ArthurClemens, GeorgeClark

See topic history for excised comments (removed for clarity)

BasicForm edit

TopicClassification AdminTopic
Topic Summary How to enable shorter URLs in Foswiki
Extension
Interested Parties
Related Topics
Topic revision: r18 - 02 Jul 2016, GeorgeClark
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy