# HG changeset patch # User Goffi # Date 1456935242 -3600 # Node ID d9b98b8a184750125b30f65ca9176384534235ca # Parent c030d8235c237764e5751b6643d66548e299d769 server: handling of dict and "file:" urls in url_redirections_dict: - file: urls can be specified, they can redirect to a directory or of file. In the case of directory, all the hierarchy with subdirectories will be available - a dict can be used instead of plain string url, to specify options - if a dict is used, either "url" or "path" must be specified. "url" has the same meaning as the plain string url, "path" is used to construct a file: url - for file: redirections, there is a "protected" option which can be specified in the dict (JSON boolean). If true (default) the directories listings will not be displayed. diff -r c030d8235c23 -r d9b98b8a1847 src/server/server.py --- a/src/server/server.py Wed Mar 02 15:08:42 2016 +0100 +++ b/src/server/server.py Wed Mar 02 17:14:02 2016 +0100 @@ -124,7 +124,28 @@ if options['url_redirections_dict'] and not options['url_redirections_profile']: raise ValueError(u"url_redirections_profile need to be filled if you want to use url_redirections_dict") - for old, new in options['url_redirections_dict'].iteritems(): + for old, new_data in options['url_redirections_dict'].iteritems(): + # new_data can be a dictionary or a unicode url + if isinstance(new_data, dict): + # new_data dict must contain either "url" or "path" key (exclusive) + # if "path" is used, a file url is constructed with it + try: + new = new_data['url'] + except KeyError: + try: + path = new_data['path'] + except KeyError: + raise ValueError(u'if you use a dict for url_redirections data, it must contain the "url" or a "file" key') + else: + new = 'file:{}'.format(urllib.quote(path)) + else: + if 'path' in new_data: + raise ValueError(u'You can\'t have "url" and "path" keys at the same time in url_redirections') + else: + new = new_data + new_data = {} + + # some normalization if not old.strip(): # root URL special case old = '' @@ -133,6 +154,8 @@ else: old = self._normalizeURL(old) new_url = urlparse.urlsplit(new.encode('utf-8')) + + # we handle the known URL schemes if new_url.scheme == 'xmpp': # XMPP URI parsed_qs = urlparse.parse_qs(new_url.geturl()) @@ -147,6 +170,7 @@ item = urllib.quote_plus(item), ).decode('utf-8') request_data = self._getRequestData(location) + elif new_url.scheme in ('', 'http', 'https'): # direct redirection if new_url.netloc: @@ -154,14 +178,40 @@ netloc = new_url.netloc)) location = urlparse.urlunsplit(('', '', new_url.path, new_url.query, new_url.fragment)).decode('utf-8') request_data = self._getRequestData(location) + + elif new_url.scheme in ('file'): + # file or directory + if new_url.netloc: + raise NotImplementedError(u"netloc ({netloc}) is not implemented for url redirection to file system, it is not possible to redirect to an external host".format( + netloc = new_url.netloc)) + path = urllib.unquote(new_url.path) + if not os.path.isabs(path): + raise ValueError(u'file redirection must have an absolute path: e.g. file:/path/to/my/file') + # for file redirection, we directly put child here + segments, dummy, last_segment = old.rpartition('/') + url_segments = segments.split('/') if segments else [] + current = self + for segment in url_segments: + resource = web_resource.NoResource() + current.putChild(segment, resource) + current = resource + resource_class = ProtectedFile if new_data.get('protected',True) else static.File + current.putChild(last_segment, resource_class(path)) + log.debug(u"Added redirection from /{old} to file system path {path}".format(old=old.decode('utf-8'), path=path.decode('utf-8'))) + continue # we don't want to use redirection system, so we continue here + else: raise NotImplementedError(u"{scheme}: scheme is not managed for url_redirections_dict".format(scheme=new_url.scheme)) + self.redirections[old] = request_data if not old: log.info(u"Root URL redirected to {uri}".format(uri=request_data[1].decode('utf-8'))) + + # no need to keep url_redirections*, they will not be used anymore del options['url_redirections_dict'] del options['url_redirections_profile'] + # the default root URL, if not redirected if not '' in self.redirections: self.redirections[''] = self._getRequestData(C.LIBERVIA_MAIN_PAGE)