comparison src/server/server.py @ 862:e3e2effc9a4c

server: LiberviaRootResource now manages root url redirection, and former redirection has been replaced by it: as a nice side effect, the root URL doesn't show "libervia.html" anymore (LiberviaRootResource actually do URL rewritting).
author Goffi <goffi@goffi.org>
date Mon, 25 Jan 2016 17:02:13 +0100
parents 0e9341e537d6
children f024fc5744d0
comparison
equal deleted inserted replaced
861:5cefc6ab302f 862:e3e2effc9a4c
123 self.redirections = {} 123 self.redirections = {}
124 if options['url_redirections_dict'] and not options['url_redirections_profile']: 124 if options['url_redirections_dict'] and not options['url_redirections_profile']:
125 raise ValueError(u"url_redirections_profile need to be filled if you want to use url_redirections_dict") 125 raise ValueError(u"url_redirections_profile need to be filled if you want to use url_redirections_dict")
126 126
127 for old, new in options['url_redirections_dict'].iteritems(): 127 for old, new in options['url_redirections_dict'].iteritems():
128 if not old or not old.startswith('/'): 128 if not old.strip():
129 # root URL special case
130 old = ''
131 elif not old.startswith('/'):
129 raise ValueError(u"redirected url must start with '/', got {}".format(old)) 132 raise ValueError(u"redirected url must start with '/', got {}".format(old))
130 old = self._normalizeURL(old) 133 else:
134 old = self._normalizeURL(old)
131 new_url = urlparse.urlsplit(new.encode('utf-8')) 135 new_url = urlparse.urlsplit(new.encode('utf-8'))
132 if new_url.scheme == 'xmpp': 136 if new_url.scheme == 'xmpp':
133 # XMPP URI 137 # XMPP URI
134 parsed_qs = urlparse.parse_qs(new_url.geturl()) 138 parsed_qs = urlparse.parse_qs(new_url.geturl())
135 try: 139 try:
151 location = urlparse.urlunsplit(('', '', new_url.path, new_url.query, new_url.fragment)) 155 location = urlparse.urlunsplit(('', '', new_url.path, new_url.query, new_url.fragment))
152 request_data = self._getRequestData(location) 156 request_data = self._getRequestData(location)
153 else: 157 else:
154 raise NotImplementedError(u"{scheme}: scheme is not managed for url_redirections_dict".format(scheme=new_url.scheme)) 158 raise NotImplementedError(u"{scheme}: scheme is not managed for url_redirections_dict".format(scheme=new_url.scheme))
155 self.redirections[old] = request_data 159 self.redirections[old] = request_data
160 if not old:
161 log.info(u"Root URL redirected to {uri}".format(uri=request_data[1].decode('utf-8')))
156 del options['url_redirections_dict'] 162 del options['url_redirections_dict']
157 del options['url_redirections_profile'] 163 del options['url_redirections_profile']
164
165 if not '' in self.redirections:
166 self.redirections[''] = self._getRequestData(C.LIBERVIA_MAIN_PAGE)
158 167
159 def _normalizeURL(self, url, lower=True): 168 def _normalizeURL(self, url, lower=True):
160 """Return URL normalized for self.redirections dict 169 """Return URL normalized for self.redirections dict
161 170
162 @param url(unicode): URL to normalize 171 @param url(unicode): URL to normalize
190 args = http.parse_qs(argstring, 1) 199 args = http.parse_qs(argstring, 1)
191 200
192 # XXX: splitted path case must not be changed, as it may be significant 201 # XXX: splitted path case must not be changed, as it may be significant
193 # (e.g. for blog items) 202 # (e.g. for blog items)
194 return self._normalizeURL(path, lower=False).split('/'), uri, path, args 203 return self._normalizeURL(path, lower=False).split('/'), uri, path, args
204
205 def _redirect(self, request, request_data):
206 """Redirect an URL by rewritting request
207
208 this is *NOT* a HTTP redirection, but equivalent to URL rewritting
209 @param request(web.http.request): original request
210 @param request_data(tuple): data returned by self._getRequestData
211 @return (web_resource.Resource): resource to use
212 """
213 path_list, uri, path, args = request_data
214 try:
215 request._redirected
216 except AttributeError:
217 pass
218 else:
219 log.warning(D_(u"recursive redirection, please fix this URL:\n{old} ==> {new}").format(
220 old=request.uri,
221 new=uri,
222 ))
223 return web_resource.NoResource()
224 log.debug(u"Redirecting URL {old} to {new}".format(
225 old=request.uri,
226 new=uri,
227 ))
228 # we change the request to reflect the new url
229 request._redirected = True # here to avoid recursive redirections
230 request.postpath = path_list[1:]
231 request.uri = uri
232 request.path = path
233 request.args = args
234 # and we start again to look for a child with the new url
235 return self.getChildWithDefault(path_list[0], request)
236
237 def getChildWithDefault(self, name, request):
238 # XXX: this method is overriden only for root url
239 # which is the only ones who need to be handled before other children
240 if name == '' and not request.postpath:
241 return self._redirect(request, self.redirections[''])
242 return super(LiberviaRootResource, self).getChildWithDefault(name, request)
195 243
196 def getChild(self, name, request): 244 def getChild(self, name, request):
197 resource = super(LiberviaRootResource, self).getChild(name, request) 245 resource = super(LiberviaRootResource, self).getChild(name, request)
198 246
199 if isinstance(resource, web_resource.NoResource): 247 if isinstance(resource, web_resource.NoResource):
204 request_data = self.redirections[current_url] 252 request_data = self.redirections[current_url]
205 except KeyError: 253 except KeyError:
206 # no redirection for this url 254 # no redirection for this url
207 pass 255 pass
208 else: 256 else:
209 path_list, uri, path, args = request_data 257 return self._redirect(request, request_data)
210 try:
211 request._redirected
212 except AttributeError:
213 pass
214 else:
215 log.warning(D_(u"recursive redirection, please fix this URL:\n{old} ==> {new}").format(
216 old=request.uri,
217 new=uri,
218 ))
219 return web_resource.NoResource()
220 log.debug(u"Redirecting URL {old} to {new}".format(
221 old=request.uri,
222 new=uri,
223 ))
224 # we change the request to reflect the new url
225 request._redirected = True # here to avoid recursive redirections
226 request.postpath = path_list[1:]
227 request.uri = uri
228 request.path = path
229 request.args = args
230 # and we start again to look for a child with the new url
231 return self.getChildWithDefault(path_list[0], request)
232 258
233 return resource 259 return resource
234 260
235 def createSimilarFile(self, path): 261 def createSimilarFile(self, path):
236 # XXX: this method need to be overriden to avoid recreating a LiberviaRootResource 262 # XXX: this method need to be overriden to avoid recreating a LiberviaRootResource
1419 ## URLs ## 1445 ## URLs ##
1420 def putChild(path, resource): 1446 def putChild(path, resource):
1421 """Add a child to the root resource""" 1447 """Add a child to the root resource"""
1422 # FIXME: check that no information is leaked (c.f. https://twistedmatrix.com/documents/current/web/howto/using-twistedweb.html#request-encoders) 1448 # FIXME: check that no information is leaked (c.f. https://twistedmatrix.com/documents/current/web/howto/using-twistedweb.html#request-encoders)
1423 root.putChild(path, web_resource.EncodingResourceWrapper(resource, [server.GzipEncoderFactory()])) 1449 root.putChild(path, web_resource.EncodingResourceWrapper(resource, [server.GzipEncoderFactory()]))
1424
1425 # we redirect root url to libevia's dynamic part
1426 putChild('', web_util.Redirect(C.LIBERVIA_MAIN_PAGE))
1427 1450
1428 # JSON APIs 1451 # JSON APIs
1429 putChild('json_signal_api', self.signal_handler) 1452 putChild('json_signal_api', self.signal_handler)
1430 putChild('json_api', MethodHandler(self)) 1453 putChild('json_api', MethodHandler(self))
1431 putChild('register_api', _register) 1454 putChild('register_api', _register)