Mercurial > hg
comparison mercurial/httppeer.py @ 37551:946eb204ba67
httppeer: extract common response handling into own function
This allows the common redirect detection, content type
validation, and decompression wrapping to be usable outside of
httppeer instances.
Differential Revision: https://phab.mercurial-scm.org/D3236
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 10 Apr 2018 12:52:29 -0700 |
parents | b5862ee01abe |
children | 8b8a845c85fc |
comparison
equal
deleted
inserted
replaced
37550:b5862ee01abe | 37551:946eb204ba67 |
---|---|
303 # Insert error handlers for common I/O failures. | 303 # Insert error handlers for common I/O failures. |
304 _wraphttpresponse(res) | 304 _wraphttpresponse(res) |
305 | 305 |
306 return res | 306 return res |
307 | 307 |
308 def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible): | |
309 # record the url we got redirected to | |
310 respurl = pycompat.bytesurl(resp.geturl()) | |
311 if respurl.endswith(qs): | |
312 respurl = respurl[:-len(qs)] | |
313 if baseurl.rstrip('/') != respurl.rstrip('/'): | |
314 if not ui.quiet: | |
315 ui.warn(_('real URL is %s\n') % respurl) | |
316 | |
317 try: | |
318 proto = pycompat.bytesurl(resp.getheader(r'content-type', r'')) | |
319 except AttributeError: | |
320 proto = pycompat.bytesurl(resp.headers.get(r'content-type', r'')) | |
321 | |
322 safeurl = util.hidepassword(baseurl) | |
323 if proto.startswith('application/hg-error'): | |
324 raise error.OutOfBandError(resp.read()) | |
325 # accept old "text/plain" and "application/hg-changegroup" for now | |
326 if not (proto.startswith('application/mercurial-') or | |
327 (proto.startswith('text/plain') | |
328 and not resp.headers.get('content-length')) or | |
329 proto.startswith('application/hg-changegroup')): | |
330 ui.debug("requested URL: '%s'\n" % util.hidepassword(requrl)) | |
331 raise error.RepoError( | |
332 _("'%s' does not appear to be an hg repository:\n" | |
333 "---%%<--- (%s)\n%s\n---%%<---\n") | |
334 % (safeurl, proto or 'no content-type', resp.read(1024))) | |
335 | |
336 if proto.startswith('application/mercurial-'): | |
337 try: | |
338 version = proto.split('-', 1)[1] | |
339 version_info = tuple([int(n) for n in version.split('.')]) | |
340 except ValueError: | |
341 raise error.RepoError(_("'%s' sent a broken Content-Type " | |
342 "header (%s)") % (safeurl, proto)) | |
343 | |
344 # TODO consider switching to a decompression reader that uses | |
345 # generators. | |
346 if version_info == (0, 1): | |
347 if compressible: | |
348 resp = util.compengines['zlib'].decompressorreader(resp) | |
349 | |
350 return respurl, resp | |
351 | |
352 elif version_info == (0, 2): | |
353 # application/mercurial-0.2 always identifies the compression | |
354 # engine in the payload header. | |
355 elen = struct.unpack('B', resp.read(1))[0] | |
356 ename = resp.read(elen) | |
357 engine = util.compengines.forwiretype(ename) | |
358 return respurl, engine.decompressorreader(resp) | |
359 else: | |
360 raise error.RepoError(_("'%s' uses newer protocol %s") % | |
361 (safeurl, version)) | |
362 | |
363 if compressible: | |
364 resp = util.compengines['zlib'].decompressorreader(resp) | |
365 | |
366 return respurl, resp | |
367 | |
308 class httppeer(wireproto.wirepeer): | 368 class httppeer(wireproto.wirepeer): |
309 def __init__(self, ui, path, url, opener, requestbuilder): | 369 def __init__(self, ui, path, url, opener, requestbuilder): |
310 self.ui = ui | 370 self.ui = ui |
311 self._path = path | 371 self._path = path |
312 self._url = url | 372 self._url = url |
360 self._caps, self.capable, | 420 self._caps, self.capable, |
361 self._url, cmd, args) | 421 self._url, cmd, args) |
362 | 422 |
363 resp = sendrequest(self.ui, self._urlopener, req) | 423 resp = sendrequest(self.ui, self._urlopener, req) |
364 | 424 |
365 # record the url we got redirected to | 425 self._url, resp = parsev1commandresponse(self.ui, self._url, cu, qs, |
366 resp_url = pycompat.bytesurl(resp.geturl()) | 426 resp, _compressible) |
367 if resp_url.endswith(qs): | |
368 resp_url = resp_url[:-len(qs)] | |
369 if self._url.rstrip('/') != resp_url.rstrip('/'): | |
370 if not self.ui.quiet: | |
371 self.ui.warn(_('real URL is %s\n') % resp_url) | |
372 self._url = resp_url | |
373 try: | |
374 proto = pycompat.bytesurl(resp.getheader(r'content-type', r'')) | |
375 except AttributeError: | |
376 proto = pycompat.bytesurl(resp.headers.get(r'content-type', r'')) | |
377 | |
378 safeurl = util.hidepassword(self._url) | |
379 if proto.startswith('application/hg-error'): | |
380 raise error.OutOfBandError(resp.read()) | |
381 # accept old "text/plain" and "application/hg-changegroup" for now | |
382 if not (proto.startswith('application/mercurial-') or | |
383 (proto.startswith('text/plain') | |
384 and not resp.headers.get('content-length')) or | |
385 proto.startswith('application/hg-changegroup')): | |
386 self.ui.debug("requested URL: '%s'\n" % util.hidepassword(cu)) | |
387 raise error.RepoError( | |
388 _("'%s' does not appear to be an hg repository:\n" | |
389 "---%%<--- (%s)\n%s\n---%%<---\n") | |
390 % (safeurl, proto or 'no content-type', resp.read(1024))) | |
391 | |
392 if proto.startswith('application/mercurial-'): | |
393 try: | |
394 version = proto.split('-', 1)[1] | |
395 version_info = tuple([int(n) for n in version.split('.')]) | |
396 except ValueError: | |
397 raise error.RepoError(_("'%s' sent a broken Content-Type " | |
398 "header (%s)") % (safeurl, proto)) | |
399 | |
400 # TODO consider switching to a decompression reader that uses | |
401 # generators. | |
402 if version_info == (0, 1): | |
403 if _compressible: | |
404 return util.compengines['zlib'].decompressorreader(resp) | |
405 return resp | |
406 elif version_info == (0, 2): | |
407 # application/mercurial-0.2 always identifies the compression | |
408 # engine in the payload header. | |
409 elen = struct.unpack('B', resp.read(1))[0] | |
410 ename = resp.read(elen) | |
411 engine = util.compengines.forwiretype(ename) | |
412 return engine.decompressorreader(resp) | |
413 else: | |
414 raise error.RepoError(_("'%s' uses newer protocol %s") % | |
415 (safeurl, version)) | |
416 | |
417 if _compressible: | |
418 return util.compengines['zlib'].decompressorreader(resp) | |
419 | 427 |
420 return resp | 428 return resp |
421 | 429 |
422 def _call(self, cmd, **args): | 430 def _call(self, cmd, **args): |
423 fp = self._callstream(cmd, **args) | 431 fp = self._callstream(cmd, **args) |