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: 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.
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;
}
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
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)