Mercurial > hg
comparison 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 |
comparison
equal
deleted
inserted
replaced
30762:35b516f800e0 | 30763:a520aefb96f1 |
---|---|
9 from __future__ import absolute_import | 9 from __future__ import absolute_import |
10 | 10 |
11 import errno | 11 import errno |
12 import os | 12 import os |
13 import socket | 13 import socket |
14 import struct | |
14 import tempfile | 15 import tempfile |
15 | 16 |
16 from .i18n import _ | 17 from .i18n import _ |
17 from .node import nullid | 18 from .node import nullid |
18 from . import ( | 19 from . import ( |
172 headers['Expect'] = '100-Continue' | 173 headers['Expect'] = '100-Continue' |
173 headers['X-HgHttp2'] = '1' | 174 headers['X-HgHttp2'] = '1' |
174 if data is not None and 'Content-Type' not in headers: | 175 if data is not None and 'Content-Type' not in headers: |
175 headers['Content-Type'] = 'application/mercurial-0.1' | 176 headers['Content-Type'] = 'application/mercurial-0.1' |
176 | 177 |
178 # Tell the server we accept application/mercurial-0.2 and multiple | |
179 # compression formats if the server is capable of emitting those | |
180 # payloads. | |
181 protoparams = [] | |
182 | |
183 mediatypes = set() | |
184 if self.caps is not None: | |
185 mt = self.capable('httpmediatype') | |
186 if mt: | |
187 protoparams.append('0.1') | |
188 mediatypes = set(mt.split(',')) | |
189 | |
190 if '0.2tx' in mediatypes: | |
191 protoparams.append('0.2') | |
192 | |
193 if '0.2tx' in mediatypes and self.capable('compression'): | |
194 # We /could/ compare supported compression formats and prune | |
195 # non-mutually supported or error if nothing is mutually supported. | |
196 # For now, send the full list to the server and have it error. | |
197 comps = [e.wireprotosupport().name for e in | |
198 util.compengines.supportedwireengines(util.CLIENTROLE)] | |
199 protoparams.append('comp=%s' % ','.join(comps)) | |
200 | |
201 if protoparams: | |
202 protoheaders = encodevalueinheaders(' '.join(protoparams), | |
203 'X-HgProto', | |
204 headersize or 1024) | |
205 for header, value in protoheaders: | |
206 headers[header] = value | |
207 varyheaders.append(header) | |
208 | |
177 headers['Vary'] = ','.join(varyheaders) | 209 headers['Vary'] = ','.join(varyheaders) |
178 req = self.requestbuilder(cu, data, headers) | 210 req = self.requestbuilder(cu, data, headers) |
179 | 211 |
180 if data is not None: | 212 if data is not None: |
181 self.ui.debug("sending %s bytes\n" % size) | 213 self.ui.debug("sending %s bytes\n" % size) |
222 version = proto.split('-', 1)[1] | 254 version = proto.split('-', 1)[1] |
223 version_info = tuple([int(n) for n in version.split('.')]) | 255 version_info = tuple([int(n) for n in version.split('.')]) |
224 except ValueError: | 256 except ValueError: |
225 raise error.RepoError(_("'%s' sent a broken Content-Type " | 257 raise error.RepoError(_("'%s' sent a broken Content-Type " |
226 "header (%s)") % (safeurl, proto)) | 258 "header (%s)") % (safeurl, proto)) |
227 if version_info > (0, 1): | 259 |
260 if version_info == (0, 1): | |
261 if _compressible: | |
262 return decompressresponse(resp, util.compengines['zlib']) | |
263 return resp | |
264 elif version_info == (0, 2): | |
265 # application/mercurial-0.2 always identifies the compression | |
266 # engine in the payload header. | |
267 elen = struct.unpack('B', resp.read(1))[0] | |
268 ename = resp.read(elen) | |
269 engine = util.compengines.forwiretype(ename) | |
270 return decompressresponse(resp, engine) | |
271 else: | |
228 raise error.RepoError(_("'%s' uses newer protocol %s") % | 272 raise error.RepoError(_("'%s' uses newer protocol %s") % |
229 (safeurl, version)) | 273 (safeurl, version)) |
230 | 274 |
231 if _compressible: | 275 if _compressible: |
232 return decompressresponse(resp, util.compengines['zlib']) | 276 return decompressresponse(resp, util.compengines['zlib']) |