Wiki source code of Short URLs

Last modified by Daniel Turner on 2025/01/31

Show last authors
1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc start="2"/}}
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 === Deploying as ROOT ===
16
17 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##.
18
19 Achieving this depends on the container, as there's no standard regarding the ROOT application (Refer to your container's documentation for more details).
20
21 Some examples:
22
23 * 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##).
24 * 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:
25 ** 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.
26 ** Rename the existing ##webapps/xwiki## directory into ##webapps/root##.
27 ** 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.
28
29 You must tell XWiki that it's deployed as ROOT by setting the ##xwiki.webapppath## to empty in your ##xwiki.cfg## configuration file as in:
30
31 {{code language="none"}}
32 xwiki.webapppath=
33 {{/code}}
34
35 The reason is that XWiki cannot guess the webapp context from the URL in this case. This seemed to work on previous versions but it was actually leading to errors from time to time, depending on what URL was used when doing the first request on the XWiki instance.
36
37 === When using the XWiki Debian Package ===
38
39 See [[Installation using Debian (.DEB) packages>>Documentation.AdminGuide.Installation.InstallationViaAPT.WebHome||anchor="HXWikiasrootwebapp28shortURLs29"]].
40
41 == II. Servlet mapping name ==
42
43 The second part is the hardest part to remove. It identifies the servlet that should process the page, which, for ##/bin/##, is the action servlet. Generically speaking, to get rid of ##/bin/##, you need to configure your system so that URLs matching ##/*## are mapped to the Action Servlet (by default only ##/bin/*## URLs are mapped to the Action Servlet).
44
45 However you need to be careful that the following prefixes do NOT go through the Action Servlet (see your ##web.xml## to check their current mappings):
46
47 * ##/resources/*## and ##/skins/*##: Statically served resources. These need to be served directly as static resources.
48 * ##/rest/*##: REST resources, served by the XWiki REST Servlet
49 * ##/redirect##: The XWiki Redirect Servlet used to redirect to the home page when no page is specified in the URL
50
51 There are various alternate to achieve this:
52
53 {{toc scope="local"/}}
54
55 {{info}}
56 You might be tempted to configure just your XWiki's ##web.xml## file [[but this won't work>>Documentation.AdminGuide.ShortURLs.ShortURLsInvalid.WebHome]].
57 {{/info}}
58
59 === UrlRewriteFilter ===
60
61 {{warning}}
62 This approach requires a specific workaround configuration with Tomcat 9.x+ (the workaround was not needed with Tomcat 8.x) since Tomcat performs very early mapping of incoming requests before the ##URLRewriteFilter## has a chance to add the ##/bin## prefix. Thus the mapping is [[wrongly associated to the default Servlet instead of the XWiki Action Servlet>>https://jira.xwiki.org/browse/XWIKI-19444?focusedCommentId=112420&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-112420]]. The workaround consists of the two actions below.
63
64 * Declare new Servlet mappings in ##web.xml##:(((
65 {{code language="xml"}}
66 <servlet-mapping>
67 <servlet-name>action</servlet-name>
68 <url-pattern>/upload/*</url-pattern>
69 </servlet-mapping>
70
71 <!-- This is for the file upload from CKEditor to work, since it sends a POST action to the current page using the "/get/" path -->
72 <servlet-mapping>
73 <servlet-name>action</servlet-name>
74 <url-pattern>/get/*</url-pattern>
75 </servlet-mapping>
76 {{/code}}
77 )))
78 * Update the ##upload.js## content:
79 ** Do a backup of ##$XWIKI_WEBAPP/resources/uicomponents/widgets/upload.min.js##, then remove the original file
80 ** Edit the file ##$XWIKI_WEBAPP/resources/uicomponents/widgets/upload.js## and update the line {{code language="javascript"}}request.open('POST', this.formData.action);{{/code}} to:(((
81 {{code language="javascript"}}
82 request.open('POST', this.formData.action + '?form_token='+this.formData.additionalFields['form_token']
83 + '&xredirect=' + escape(this.formData.additionalFields['xredirect']));
84 {{/code}}
85 )))
86 {{/warning}}
87
88 "UrlRewriteFilter" is a [[framework offering a Servlet Filter>>http://www.tuckey.org/urlrewrite/]] allowing to rewrite URLs.
89
90 {{warning}}
91 XWiki Version 17.0.0 has moved from the Javax to the Jakarta namespace which requires Tuckey Url Rewrite Filter Version 5 instead of Version 4.
92
93 Additionally, you will need to apply the changes noted above to the web.xml even when using Jetty 12 instead of Tomcat 9. Changes to the upload.js are not required.
94 {{/warning}}
95
96 Install steps:
97
98 1. [[Download the JAR>>https://search.maven.org/artifact/org.tuckey/urlrewritefilter]] and put it in ##WEB-INF/lib##
99 1. Edit your ##WEB-INF/web.xml## and add the ##<filter>## and ##<filter-mapping>## definitions [[as documented>>http://www.tuckey.org/urlrewrite/]]. Make sure to have them first so that they're executed before any other XWiki filter.
100 1. Drop the following content below in a file at ##WEB-INF/urlrewrite.xml##:(((
101 Note that this is just an example and you should tune it depending on what you wish to achieve. Its principle is very simple: it takes some URL format you wish to have and convert those URLs into the format that XWiki expects in input, and, in output, it does the opposite and converts the XWiki format into the format you wish to have.
102
103 The example below expects URLs without a ##/bin## and thus adds it so that XWiki has it when it processes URLs and in output, removes the ##/bin## so that generated URLs are without ##/bin##.
104
105 {{code language="xml"}}
106 <?xml version="1.0" encoding="utf-8"?>
107 <!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
108 "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
109 <urlrewrite decode-using="null">
110
111 <rule>
112 <note>
113 Ensure that URLs that must not be served by the Action Servlet are not modified.
114 </note>
115 <from>^/((authenticate|bin|resources|skins|asyncrenderer|rest|wiki|jcaptcha|webjars|job)/(.*)|robots\.txt)$</from>
116 <to type="forward" last="true">-</to>
117 </rule>
118
119 <rule>
120 <note>
121 For all other URLs we prepend the "/bin/" prefix so that they get routed to the XWiki Action Servlet.
122 </note>
123 <from>^/(.*)$</from>
124 <to type="forward">/bin/$1</to>
125 </rule>
126
127 <outbound-rule>
128 <note>
129 Rewrite outbound URLs to remove the "/bin" part when there are two paths after it.
130 </note>
131 <from>/bin/(.*)/(.*)$</from>
132 <to>/$1/$2</to>
133 </outbound-rule>
134
135 <outbound-rule>
136 <note>
137 Rewrite outbound URLs to remove the "/bin" part when there's a single path after it.
138 </note>
139 <from>/bin/(.*)$</from>
140 <to>/$1</to>
141 </outbound-rule>
142
143 <outbound-rule>
144 <note>
145 Rewrite outbound URLs to remove the "/bin" part it's the last path.
146 </note>
147 <from>/bin$</from>
148 <to>/</to>
149 </outbound-rule>
150
151 </urlrewrite>
152 {{/code}}
153 )))
154
155 **Note**: for debugging of URL Rewrite filter, set the ##logLevel## parameter as described in https://tuckey.org/urlrewrite/manual/5.1/index.html#filterparams (using the value ##sysout:DEBUG##, the logs can be read in tomcat logs).
156
157 === Apache ===
158
159 Strategy:
160
161 * Tell Apache that ##/skins## and ##/resources## URLs are served statically so that they don't go through the Servlet container
162 * Configure ##web.xml## so that ##/*## URLs go through the Action Servlet
163 * Tell XWiki to not generate URLs with ##bin## in the path
164
165 Configuration steps:
166
167 * Setup the following Apache configuration:(((
168 {{code language="apache"}}
169 Alias /skins /usr/local/xwiki/skins
170 Alias /resources /usr/local/xwiki/resources
171
172 RewriteEngine on
173
174 RewriteRule ^/+skins - [L]
175 RewriteCond %{REQUEST_URI} !\.gwtrpc$
176 RewriteRule ^/+resources($|/.*) - [L]
177
178 ## For some reason, the "/" end points does not work with tomcat, so the workaround is to rewrite it to /Main
179 RewriteRule ^/*$ http://localhost:8080/Main/ [P,L]
180 ## For all other URLs, we go to tomcat
181 RewriteRule .* http://localhost:8080%{REQUEST_URI} [P,L]
182 ProxyPassReverse / http://localhost:8080/
183 {{/code}}
184 )))
185 * Edit ##web.xml## and add:(((
186 {{code language="xml"}}
187 <servlet-mapping>
188 <servlet-name>action</servlet-name>
189 <url-pattern>/*</url-pattern>
190 </servlet-mapping>
191 {{/code}}
192 )))
193 * Add the following in ##xwiki.cfg## (empty value after the equal sign):(((
194 {{code language="none"}}
195 xwiki.defaultservletpath=
196 {{/code}}
197 )))
198
199 === Nginx ===
200
201 The strategy is almost identical to the Apache strategy above, except of course for the first step which is the configuration file for Nginx.
202
203 Full Nginx configuration:
204
205 {{code language="nginx"}}
206 server {
207 listen       80;
208 server_name  domain.tld;
209 return 301 $scheme://www.domain.tld$request_uri;
210 }
211
212 server {
213 listen       80;
214 server_name  www.domain.tld;
215
216 charset utf-8;
217
218 # Configuration to avoid error 413: Request Entity too large.
219 client_max_body_size 0;
220
221 # Serve the following URLs statically instead of through the servlet container.
222 location /skins {
223 alias /usr/lib/xwiki/skins;
224 }
225
226 location /resources/uicomponents {
227 alias /usr/lib/xwiki/resources/uicomponents;
228 }
229
230 location /resources/js {
231 alias /usr/lib/xwiki/resources/js;
232 }
233
234 location /resources/css {
235 alias /usr/lib/xwiki/resources/css;
236 }
237
238 location /resources/icons {
239 alias /usr/lib/xwiki/resources/icons;
240 }
241
242 # Remove the "/bin" part from the URL by a rewrite.
243 location /bin {
244 rewrite ^/bin/(.*)$ /$1 permanent;
245 }
246
247 # Rewrite the empty ("/") endpoint to "/Main", so to accommodate Tomcat.
248 location = / {
249 return 301 $scheme://$server_name/Main;
250 }
251
252 # Passing requests to the proxied Tomcat Server.
253 location / {
254 # Redirect root and beyond to backend.
255 proxy_pass http://localhost:8080/;
256 proxy_set_header        X-Real-IP $remote_addr;
257 proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
258 proxy_set_header        Host $http_host;
259 proxy_set_header        X-Forwarded-Proto $scheme;
260 }
261 }
262 {{/code}}
263
264 == III. action name ==
265
266 The third part, ##/view/##, identifies the 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.
267
268 It's possible to configure XWiki to allow omitting this action when you wish to imply ##view## and also to have XWiki generate URLs without the ##view## action. This is achieved by editing ##xwiki.cfg## and setting {{code language="none"}}xwiki.showviewaction=0{{/code}}.
269
270 == IV. Error Page ==
271
272 At the ##WEB-INF/web.xml##, the ##location## of the 404 error code needs to be changed accordingly. For example:
273
274 {{code language="xml"}}
275 <error-page>
276 <error-code>404</error-code>
277 <!--<location>/xwiki/bin/view/Main/DocumentDoesNotExist</location>-->
278 <location>/bin/Main/DocumentDoesNotExist</location>
279 </error-page>
280 {{/code}}
281
282 == V. Conclusion ==
283
284 After performing all these changes, you should be able to access documents with URLs like:
285
286 * server.com/Space/Document
287 * server.com/Space/ (pointing to Space.WebHome)
288 * server.com/Document (pointing to Main.Document)
289 * server.com/ will show Main.WebHome, without any redirect.
290
291 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.
292
293 == Other solutions ==
294
295 Some XWiki users have contributed other solutions but they've not been verified by a XWiki Development Team member at this stage so use at your own risk ;)
296
297 * [[Lighttpd + Jetty>>dev:Drafts.ShortURLsLighttpdJetty]]
298 * [[Apache + Tomcat>>http://odo.lv/Recipes/XWikiShortURLs?language=en]]

Get Connected