Mercurial > hg
diff mercurial/httppeer.py @ 30763:a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Now that servers expose a capability indicating they support
application/mercurial-0.2 and compression, clients can key off
this to say they support responses that are compressed with
various compression formats.
After this commit, the HTTP wire protocol client now sends an
"X-HgProto-<N>" request header indicating its support for
"application/mercurial-0.2" media type and various compression
formats.
This commit also implements support for handling
"application/mercurial-0.2" responses. It simply reads the header
compression engine identifier then routes the remainder of the
response to the appropriate decompressor.
There were some test changes, but only to logging. That points to
an obvious gap in our test coverage. This will be addressed in a
subsequent commit once server support is in place (it is hard to
test without server support).
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 24 Dec 2016 15:22:18 -0700 |
parents | 3f5f0c98cd18 |
children | 48dea083f66d |
line wrap: on
line diff
--- a/mercurial/httppeer.py Sat Dec 24 15:21:46 2016 -0700 +++ b/mercurial/httppeer.py Sat Dec 24 15:22:18 2016 -0700 @@ -11,6 +11,7 @@ import errno import os import socket +import struct import tempfile from .i18n import _ @@ -174,6 +175,37 @@ if data is not None and 'Content-Type' not in headers: headers['Content-Type'] = 'application/mercurial-0.1' + # Tell the server we accept application/mercurial-0.2 and multiple + # compression formats if the server is capable of emitting those + # payloads. + protoparams = [] + + mediatypes = set() + if self.caps is not None: + mt = self.capable('httpmediatype') + if mt: + protoparams.append('0.1') + mediatypes = set(mt.split(',')) + + if '0.2tx' in mediatypes: + protoparams.append('0.2') + + if '0.2tx' in mediatypes and self.capable('compression'): + # We /could/ compare supported compression formats and prune + # non-mutually supported or error if nothing is mutually supported. + # For now, send the full list to the server and have it error. + comps = [e.wireprotosupport().name for e in + util.compengines.supportedwireengines(util.CLIENTROLE)] + protoparams.append('comp=%s' % ','.join(comps)) + + if protoparams: + protoheaders = encodevalueinheaders(' '.join(protoparams), + 'X-HgProto', + headersize or 1024) + for header, value in protoheaders: + headers[header] = value + varyheaders.append(header) + headers['Vary'] = ','.join(varyheaders) req = self.requestbuilder(cu, data, headers) @@ -224,7 +256,19 @@ except ValueError: raise error.RepoError(_("'%s' sent a broken Content-Type " "header (%s)") % (safeurl, proto)) - if version_info > (0, 1): + + if version_info == (0, 1): + if _compressible: + return decompressresponse(resp, util.compengines['zlib']) + return resp + elif version_info == (0, 2): + # application/mercurial-0.2 always identifies the compression + # engine in the payload header. + elen = struct.unpack('B', resp.read(1))[0] + ename = resp.read(elen) + engine = util.compengines.forwiretype(ename) + return decompressresponse(resp, engine) + else: raise error.RepoError(_("'%s' uses newer protocol %s") % (safeurl, version))