Wiki source code of Short XWiki URLs

Version 38.1 by Vincent Massol on 2013/09/19

Show last authors
1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
4
5 This tutorial shows you how to tune your XWiki platform by replacing the default URL scheme with a shorter scheme.
6
7 {{info}}
8 A short URL is an URL without the ##xwiki/bin/view## parts.
9 {{/info}}
10
11 = I. Application name =
12
13 The ##/xwiki/## part of the URL is the application name. It identifies the application that should process the request, and it allows a container to host more than one application. To change it you must refer to your container's documentation and find how to map the context path of a web application. For example on Tomcat it's enough to simply deploy the XWiki webapp in the ##webapps## directory, in a sub directory named after the application name you wish to use (e.g. ##webapps/myappname##).
14
15 A special case is when deploying XWiki as the ROOT application, which actually allows the application name part to be empty, so an URL can take the form ##server.com/bin/view/Space/Document##. Achieving this depends on the container, as there's no standard regarding the ROOT application. For example:
16 * in Tomcat, with the default configuration, all it takes is to deploy the XWiki web application in ##webapps##, in a sub directory named ##ROOT## (i.e. ##webapps/ROOT##).
17 * In Jetty, with the default configuration, all it takes is to deploy the XWiki web application in ##webapps##, in a sub directory named ##root##. Note that if you're using the Standalone distribution (which packages Jetty and HSQLDB) then you'll also need to:
18 ** Remove the existing ##webapps/root## directory which contains a redirect Servlet that automatically redirects root URLs to the ##xwiki## context. You won't need that anymore.
19 ** Rename the existing ##webapps/xwiki## directory into ##webapps/root##.
20 ** Remove the ##jetty/contexts/xwiki.xml## file and thus keep only the ##jetty/contexts/root.xml## file. Otherwise you'll get a warning in the console.
21
22 Refer to your container's documentation for more details.
23
24 = II. Servlet mapping name =
25
26 The second part is the hardest part to remove. It identifies the servlet that should process the page, which, for ##/bin/##, is the Struts servlet. Generically speaking, to get rid of ##/bin/##, you need to configure your system so that URLs matching ##/*## are mapped to the Struts Servlet (by default only ##/bin/*## URLs are mapped to the Struts Servlet).
27
28 However you need to be careful that the following prefixes do NOT go through the Struts Servlet (see your ##web.xml## to check their current mappings):
29 * ##/resources/*## and ##/skins/*##: Statically served resources. These need to be served directly as static resources.
30 * ##/rest/*##: REST resources, served by the XWiki REST Servlet
31 * ##/xmlrpc/*##: XML-RPC resources, served by the XWiki XMLRPC Servlet
32 * ##/resources/*~*/*.gwtrpc##: GWT-RPC calls, served by the XWiki GWT Servlet
33 * ##/webdav/*##: WebDav calls, served by the XWiki WebDAV Servlet
34 * ##/XWikiService##: Another XWiki GWT Servlet
35 * ##/redirect##: The XWiki Redirect Servlet used to redirect to the home page when no page is specified in the URL
36
37 There are various alternate to achieve this:
38
39 {{toc scope="local"/}}
40
41 {{info}}
42 You might be tempted to configure just your XWiki's ##web.xml## file [[but this won't work>>ShortURLsInvalid]].
43 {{/info}}
44
45 XWiki also generates URL and you can tell it to generate URLs without the ##bin/## part by adding this piece of code in ##xwiki.cfg##: {{code language="none"}}xwiki.defaultservletpath={{/code}} (Note that this is not required with the UrlRewriteFilter solution described below since it rewrites outbound URLs too).
46
47 == UrlRewriteFilter ==
48
49 {{info}}This is the simplest solution of all but you'll need XWiki 5.2+ because of [[this issue that was fixed in XWiki 5.2>>http://jira.xwiki.org/browse/XWIKI-9430]].{{/info}}
50
51 "UrlRewriteFilter" is a [[framework offering a Servlet Filter>>http://www.tuckey.org/urlrewrite/]] allowing to rewrite URLs.
52
53 Install steps:
54 1. [[Download the JAR>>http://www.tuckey.org/urlrewrite/]] and put it in ##WEB-INF/lib##
55 1. Edit your ##WEB-INF/web.xml## and add the ##<filter>## and ##filter-mapping## definitions [[as documented>>http://www.tuckey.org/urlrewrite/]]
56 1. Drop the following content in a file at ##WEB-INF/urlrewrite.xml##:(((
57 {{code language="xml"}}
58 <?xml version="1.0" encoding="utf-8"?>
59 <!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
60 "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
61 <urlrewrite>
62
63 <rule>
64 <note>
65 Ensure that URLs ending with .gwtrpc are not modified.
66 </note>
67 <from>^/(.*)\.gwtrpc$</from>
68 <to type="forward" last="true">-</to>
69 </rule>
70
71 <rule>
72 <note>
73 En sure that URLs that must not be served by the Struts Servlet are not modified.
74 </note>
75 <from>^/(bin|resources|skins|rest|webdav|xmlrpc)/(.*)$</from>
76 <to type="forward" last="true">-</to>
77 </rule>
78
79 <rule>
80 <note>
81 For all other URLs we prepend the "/bin/" prefix so that they get routed to the XWiki Action Servlet.
82 </note>
83 <from>^/(.*)$</from>
84 <to type="forward">/bin/$1</to>
85 </rule>
86
87 <outbound-rule>
88 <note>
89 Rewrite outbound URLs to remove the "/bin" part.
90 </note>
91 <from>/bin/(.*)/(.*)$</from>
92 <to>/$1/$2</to>
93 </outbound-rule>
94
95 </urlrewrite>
96 {{/code}}
97 )))
98
99 == web.xml + Apache ==
100
101 Do as above but instead of mapping the Default Servlet, bypass the Servlet container at the web front-end level. For example, if you are using Apache httpd as a front-end, and assuming a webapp deployed as a ROOT webapp and an AJP connection between httpd and the servlet container, the following configuration allows you to serve skin files and static resources directly from httpd:
102
103 {{code}}
104 Alias /skins /usr/local/xwiki/skins
105 Alias /resources /usr/local/xwiki/resources
106 ProxyPass /skins/ !
107 ProxyPass /resources/ !
108 {{/code}}
109
110 Note that this solution will not work for the WYSIWYG editor since it needs that the ##.gwtrpc## URLs are directed to the XWiki Servlet. The following Apache configuration using URL rewriting achieves this:
111
112 {{code}}
113 Alias /skins /usr/local/xwiki/skins
114 Alias /resources /usr/local/xwiki/resources
115
116 RewriteEngine on
117
118 RewriteRule ^/+skins - [L]
119 RewriteCond %{REQUEST_URI} !\.gwtrpc$
120 RewriteRule ^/+resources($|/.*) - [L]
121
122 RewriteRule .* http://localhost:8080%{REQUEST_URI} [P,L]
123 ProxyPassReverse / http://localhost:8080/
124 {{/code}}
125
126 {{warning}}Note that while this has been tested to work with XWiki 3.1, it seems it [[doesn't work with 4.5.4 and later>>http://jira.xwiki.org/browse/XWIKI-9455]].{{/warning}}
127
128 == Lighttpd + Jetty ==
129
130 I used lighttpd, but I assume it can be done with other webservers too. This is the configuration I used in the lighttpd config (note that my xwiki folder has been moved to ##/usr/share/jetty/webapps/root## (no 'xwiki' at all)):
131
132 {{code language="none"}}
133 $HTTP["host"] =~ "^www\.domain\.com$" {
134 # ensure all requests for .gwtrpc files go through to java server
135 # we can put this rule first as a higher priority, which java couldn't do
136 $HTTP["url"] =~ "\.gwtrpc$" {
137 proxy.server = ( "" => (( "host" => "127.0.0.1", "port" => 8080 )))
138 }
139 # otherwise, we can handle the static resources
140 else $HTTP["url"] =~ "^/resources/" {
141 alias.url += ( "/resources" => "/usr/share/jetty/webapps/root/resources" )
142 }
143 # otherwise, we can handle the static resources
144 else $HTTP["url"] =~ "^/skins/" {
145 alias.url += ( "/skins" => "/usr/share/jetty/webapps/root/skins" )
146 }
147 # and here is the primary server
148 else $HTTP["host"] =~ "^www\.domain\.com$" {
149 proxy.server = ( "" => (( "host" => "127.0.0.1", "port" => 8080 )))
150 }
151 }
152 # redirect anything.domain.com to www.domain.com
153 else $HTTP["host"] =~ "\.domain\.com$" {
154 url.redirect = ( "^/(.*)" => "http://www.domain.com/$1" )
155 server.name = "www.domain.com"
156 }
157 # redirect domain.com to www.domain.com
158 else $HTTP["host"] =~ "domain\.com$" {
159 url.redirect = ( "^/(.*)" => "http://www.domain.com/$1" )
160 server.name = "www.domain.com"
161 }
162 {{/code}}
163
164 So lighttpd will serve any static content unless it has ##.gwtrpc## on the end of the URL.
165
166 If you use Nginx as a web-server, just add three more locations and set ##root## to them. By ##try_files## Nginx checks static content presence and if doesn't exist, redirect it to the Tomcat (we expect dynamic content in this case, including all ##*.gwtrpc## requests).
167
168 {{code}}
169 location /skins/ {
170 root /var/lib/tomcat7/webapps/ROOT;
171 }
172
173 location /resources/ {
174 try_files $uri $uri/ @fallback;
175 root /var/lib/tomcat7/webapps/ROOT;
176 }
177
178 location @fallback {
179 proxy_pass http://localhost:8080;
180 }
181 {{/code}}
182
183 In the example above XWiki installed as ROOT application in Tomcat. Change path to your XWiki application accordingly.
184
185 Then in ##web.xml##, I changed the ##gwtrpc## mapping to:
186
187 {{code language="xml"}}
188 <servlet-mapping>
189 <servlet-name>gwtrpc</servlet-name>
190 <url-pattern>/resources/*</url-pattern>
191 <url-pattern>/skins/*</url-pattern>
192 </servlet-mapping>
193 {{/code}}
194
195 Since we are using a url-pattern of ##/path/##, it will be specific enough to be a higher priority than the ##/## pattern we'll use next. And since the only thing that will come through via resources or skins will be ##gwtrpc##, then we can be sure it's ok. Note that only ##resources## is required, but I did both anyway.
196
197 Now, as described above, add a rule to catch everything else and redirect it to your XWiki servlet:
198
199 {{code language="xml"}}
200 <servlet-mapping>
201 <servlet-name>action</servlet-name>
202 <url-pattern>/*</url-pattern>
203 </servlet-mapping>
204 {{/code}}
205
206 = III. Struts action name =
207
208 The third part, ##/view/##, identifies the struts action that should process a request. So this tells what we want to do with the document, ##/view/## it, ##/edit/## it or ##/delete/## it, for example. The XWiki platform allows this part to be missing, considering that the default action is to just display the document, so an URL like ##server.com/bin/Space/Document## will work out of the box.
209
210 Even more, the URL factory, the component that generates URLs, can be configured to skip this part when the action is ##/view/##. To do this write this code in ##xwiki.cfg##: {{code language="none"}}xwiki.showviewaction=0{{/code}}.
211
212 = IV. Error Page =
213
214 At the ##WEB-INF/web.xml##, the ##location## of the 404 error code needs to be changed accordingly. For example:
215
216 {{code language="xml"}}
217 <error-page>
218 <error-code>404</error-code>
219 <!--<location>/xwiki/bin/view/Main/DocumentDoesNotExist</location>-->
220 <location>/bin/Main/DocumentDoesNotExist</location>
221 </error-page>
222 {{/code}}
223
224 = V. Conclusion =
225
226 After performing all these changes, you should be able to access documents with URLs like:
227
228 * server.com/Space/Document
229 * server.com/Space/ (pointing to Space.WebHome)
230 * server.com/Document (pointing to Main.Document)
231 * server.com/ will show Main.WebHome, without any redirect.
232
233 As a bonus, these changes are backwards compatible, meaning that any currently working URL will also work with these changes performed, so you won't have any broken bookmarks.

Get Connected