##// END OF EJS Templates
wireprotoserver: move all wire protocol handling logic out of hgweb...
Gregory Szorc -
r36830:158d4ecc default
parent child Browse files
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 parsehttprequest(rctx, wsgireq, req, checkperm):
153 def handlewsgirequest(rctx, wsgireq, req, checkperm):
154 """Parse the HTTP request for a wire protocol request.
154 """Possibly process a wire protocol request.
155
155
156 If the current request appears to be a wire protocol request, this
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