Mercurial > libervia-web
comparison src/server/server.py @ 875:d9b98b8a1847
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.
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 02 Mar 2016 17:14:02 +0100 |
parents | 0cf250066b8a |
children | 6bdee34fa2f4 |
comparison
equal
deleted
inserted
replaced
874:c030d8235c23 | 875:d9b98b8a1847 |
---|---|
122 ## redirections | 122 ## redirections |
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_data in options['url_redirections_dict'].iteritems(): |
128 # new_data can be a dictionary or a unicode url | |
129 if isinstance(new_data, dict): | |
130 # new_data dict must contain either "url" or "path" key (exclusive) | |
131 # if "path" is used, a file url is constructed with it | |
132 try: | |
133 new = new_data['url'] | |
134 except KeyError: | |
135 try: | |
136 path = new_data['path'] | |
137 except KeyError: | |
138 raise ValueError(u'if you use a dict for url_redirections data, it must contain the "url" or a "file" key') | |
139 else: | |
140 new = 'file:{}'.format(urllib.quote(path)) | |
141 else: | |
142 if 'path' in new_data: | |
143 raise ValueError(u'You can\'t have "url" and "path" keys at the same time in url_redirections') | |
144 else: | |
145 new = new_data | |
146 new_data = {} | |
147 | |
148 # some normalization | |
128 if not old.strip(): | 149 if not old.strip(): |
129 # root URL special case | 150 # root URL special case |
130 old = '' | 151 old = '' |
131 elif not old.startswith('/'): | 152 elif not old.startswith('/'): |
132 raise ValueError(u"redirected url must start with '/', got {}".format(old)) | 153 raise ValueError(u"redirected url must start with '/', got {}".format(old)) |
133 else: | 154 else: |
134 old = self._normalizeURL(old) | 155 old = self._normalizeURL(old) |
135 new_url = urlparse.urlsplit(new.encode('utf-8')) | 156 new_url = urlparse.urlsplit(new.encode('utf-8')) |
157 | |
158 # we handle the known URL schemes | |
136 if new_url.scheme == 'xmpp': | 159 if new_url.scheme == 'xmpp': |
137 # XMPP URI | 160 # XMPP URI |
138 parsed_qs = urlparse.parse_qs(new_url.geturl()) | 161 parsed_qs = urlparse.parse_qs(new_url.geturl()) |
139 try: | 162 try: |
140 item = parsed_qs['item'][0] | 163 item = parsed_qs['item'][0] |
145 location = "/blog/{profile}/{item}".format( | 168 location = "/blog/{profile}/{item}".format( |
146 profile=urllib.quote(options['url_redirections_profile'].encode('utf-8')), | 169 profile=urllib.quote(options['url_redirections_profile'].encode('utf-8')), |
147 item = urllib.quote_plus(item), | 170 item = urllib.quote_plus(item), |
148 ).decode('utf-8') | 171 ).decode('utf-8') |
149 request_data = self._getRequestData(location) | 172 request_data = self._getRequestData(location) |
173 | |
150 elif new_url.scheme in ('', 'http', 'https'): | 174 elif new_url.scheme in ('', 'http', 'https'): |
151 # direct redirection | 175 # direct redirection |
152 if new_url.netloc: | 176 if new_url.netloc: |
153 raise NotImplementedError(u"netloc ({netloc}) is not implemented yet for url_redirections_dict, it is not possible to redirect to an external website".format( | 177 raise NotImplementedError(u"netloc ({netloc}) is not implemented yet for url_redirections_dict, it is not possible to redirect to an external website".format( |
154 netloc = new_url.netloc)) | 178 netloc = new_url.netloc)) |
155 location = urlparse.urlunsplit(('', '', new_url.path, new_url.query, new_url.fragment)).decode('utf-8') | 179 location = urlparse.urlunsplit(('', '', new_url.path, new_url.query, new_url.fragment)).decode('utf-8') |
156 request_data = self._getRequestData(location) | 180 request_data = self._getRequestData(location) |
181 | |
182 elif new_url.scheme in ('file'): | |
183 # file or directory | |
184 if new_url.netloc: | |
185 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( | |
186 netloc = new_url.netloc)) | |
187 path = urllib.unquote(new_url.path) | |
188 if not os.path.isabs(path): | |
189 raise ValueError(u'file redirection must have an absolute path: e.g. file:/path/to/my/file') | |
190 # for file redirection, we directly put child here | |
191 segments, dummy, last_segment = old.rpartition('/') | |
192 url_segments = segments.split('/') if segments else [] | |
193 current = self | |
194 for segment in url_segments: | |
195 resource = web_resource.NoResource() | |
196 current.putChild(segment, resource) | |
197 current = resource | |
198 resource_class = ProtectedFile if new_data.get('protected',True) else static.File | |
199 current.putChild(last_segment, resource_class(path)) | |
200 log.debug(u"Added redirection from /{old} to file system path {path}".format(old=old.decode('utf-8'), path=path.decode('utf-8'))) | |
201 continue # we don't want to use redirection system, so we continue here | |
202 | |
157 else: | 203 else: |
158 raise NotImplementedError(u"{scheme}: scheme is not managed for url_redirections_dict".format(scheme=new_url.scheme)) | 204 raise NotImplementedError(u"{scheme}: scheme is not managed for url_redirections_dict".format(scheme=new_url.scheme)) |
205 | |
159 self.redirections[old] = request_data | 206 self.redirections[old] = request_data |
160 if not old: | 207 if not old: |
161 log.info(u"Root URL redirected to {uri}".format(uri=request_data[1].decode('utf-8'))) | 208 log.info(u"Root URL redirected to {uri}".format(uri=request_data[1].decode('utf-8'))) |
209 | |
210 # no need to keep url_redirections*, they will not be used anymore | |
162 del options['url_redirections_dict'] | 211 del options['url_redirections_dict'] |
163 del options['url_redirections_profile'] | 212 del options['url_redirections_profile'] |
164 | 213 |
214 # the default root URL, if not redirected | |
165 if not '' in self.redirections: | 215 if not '' in self.redirections: |
166 self.redirections[''] = self._getRequestData(C.LIBERVIA_MAIN_PAGE) | 216 self.redirections[''] = self._getRequestData(C.LIBERVIA_MAIN_PAGE) |
167 | 217 |
168 def _normalizeURL(self, url, lower=True): | 218 def _normalizeURL(self, url, lower=True): |
169 """Return URL normalized for self.redirections dict | 219 """Return URL normalized for self.redirections dict |