Wiki source code of Short URLs

Version 99.2 by Vincent Massol on 2024/10/18

Hide last authors
Manuel Smeria 19.4 1 {{box cssClass="floatinginfobox" title="**Contents**"}}
Jan-Paul Kleijn 96.1 2 {{toc start="2"/}}
Manuel Smeria 19.4 3 {{/box}}
Jerome 14.1 4
Manuel Smeria 19.4 5 This tutorial shows you how to tune your XWiki platform by replacing the default URL scheme with a shorter scheme.
Jerome 15.1 6
Jerome 14.1 7 {{info}}
8 A short URL is an URL without the ##xwiki/bin/view## parts.
9 {{/info}}
maalej 2.1 10
Jan-Paul Kleijn 95.1 11 == I. Application name ==
maalej 1.1 12
Jerome 14.1 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##).
maalej 1.1 14
Jan-Paul Kleijn 95.1 15 === Deploying as ROOT ===
Vincent Massol 47.1 16
Vincent Massol 46.1 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##.
Guillaume Fenollar 43.1 18
Vincent Massol 46.1 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:
Paul Libbrecht 51.1 22
Vincent Massol 46.1 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##).
Vincent Massol 26.1 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.
Vincent Massol 10.2 28
Vincent Massol 98.2 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:
Vincent Massol 26.1 30
Vincent Massol 46.1 31 {{code language="none"}}
32 xwiki.webapppath=
33 {{/code}}
34
promasu 97.1 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.
Vincent Massol 46.1 36
Vincent Massol 49.1 37 === When using the XWiki Debian Package ===
38
Ecaterina Moraru (Valica) 61.1 39 See [[Installation using Debian (.DEB) packages>>Documentation.AdminGuide.Installation.InstallationViaAPT.WebHome||anchor="HXWikiasrootwebapp28shortURLs29"]].
Vincent Massol 49.1 40
promasu 96.2 41 === When using Jetty from the XWiki Debian Package ===
42
promasu 97.1 43 {{version since="16.7.0"}}
44 You have to modify the ##xjetty-web.xml## file
promasu 96.2 45
promasu 97.1 46 The WebAppContext from the xwiki-jetty configuration has to be modified so that Jetty actually serves the XWiki application from the root-path. For this you have to modify the ##/etc/xwiki/xjetty-web.xml## and add the following directive.
promasu 96.2 47
48 {{code language="xml"}}
49 <Set name="contextPath">/</Set>
50 {{/code}}
promasu 99.1 51 {{/version}}
promasu 96.2 52
Jan-Paul Kleijn 95.1 53 == II. Servlet mapping name ==
maalej 1.1 54
Thomas Mortagne 71.1 55 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).
maalej 1.1 56
Thomas Mortagne 70.1 57 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):
Guillaume Fenollar 43.1 58
Vincent Massol 29.1 59 * ##/resources/*## and ##/skins/*##: Statically served resources. These need to be served directly as static resources.
Vincent Massol 35.1 60 * ##/rest/*##: REST resources, served by the XWiki REST Servlet
Vincent Massol 29.1 61 * ##/redirect##: The XWiki Redirect Servlet used to redirect to the home page when no page is specified in the URL
maalej 1.1 62
Vincent Massol 38.1 63 There are various alternate to achieve this:
Dmitry Bakbardin 20.1 64
Vincent Massol 38.1 65 {{toc scope="local"/}}
66
Vincent Massol 37.1 67 {{info}}
Ecaterina Moraru (Valica) 62.1 68 You might be tempted to configure just your XWiki's ##web.xml## file [[but this won't work>>Documentation.AdminGuide.ShortURLs.ShortURLsInvalid.WebHome]].
Vincent Massol 37.1 69 {{/info}}
70
Jan-Paul Kleijn 95.1 71 === UrlRewriteFilter ===
Vincent Massol 29.1 72
slauriere 82.1 73 {{warning}}
slauriere 86.1 74 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.
Vincent Massol 29.1 75
slauriere 94.1 76 * Declare new Servlet mappings in ##web.xml##:(((
Vincent Massol 81.1 77 {{code language="xml"}}
78 <servlet-mapping>
79 <servlet-name>action</servlet-name>
80 <url-pattern>/upload/*</url-pattern>
81 </servlet-mapping>
slauriere 94.1 82
83 <!-- This is for the file upload from CKEditor to work, since it sends a POST action to the current page using the "/get/" path -->
84 <servlet-mapping>
85 <servlet-name>action</servlet-name>
86 <url-pattern>/get/*</url-pattern>
87 </servlet-mapping>
Vincent Massol 81.1 88 {{/code}}
slauriere 85.1 89 )))
Vincent Massol 88.2 90 * Update the ##upload.js## content:
91 ** Do a backup of ##$XWIKI_WEBAPP/resources/uicomponents/widgets/upload.min.js##, then remove the original file
92 ** 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:(((
slauriere 87.1 93 {{code language="javascript"}}
slauriere 88.1 94 request.open('POST', this.formData.action + '?form_token='+this.formData.additionalFields['form_token']
95 + '&xredirect=' + escape(this.formData.additionalFields['xredirect']));
slauriere 85.1 96 {{/code}}
97 )))
98 {{/warning}}
slauriere 84.1 99
Vincent Massol 81.1 100 "UrlRewriteFilter" is a [[framework offering a Servlet Filter>>http://www.tuckey.org/urlrewrite/]] allowing to rewrite URLs.
Vincent Massol 36.1 101
102 Install steps:
Guillaume Fenollar 43.1 103
Vincent Massol 73.2 104 1. [[Download the JAR>>https://search.maven.org/artifact/org.tuckey/urlrewritefilter]] and put it in ##WEB-INF/lib##
Vincent Massol 64.1 105 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.
slauriere 67.1 106 1. Drop the following content below in a file at ##WEB-INF/urlrewrite.xml##:(((
Vincent Massol 63.1 107 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.
108
109 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##.
110
Jerome 14.1 111 {{code language="xml"}}
Vincent Massol 29.1 112 <?xml version="1.0" encoding="utf-8"?>
113 <!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
114 "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
Vincent Massol 42.1 115 <urlrewrite decode-using="null">
Vincent Massol 29.1 116
117 <rule>
118 <note>
Thomas Mortagne 70.1 119 Ensure that URLs that must not be served by the Action Servlet are not modified.
Vincent Massol 29.1 120 </note>
slauriere 83.1 121 <from>^/((authenticate|bin|resources|skins|asyncrenderer|rest|wiki|jcaptcha|webjars|job)/(.*)|robots\.txt)$</from>
Vincent Massol 29.1 122 <to type="forward" last="true">-</to>
123 </rule>
124
125 <rule>
126 <note>
127 For all other URLs we prepend the "/bin/" prefix so that they get routed to the XWiki Action Servlet.
128 </note>
129 <from>^/(.*)$</from>
130 <to type="forward">/bin/$1</to>
131 </rule>
132
Vincent Massol 32.1 133 <outbound-rule>
134 <note>
Vincent Massol 48.1 135 Rewrite outbound URLs to remove the "/bin" part when there are two paths after it.
Vincent Massol 32.1 136 </note>
137 <from>/bin/(.*)/(.*)$</from>
138 <to>/$1/$2</to>
139 </outbound-rule>
140
Vincent Massol 48.1 141 <outbound-rule>
142 <note>
143 Rewrite outbound URLs to remove the "/bin" part when there's a single path after it.
144 </note>
145 <from>/bin/(.*)$</from>
146 <to>/$1</to>
147 </outbound-rule>
148
149 <outbound-rule>
150 <note>
151 Rewrite outbound URLs to remove the "/bin" part it's the last path.
152 </note>
153 <from>/bin$</from>
154 <to>/</to>
155 </outbound-rule>
156
Vincent Massol 29.1 157 </urlrewrite>
158 {{/code}}
Vincent Massol 36.1 159 )))
Vincent Massol 29.1 160
Vincent Massol 94.2 161 **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).
Anca Luca 45.1 162
Jan-Paul Kleijn 95.1 163 === Apache ===
Jerome 16.1 164
Vincent Massol 39.1 165 Strategy:
Guillaume Fenollar 43.1 166
Vincent Massol 73.1 167 * Tell Apache that ##/skins## and ##/resources## URLs are served statically so that they don't go through the Servlet container
168 * Configure ##web.xml## so that ##/*## URLs go through the Action Servlet
Vincent Massol 39.1 169 * Tell XWiki to not generate URLs with ##bin## in the path
Sergiu Dumitriu 4.1 170
Vincent Massol 39.1 171 Configuration steps:
Guillaume Fenollar 43.1 172
Vincent Massol 39.1 173 * Setup the following Apache configuration:(((
174 {{code language="apache"}}
Manuel Smeria 19.4 175 Alias /skins /usr/local/xwiki/skins
176 Alias /resources /usr/local/xwiki/resources
Jerome 19.1 177
Vincent Massol 34.1 178 RewriteEngine on
179
180 RewriteRule ^/+skins - [L]
181 RewriteCond %{REQUEST_URI} !\.gwtrpc$
182 RewriteRule ^/+resources($|/.*) - [L]
183
Clément Aubin 89.1 184 ## For some reason, the "/" end points does not work with tomcat, so the workaround is to rewrite it to /Main
185 RewriteRule ^/*$ http://localhost:8080/Main/ [P,L]
186 ## For all other URLs, we go to tomcat
Vincent Massol 34.1 187 RewriteRule .* http://localhost:8080%{REQUEST_URI} [P,L]
188 ProxyPassReverse / http://localhost:8080/
189 {{/code}}
Vincent Massol 39.1 190 )))
Vincent Massol 41.1 191 * Edit ##web.xml## and add:(((
Vincent Massol 39.1 192 {{code language="xml"}}
193 <servlet-mapping>
194 <servlet-name>action</servlet-name>
195 <url-pattern>/*</url-pattern>
196 </servlet-mapping>
197 {{/code}}
198 )))
199 * Add the following in ##xwiki.cfg## (empty value after the equal sign):(((
Jerome 14.1 200 {{code language="none"}}
Vincent Massol 39.1 201 xwiki.defaultservletpath=
Jerome 14.1 202 {{/code}}
Guillaume Fenollar 43.1 203 )))
PaulHarris 12.1 204
Jan-Paul Kleijn 95.1 205 === Nginx ===
Jerome 14.1 206
Jan-Paul Kleijn 95.1 207 The strategy is almost identical to the Apache strategy above, except of course for the first step which is the configuration file for Nginx.
208
209 Full Nginx configuration:
210
211 {{code language="nginx"}}
212 server {
213 listen       80;
214 server_name  domain.tld;
215 return 301 $scheme://www.domain.tld$request_uri;
216 }
217
218 server {
219 listen       80;
220 server_name  www.domain.tld;
221
222 charset utf-8;
223
224 # Configuration to avoid error 413: Request Entity too large.
225 client_max_body_size 0;
226
227 # Serve the following URLs statically instead of through the servlet container.
228 location /skins {
229 alias /usr/lib/xwiki/skins;
230 }
231
232 location /resources/uicomponents {
233 alias /usr/lib/xwiki/resources/uicomponents;
234 }
235
236 location /resources/js {
237 alias /usr/lib/xwiki/resources/js;
238 }
239
240 location /resources/css {
241 alias /usr/lib/xwiki/resources/css;
242 }
243
244 location /resources/icons {
245 alias /usr/lib/xwiki/resources/icons;
246 }
247
248 # Remove the "/bin" part from the URL by a rewrite.
249 location /bin {
250 rewrite ^/bin/(.*)$ /$1 permanent;
251 }
252
253 # Rewrite the empty ("/") endpoint to "/Main", so to accommodate Tomcat.
254 location = / {
255 return 301 $scheme://$server_name/Main;
256 }
257
258 # Passing requests to the proxied Tomcat Server.
259 location / {
260 # Redirect root and beyond to backend.
261 proxy_pass http://localhost:8080/;
262 proxy_set_header        X-Real-IP $remote_addr;
263 proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
264 proxy_set_header        Host $http_host;
265 proxy_set_header        X-Forwarded-Proto $scheme;
266 }
267 }
268 {{/code}}
269
270 == III. action name ==
271
Vincent Massol 99.2 272 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.
Manuel Smeria 19.4 273
Alex Cotiugă 93.1 274 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}}.
Manuel Smeria 19.4 275
Jan-Paul Kleijn 95.1 276 == IV. Error Page ==
Manuel Smeria 19.4 277
Jerome 14.1 278 At the ##WEB-INF/web.xml##, the ##location## of the 404 error code needs to be changed accordingly. For example:
279
280 {{code language="xml"}}
281 <error-page>
mingfai 9.1 282 <error-code>404</error-code>
283 <!--<location>/xwiki/bin/view/Main/DocumentDoesNotExist</location>-->
284 <location>/bin/Main/DocumentDoesNotExist</location>
285 </error-page>
Jerome 14.1 286 {{/code}}
mingfai 9.1 287
Jan-Paul Kleijn 95.1 288 == V. Conclusion ==
Sergiu Dumitriu 4.1 289
290 After performing all these changes, you should be able to access documents with URLs like:
Jerome 14.1 291
Sergiu Dumitriu 4.1 292 * server.com/Space/Document
293 * server.com/Space/ (pointing to Space.WebHome)
294 * server.com/Document (pointing to Main.Document)
295 * server.com/ will show Main.WebHome, without any redirect.
296
Vincent Massol 5.1 297 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.
Valdis Vitolins 54.1 298
Jan-Paul Kleijn 95.1 299 == Other solutions ==
Valdis Vitolins 54.1 300
301 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 ;)
302
Thomas Mortagne 91.1 303 * [[Lighttpd + Jetty>>dev:Drafts.ShortURLsLighttpdJetty]]
Valdis Vitolins 58.1 304 * [[Apache + Tomcat>>http://odo.lv/Recipes/XWikiShortURLs?language=en]]

Get Connected