Wiki source code of Short XWiki URLs

Version 24.1 by Dmitry Bakbardin on 2013/01/18

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 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##). In Jetty, the default name is ##root##. Refer to your container's documentation for more details.
16
17 = II. Servlet mapping name =
18
19 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. To get rid of ##/bin/##, for the moment ##web.xml## must be changed in a container-dependent way, so that the container's default servlet is configured to serve the existing directories, like skins, yui, tinymce and wikieditor.
20
21 == 2.1. Original Instructions ==
22
23 === 2.1.1. Container setup ===
24
25 In Jetty, the container shipped with the XWiki installer, you will have to write something like:
26
27 {{code language="xml"}}
28 <servlet>
29 <servlet-name>defaultSkins</servlet-name>
30 <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
31 <load-on-startup>1</load-on-startup>
32 </servlet>
33 <servlet-mapping>
34 <servlet-name>defaultSkins</servlet-name>
35 <url-pattern>/skins/*</url-pattern>
36 </servlet-mapping>
37 <servlet-mapping>
38 <servlet-name>defaultSkins</servlet-name>
39 <url-pattern>/resources/*</url-pattern>
40 </servlet-mapping>
41 {{/code}}
42
43 {{warning}}
44 If you are using Jetty 1.7 or higher, the correct servlet-class is ##org.eclipse.jetty.servlet.DefaultServlet##.
45 {{/warning}}
46
47 In Tomcat, the default servlet does not accept a parameter for changing the resource base, so you will need to write another default servlet.
48
49 === 2.1.2. Container setup alternative: front-end by-pass ===
50
51 Alternatively, you could by-pass 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:
52
53 {{code}}
54 Alias /skins /usr/local/xwiki/skins
55 Alias /resources /usr/local/xwiki/resources
56 ProxyPass /skins/ !
57 ProxyPass /resources/ !
58 {{/code}}
59
60 == 2.2. Struts servlet mapping ==
61
62 The second thing to do is to copy the mapping for the Struts servlet to also be activated for /, like:
63
64 {{code language="xml"}}
65 <servlet-mapping>
66 <servlet-name>action</servlet-name>
67 <url-pattern>/*</url-pattern>
68 </servlet-mapping>
69 {{/code}}
70
71 Be sure to leave the other mappings in place, so that ##/bin/## works, too.
72
73 Tthe last thing that must be changed is the default mapping used by the URL factory, by adding this piece of code in ##xwiki.cfg##: {{code language="none"}}xwiki.defaultservletpath={{/code}}.
74
75 == 2.3. Specific Lighttpd + Jetty Instructions ==
76
77 The original instructions might work for you if you don't use the WYSIWYG editor. It did not work for me and this is what I had to do:
78
79 The problem is that you need to use Java Struts for the routing. They are not very powerful when it comes to the servlet-mapping configuration. We need to map:
80
81 * /resources/* ~-~-> static content
82 * /skins/* ~-~-> static content
83 * *.gwtrpc ~-~-> a servlet
84 * everything else ~-~-> other servlets
85
86 The problem is that .gwtrpc files are in the ##/resources/## folder, and the ##/resources/*## mapping will always have a higher priority than *.gwtrpc due to the way structs works.
87
88 So, we have to cheat a bit, and offload the static content to the webserver, which does have a powerful route-map configuration.
89
90 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)):
91
92 {{code language="none"}}
93 $HTTP["host"] =~ "^www\.domain\.com$" {
94 # ensure all requests for .gwtrpc files go through to java server
95 # we can put this rule first as a higher priority, which java couldn't do
96 $HTTP["url"] =~ "\.gwtrpc$" {
97 proxy.server = ( "" => (( "host" => "127.0.0.1", "port" => 8080 )))
98 }
99 # otherwise, we can handle the static resources
100 else $HTTP["url"] =~ "^/resources/" {
101 alias.url += ( "/resources" => "/usr/share/jetty/webapps/root/resources" )
102 }
103 # otherwise, we can handle the static resources
104 else $HTTP["url"] =~ "^/skins/" {
105 alias.url += ( "/skins" => "/usr/share/jetty/webapps/root/skins" )
106 }
107 # and here is the primary server
108 else $HTTP["host"] =~ "^www\.domain\.com$" {
109 proxy.server = ( "" => (( "host" => "127.0.0.1", "port" => 8080 )))
110 }
111 }
112 # redirect anything.domain.com to www.domain.com
113 else $HTTP["host"] =~ "\.domain\.com$" {
114 url.redirect = ( "^/(.*)" => "http://www.domain.com/$1" )
115 server.name = "www.domain.com"
116 }
117 # redirect domain.com to www.domain.com
118 else $HTTP["host"] =~ "domain\.com$" {
119 url.redirect = ( "^/(.*)" => "http://www.domain.com/$1" )
120 server.name = "www.domain.com"
121 }
122 {{/code}}
123
124 So lighttpd will serve any static content unless it has .gwtrpc on the end of the URL.
125
126 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).
127
128 {{code}}
129 location /skins/ {
130 root /var/lib/tomcat7/webapps/ROOT;
131 }
132
133 location /resources/ {
134 try_files $uri $uri/ @fallback;
135 root /var/lib/tomcat7/webapps/ROOT;
136 }
137
138 location @fallback {
139 proxy_pass http://localhost:8080;
140 }
141
142 {{/code}}
143
144 In the example above XWiki is set as ROOT application in Tomcat. Change path to your XWiki application accordingly.
145
146
147 Then in ##web.xml##, I changed the gwtrpc mapping to:
148
149 {{code language="xml"}}
150 <servlet-mapping>
151 <servlet-name>gwtrpc</servlet-name>
152
153 <url-pattern>/resources/*</url-pattern>
154 <url-pattern>/skins/*</url-pattern>
155 </servlet-mapping>
156 {{/code}}
157
158 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.
159
160 Now, as described above, add a rule to catch everything else and redirect it to your xwiki servlet:
161
162 {{code language="xml"}}
163 <servlet-mapping>
164 <servlet-name>action</servlet-name>
165 <url-pattern>/*</url-pattern>
166 </servlet-mapping>
167 {{/code}}
168
169 The last thing that must be changed is the default mapping used by the URL factory, by adding this piece of code in ##xwiki.cfg##: {{code language="none"}}xwiki.defaultservletpath={{/code}}.
170
171 == 2.4. Alternative: Changing the mapping name ==
172
173 If removing the ##/bin## part is not possible in your environment, you can still rename it to something less technical, and which would better fit your site, like ##/wiki##. To do this, you must first add a mapping for the new path, as in:
174
175 {{code language="xml"}}
176 <servlet-mapping>
177 <servlet-name>action</servlet-name>
178 <url-pattern>/wiki/*</url-pattern>
179 </servlet-mapping>
180 {{/code}}
181
182 This means that the wiki now accepts requests through this mapping.
183
184 {{info}}
185 This specific mapping (##/wiki##) should already be there, but you need to add a new one for other custom mappings.
186 {{/info}}
187
188 {{warning}}
189 The ##/wiki## mapping is reserved for multiwikis with path based wiki mapping setup, so use something else in this scenarion. It should work fine when multiwikis are disabled or when only hostname wiki mapping is used.
190 {{/warning}}
191
192 Then you must make sure that accessing the application without a servlet in the path (as in ##http:~/~/server.com/xwiki/## when XWiki is not set as the ROOT application, or ##http:~/~/server.com/## if XWiki is the ROOT application) redirects to the right servlet. This involves changing the configuration for the ##redirect## servlet in ##web.xml##; search for the declaration of the ##redirectHomeServlet##, uncomment the ##init-param## section, and adjust accordingly:
193
194 {{code language="xml"}}
195 <servlet>
196 <servlet-name>redirectHomeServlet</servlet-name>
197 <servlet-class>com.xpn.xwiki.web.HomePageRedirectServlet</servlet-class>
198 <!-- Uncomment and edit this if you want to redirect to a different home page, or if you have different mappings.
199 Note: the URL should not start with /, because it allows the context name to be changed. If it starts with /,
200 then it should be an absolute URL, including the application context path. -->
201 <init-param>
202 <description>The address to redirect to when the client hits the root of the application.</description>
203 <param-name>homePage</param-name>
204 <param-value>wiki/</param-value>
205 </init-param>
206 </servlet>
207 {{/code}}
208
209 Also change the default mapping used by the URL factory, by adding this in ##xwiki.cfg##: {{code language="none"}}xwiki.defaultservletpath=wiki/{{/code}}.
210
211 Optionally, you can make sure that accessing the hostname without a path (as in ##http:~/~/server.com/##) redirects to the right servlet. This depends on your environment. In a Tomcat + Apache HTTPD + mod_redirect, just update these settings:
212
213 {{code language="none"}}
214 RedirectMatch ^/$ /xwiki/wiki/
215 RedirectMatch ^/xwiki/$ /xwiki/wiki/
216 {{/code}}
217
218 In the default standalone distribution (with Jetty), the ROOT application only redirects to the ##/xwiki## application, so configuring the XWiki redirect servlet is enough if you don't change the application name. If you do, just edit the ##web.xml## of the ##root## webapp, uncomment the ##init-param## of the ##XWikiDispatcherServlet## and change the application name.
219
220 = III. Struts action name =
221
222 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.
223
224 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}}.
225
226 = IV. Error Page =
227
228 At the ##WEB-INF/web.xml##, the ##location## of the 404 error code needs to be changed accordingly. For example:
229
230 {{code language="xml"}}
231 <error-page>
232 <error-code>404</error-code>
233 <!--<location>/xwiki/bin/view/Main/DocumentDoesNotExist</location>-->
234 <location>/bin/Main/DocumentDoesNotExist</location>
235 </error-page>
236 {{/code}}
237
238 = V. Conclusion =
239
240 After performing all these changes, you should be able to access documents with URLs like:
241
242 * server.com/Space/Document
243 * server.com/Space/ (pointing to Space.WebHome)
244 * server.com/Document (pointing to Main.Document)
245 * server.com/ will show Main.WebHome, without any redirect.
246
247 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