Show More
@@ -318,25 +318,16 b' class hgweb(object):' | |||||
318 | if h[0] != 'Content-Security-Policy'] |
|
318 | if h[0] != 'Content-Security-Policy'] | |
319 | wsgireq.headers.append(('Content-Security-Policy', rctx.csp)) |
|
319 | wsgireq.headers.append(('Content-Security-Policy', rctx.csp)) | |
320 |
|
320 | |||
|
321 | handled, res = wireprotoserver.handlewsgirequest( | |||
|
322 | rctx, wsgireq, req, self.check_perm) | |||
|
323 | if handled: | |||
|
324 | return res | |||
|
325 | ||||
321 | if req.havepathinfo: |
|
326 | if req.havepathinfo: | |
322 | query = req.dispatchpath |
|
327 | query = req.dispatchpath | |
323 | else: |
|
328 | else: | |
324 | query = req.querystring.partition('&')[0].partition(';')[0] |
|
329 | query = req.querystring.partition('&')[0].partition(';')[0] | |
325 |
|
330 | |||
326 | # Route it to a wire protocol handler if it looks like a wire protocol |
|
|||
327 | # request. |
|
|||
328 | protohandler = wireprotoserver.parsehttprequest(rctx, wsgireq, req, |
|
|||
329 | self.check_perm) |
|
|||
330 |
|
||||
331 | if protohandler: |
|
|||
332 | try: |
|
|||
333 | if query: |
|
|||
334 | raise ErrorResponse(HTTP_NOT_FOUND) |
|
|||
335 |
|
||||
336 | return protohandler['dispatch']() |
|
|||
337 | except ErrorResponse as inst: |
|
|||
338 | return protohandler['handleerror'](inst) |
|
|||
339 |
|
||||
340 | # translate user-visible url structure to internal structure |
|
331 | # translate user-visible url structure to internal structure | |
341 |
|
332 | |||
342 | args = query.split('/', 2) |
|
333 | args = query.split('/', 2) |
@@ -150,24 +150,29 b' class httpv1protocolhandler(wireprototyp' | |||||
150 | def iscmd(cmd): |
|
150 | def iscmd(cmd): | |
151 | return cmd in wireproto.commands |
|
151 | return cmd in wireproto.commands | |
152 |
|
152 | |||
153 |
def |
|
153 | def handlewsgirequest(rctx, wsgireq, req, checkperm): | |
154 |
"""P |
|
154 | """Possibly process a wire protocol request. | |
155 |
|
155 | |||
156 |
If the current request |
|
156 | If the current request is a wire protocol request, the request is | |
157 | function returns a dict with details about that request, including |
|
157 | processed by this function. | |
158 | an ``abstractprotocolserver`` instance suitable for handling the |
|
|||
159 | request. Otherwise, ``None`` is returned. |
|
|||
160 |
|
158 | |||
161 | ``wsgireq`` is a ``wsgirequest`` instance. |
|
159 | ``wsgireq`` is a ``wsgirequest`` instance. | |
162 | ``req`` is a ``parsedrequest`` instance. |
|
160 | ``req`` is a ``parsedrequest`` instance. | |
|
161 | ||||
|
162 | Returns a 2-tuple of (bool, response) where the 1st element indicates | |||
|
163 | whether the request was handled and the 2nd element is a return | |||
|
164 | value for a WSGI application (often a generator of bytes). | |||
163 | """ |
|
165 | """ | |
|
166 | # Avoid cycle involving hg module. | |||
|
167 | from .hgweb import common as hgwebcommon | |||
|
168 | ||||
164 | repo = rctx.repo |
|
169 | repo = rctx.repo | |
165 |
|
170 | |||
166 | # HTTP version 1 wire protocol requests are denoted by a "cmd" query |
|
171 | # HTTP version 1 wire protocol requests are denoted by a "cmd" query | |
167 | # string parameter. If it isn't present, this isn't a wire protocol |
|
172 | # string parameter. If it isn't present, this isn't a wire protocol | |
168 | # request. |
|
173 | # request. | |
169 | if 'cmd' not in req.querystringdict: |
|
174 | if 'cmd' not in req.querystringdict: | |
170 | return None |
|
175 | return False, None | |
171 |
|
176 | |||
172 | cmd = req.querystringdict['cmd'][0] |
|
177 | cmd = req.querystringdict['cmd'][0] | |
173 |
|
178 | |||
@@ -179,17 +184,32 b' def parsehttprequest(rctx, wsgireq, req,' | |||||
179 | # known wire protocol commands and it is less confusing for machine |
|
184 | # known wire protocol commands and it is less confusing for machine | |
180 | # clients. |
|
185 | # clients. | |
181 | if not iscmd(cmd): |
|
186 | if not iscmd(cmd): | |
182 | return None |
|
187 | return False, None | |
|
188 | ||||
|
189 | # The "cmd" query string argument is only valid on the root path of the | |||
|
190 | # repo. e.g. ``/?cmd=foo``, ``/repo?cmd=foo``. URL paths within the repo | |||
|
191 | # like ``/blah?cmd=foo`` are not allowed. So don't recognize the request | |||
|
192 | # in this case. We send an HTTP 404 for backwards compatibility reasons. | |||
|
193 | if req.dispatchpath: | |||
|
194 | res = _handlehttperror( | |||
|
195 | hgwebcommon.ErrorResponse(hgwebcommon.HTTP_NOT_FOUND), wsgireq, | |||
|
196 | cmd) | |||
|
197 | ||||
|
198 | return True, res | |||
183 |
|
199 | |||
184 | proto = httpv1protocolhandler(wsgireq, repo.ui, |
|
200 | proto = httpv1protocolhandler(wsgireq, repo.ui, | |
185 | lambda perm: checkperm(rctx, wsgireq, perm)) |
|
201 | lambda perm: checkperm(rctx, wsgireq, perm)) | |
186 |
|
202 | |||
187 | return { |
|
203 | # The permissions checker should be the only thing that can raise an | |
188 | 'cmd': cmd, |
|
204 | # ErrorResponse. It is kind of a layer violation to catch an hgweb | |
189 | 'proto': proto, |
|
205 | # exception here. So consider refactoring into a exception type that | |
190 | 'dispatch': lambda: _callhttp(repo, wsgireq, proto, cmd), |
|
206 | # is associated with the wire protocol. | |
191 | 'handleerror': lambda ex: _handlehttperror(ex, wsgireq, cmd), |
|
207 | try: | |
192 | } |
|
208 | res = _callhttp(repo, wsgireq, proto, cmd) | |
|
209 | except hgwebcommon.ErrorResponse as e: | |||
|
210 | res = _handlehttperror(e, wsgireq, cmd) | |||
|
211 | ||||
|
212 | return True, res | |||
193 |
|
213 | |||
194 | def _httpresponsetype(ui, wsgireq, prefer_uncompressed): |
|
214 | def _httpresponsetype(ui, wsgireq, prefer_uncompressed): | |
195 | """Determine the appropriate response type and compression settings. |
|
215 | """Determine the appropriate response type and compression settings. |
General Comments 0
You need to be logged in to leave comments.
Login now