Show More
@@ -33,6 +33,9 b' from .node import (' | |||
|
33 | 33 | nullrev, |
|
34 | 34 | short, |
|
35 | 35 | ) |
|
36 | from .thirdparty import ( | |
|
37 | cbor, | |
|
38 | ) | |
|
36 | 39 | from . import ( |
|
37 | 40 | bundle2, |
|
38 | 41 | changegroup, |
@@ -3045,9 +3048,14 b' def debugwireproto(ui, repo, path=None, ' | |||
|
3045 | 3048 | req.get_method = lambda: method |
|
3046 | 3049 | |
|
3047 | 3050 | try: |
|
3048 |
opener.open(req) |
|
|
3051 | res = opener.open(req) | |
|
3052 | body = res.read() | |
|
3049 | 3053 | except util.urlerr.urlerror as e: |
|
3050 | 3054 | e.read() |
|
3055 | continue | |
|
3056 | ||
|
3057 | if res.headers.get('Content-Type') == 'application/mercurial-cbor': | |
|
3058 | ui.write(_('cbor> %s\n') % stringutil.pprint(cbor.loads(body))) | |
|
3051 | 3059 | |
|
3052 | 3060 | elif action == 'close': |
|
3053 | 3061 | peer.close() |
@@ -42,8 +42,44 b' Handshake' | |||
|
42 | 42 | The client sends a ``capabilities`` command request (``?cmd=capabilities``) |
|
43 | 43 | as soon as HTTP requests may be issued. |
|
44 | 44 | |
|
45 |
|
|
|
46 | learn about the server's abilities. | |
|
45 | By default, the server responds with a version 1 capabilities string, which | |
|
46 | the client parses to learn about the server's abilities. The ``Content-Type`` | |
|
47 | for this response is ``application/mercurial-0.1`` or | |
|
48 | ``application/mercurial-0.2`` depending on whether the client advertised | |
|
49 | support for version ``0.2`` in its request. (Clients aren't supposed to | |
|
50 | advertise support for ``0.2`` until the capabilities response indicates | |
|
51 | the server's support for that media type. However, a client could | |
|
52 | conceivably cache this metadata and issue the capabilities request in such | |
|
53 | a way to elicit an ``application/mercurial-0.2`` response.) | |
|
54 | ||
|
55 | Clients wishing to switch to a newer API service may send an | |
|
56 | ``X-HgUpgrade-<X>`` header containing a space-delimited list of API service | |
|
57 | names the client is capable of speaking. The request MUST also include an | |
|
58 | ``X-HgProto-<X>`` header advertising a known serialization format for the | |
|
59 | response. ``cbor`` is currently the only defined serialization format. | |
|
60 | ||
|
61 | If the request contains these headers, the response ``Content-Type`` MAY | |
|
62 | be for a different media type. e.g. ``application/mercurial-cbor`` if the | |
|
63 | client advertises support for CBOR. | |
|
64 | ||
|
65 | The response MUST be deserializable to a map with the following keys: | |
|
66 | ||
|
67 | apibase | |
|
68 | URL path to API services, relative to the repository root. e.g. ``api/``. | |
|
69 | ||
|
70 | apis | |
|
71 | A map of API service names to API descriptors. An API descriptor contains | |
|
72 | more details about that API. In the case of the HTTP Version 2 Transport, | |
|
73 | it will be the normal response to a ``capabilities`` command. | |
|
74 | ||
|
75 | Only the services advertised by the client that are also available on | |
|
76 | the server are advertised. | |
|
77 | ||
|
78 | v1capabilities | |
|
79 | The capabilities string that would be returned by a version 1 response. | |
|
80 | ||
|
81 | The client can then inspect the server-advertised APIs and decide which | |
|
82 | API to use, including continuing to use the HTTP Version 1 Transport. | |
|
47 | 83 | |
|
48 | 84 | HTTP Version 1 Transport |
|
49 | 85 | ------------------------ |
@@ -123,6 +159,9 b' The ``application/hg-error`` media type ' | |||
|
123 | 159 | The content of the HTTP response body typically holds text describing the |
|
124 | 160 | error. |
|
125 | 161 | |
|
162 | The ``application/mercurial-cbor`` media type indicates a CBOR payload | |
|
163 | and should be interpreted as identical to ``application/cbor``. | |
|
164 | ||
|
126 | 165 | Behavior of media types is further described in the ``Content Negotiation`` |
|
127 | 166 | section below. |
|
128 | 167 | |
@@ -1252,6 +1291,12 b' 0.2' | |||
|
1252 | 1291 | Indicates the client supports receiving ``application/mercurial-0.2`` |
|
1253 | 1292 | responses. |
|
1254 | 1293 | |
|
1294 | cbor | |
|
1295 | Indicates the client supports receiving ``application/mercurial-cbor`` | |
|
1296 | responses. | |
|
1297 | ||
|
1298 | (Only intended to be used with version 2 transports.) | |
|
1299 | ||
|
1255 | 1300 | comp |
|
1256 | 1301 | Indicates compression formats the client can decode. Value is a list of |
|
1257 | 1302 | comma delimited strings identifying compression formats ordered from |
@@ -12,6 +12,9 b' import sys' | |||
|
12 | 12 | import threading |
|
13 | 13 | |
|
14 | 14 | from .i18n import _ |
|
15 | from .thirdparty import ( | |
|
16 | cbor, | |
|
17 | ) | |
|
15 | 18 | from .thirdparty.zope import ( |
|
16 | 19 | interface as zi, |
|
17 | 20 | ) |
@@ -230,6 +233,18 b' def handlewsgirequest(rctx, req, res, ch' | |||
|
230 | 233 | |
|
231 | 234 | return True |
|
232 | 235 | |
|
236 | def _availableapis(repo): | |
|
237 | apis = set() | |
|
238 | ||
|
239 | # Registered APIs are made available via config options of the name of | |
|
240 | # the protocol. | |
|
241 | for k, v in API_HANDLERS.items(): | |
|
242 | section, option = v['config'] | |
|
243 | if repo.ui.configbool(section, option): | |
|
244 | apis.add(k) | |
|
245 | ||
|
246 | return apis | |
|
247 | ||
|
233 | 248 | def handlewsgiapirequest(rctx, req, res, checkperm): |
|
234 | 249 | """Handle requests to /api/*.""" |
|
235 | 250 | assert req.dispatchparts[0] == b'api' |
@@ -247,13 +262,7 b' def handlewsgiapirequest(rctx, req, res,' | |||
|
247 | 262 | # The URL space is /api/<protocol>/*. The structure of URLs under varies |
|
248 | 263 | # by <protocol>. |
|
249 | 264 | |
|
250 | # Registered APIs are made available via config options of the name of | |
|
251 | # the protocol. | |
|
252 | availableapis = set() | |
|
253 | for k, v in API_HANDLERS.items(): | |
|
254 | section, option = v['config'] | |
|
255 | if repo.ui.configbool(section, option): | |
|
256 | availableapis.add(k) | |
|
265 | availableapis = _availableapis(repo) | |
|
257 | 266 | |
|
258 | 267 | # Requests to /api/ list available APIs. |
|
259 | 268 | if req.dispatchparts == [b'api']: |
@@ -287,10 +296,21 b' def handlewsgiapirequest(rctx, req, res,' | |||
|
287 | 296 | req.dispatchparts[2:]) |
|
288 | 297 | |
|
289 | 298 | # Maps API name to metadata so custom API can be registered. |
|
299 | # Keys are: | |
|
300 | # | |
|
301 | # config | |
|
302 | # Config option that controls whether service is enabled. | |
|
303 | # handler | |
|
304 | # Callable receiving (rctx, req, res, checkperm, urlparts) that is called | |
|
305 | # when a request to this API is received. | |
|
306 | # apidescriptor | |
|
307 | # Callable receiving (req, repo) that is called to obtain an API | |
|
308 | # descriptor for this service. The response must be serializable to CBOR. | |
|
290 | 309 | API_HANDLERS = { |
|
291 | 310 | wireprotov2server.HTTPV2: { |
|
292 | 311 | 'config': ('experimental', 'web.api.http-v2'), |
|
293 | 312 | 'handler': wireprotov2server.handlehttpv2request, |
|
313 | 'apidescriptor': wireprotov2server.httpv2apidescriptor, | |
|
294 | 314 | }, |
|
295 | 315 | } |
|
296 | 316 | |
@@ -327,6 +347,54 b' def _httpresponsetype(ui, proto, prefer_' | |||
|
327 | 347 | opts = {'level': ui.configint('server', 'zliblevel')} |
|
328 | 348 | return HGTYPE, util.compengines['zlib'], opts |
|
329 | 349 | |
|
350 | def processcapabilitieshandshake(repo, req, res, proto): | |
|
351 | """Called during a ?cmd=capabilities request. | |
|
352 | ||
|
353 | If the client is advertising support for a newer protocol, we send | |
|
354 | a CBOR response with information about available services. If no | |
|
355 | advertised services are available, we don't handle the request. | |
|
356 | """ | |
|
357 | # Fall back to old behavior unless the API server is enabled. | |
|
358 | if not repo.ui.configbool('experimental', 'web.apiserver'): | |
|
359 | return False | |
|
360 | ||
|
361 | clientapis = decodevaluefromheaders(req, b'X-HgUpgrade') | |
|
362 | protocaps = decodevaluefromheaders(req, b'X-HgProto') | |
|
363 | if not clientapis or not protocaps: | |
|
364 | return False | |
|
365 | ||
|
366 | # We currently only support CBOR responses. | |
|
367 | protocaps = set(protocaps.split(' ')) | |
|
368 | if b'cbor' not in protocaps: | |
|
369 | return False | |
|
370 | ||
|
371 | descriptors = {} | |
|
372 | ||
|
373 | for api in sorted(set(clientapis.split()) & _availableapis(repo)): | |
|
374 | handler = API_HANDLERS[api] | |
|
375 | ||
|
376 | descriptorfn = handler.get('apidescriptor') | |
|
377 | if not descriptorfn: | |
|
378 | continue | |
|
379 | ||
|
380 | descriptors[api] = descriptorfn(req, repo) | |
|
381 | ||
|
382 | v1caps = wireproto.dispatch(repo, proto, 'capabilities') | |
|
383 | assert isinstance(v1caps, wireprototypes.bytesresponse) | |
|
384 | ||
|
385 | m = { | |
|
386 | # TODO allow this to be configurable. | |
|
387 | 'apibase': 'api/', | |
|
388 | 'apis': descriptors, | |
|
389 | 'v1capabilities': v1caps.data, | |
|
390 | } | |
|
391 | ||
|
392 | res.status = b'200 OK' | |
|
393 | res.headers[b'Content-Type'] = b'application/mercurial-cbor' | |
|
394 | res.setbodybytes(cbor.dumps(m, canonical=True)) | |
|
395 | ||
|
396 | return True | |
|
397 | ||
|
330 | 398 | def _callhttp(repo, req, res, proto, cmd): |
|
331 | 399 | # Avoid cycle involving hg module. |
|
332 | 400 | from .hgweb import common as hgwebcommon |
@@ -363,6 +431,12 b' def _callhttp(repo, req, res, proto, cmd' | |||
|
363 | 431 | |
|
364 | 432 | proto.checkperm(wireproto.commands[cmd].permission) |
|
365 | 433 | |
|
434 | # Possibly handle a modern client wanting to switch protocols. | |
|
435 | if (cmd == 'capabilities' and | |
|
436 | processcapabilitieshandshake(repo, req, res, proto)): | |
|
437 | ||
|
438 | return | |
|
439 | ||
|
366 | 440 | rsp = wireproto.dispatch(repo, proto, cmd) |
|
367 | 441 | |
|
368 | 442 | if isinstance(rsp, bytes): |
@@ -365,6 +365,11 b' class httpv2protocolhandler(object):' | |||
|
365 | 365 | def checkperm(self, perm): |
|
366 | 366 | raise NotImplementedError |
|
367 | 367 | |
|
368 | def httpv2apidescriptor(req, repo): | |
|
369 | proto = httpv2protocolhandler(req, repo.ui) | |
|
370 | ||
|
371 | return _capabilitiesv2(repo, proto) | |
|
372 | ||
|
368 | 373 | def _capabilitiesv2(repo, proto): |
|
369 | 374 | """Obtain the set of capabilities for version 2 transports. |
|
370 | 375 |
@@ -1,11 +1,201 b'' | |||
|
1 | 1 | $ . $TESTDIR/wireprotohelpers.sh |
|
2 | 2 | |
|
3 | 3 | $ hg init server |
|
4 | $ enablehttpv2 server | |
|
4 | $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log | |
|
5 | $ cat hg.pid > $DAEMON_PIDS | |
|
6 | ||
|
7 | A normal capabilities request is serviced for version 1 | |
|
8 | ||
|
9 | $ sendhttpraw << EOF | |
|
10 | > httprequest GET ?cmd=capabilities | |
|
11 | > user-agent: test | |
|
12 | > EOF | |
|
13 | using raw connection to peer | |
|
14 | s> GET /?cmd=capabilities HTTP/1.1\r\n | |
|
15 | s> Accept-Encoding: identity\r\n | |
|
16 | s> user-agent: test\r\n | |
|
17 | s> host: $LOCALIP:$HGPORT\r\n (glob) | |
|
18 | s> \r\n | |
|
19 | s> makefile('rb', None) | |
|
20 | s> HTTP/1.1 200 Script output follows\r\n | |
|
21 | s> Server: testing stub value\r\n | |
|
22 | s> Date: $HTTP_DATE$\r\n | |
|
23 | s> Content-Type: application/mercurial-0.1\r\n | |
|
24 | s> Content-Length: 458\r\n | |
|
25 | s> \r\n | |
|
26 | s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash | |
|
27 | ||
|
28 | A proper request without the API server enabled returns the legacy response | |
|
29 | ||
|
30 | $ sendhttpraw << EOF | |
|
31 | > httprequest GET ?cmd=capabilities | |
|
32 | > user-agent: test | |
|
33 | > x-hgupgrade-1: foo | |
|
34 | > x-hgproto-1: cbor | |
|
35 | > EOF | |
|
36 | using raw connection to peer | |
|
37 | s> GET /?cmd=capabilities HTTP/1.1\r\n | |
|
38 | s> Accept-Encoding: identity\r\n | |
|
39 | s> user-agent: test\r\n | |
|
40 | s> x-hgproto-1: cbor\r\n | |
|
41 | s> x-hgupgrade-1: foo\r\n | |
|
42 | s> host: $LOCALIP:$HGPORT\r\n (glob) | |
|
43 | s> \r\n | |
|
44 | s> makefile('rb', None) | |
|
45 | s> HTTP/1.1 200 Script output follows\r\n | |
|
46 | s> Server: testing stub value\r\n | |
|
47 | s> Date: $HTTP_DATE$\r\n | |
|
48 | s> Content-Type: application/mercurial-0.1\r\n | |
|
49 | s> Content-Length: 458\r\n | |
|
50 | s> \r\n | |
|
51 | s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash | |
|
52 | ||
|
53 | Restart with just API server enabled. This enables serving the new format. | |
|
54 | ||
|
55 | $ killdaemons.py | |
|
56 | $ cat error.log | |
|
57 | ||
|
58 | $ cat >> server/.hg/hgrc << EOF | |
|
59 | > [experimental] | |
|
60 | > web.apiserver = true | |
|
61 | > EOF | |
|
62 | ||
|
5 | 63 | $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log |
|
6 | 64 | $ cat hg.pid > $DAEMON_PIDS |
|
7 | 65 | |
|
8 | capabilities request returns an array of capability strings | |
|
66 | X-HgUpgrade-<N> without CBOR advertisement uses legacy response | |
|
67 | ||
|
68 | $ sendhttpraw << EOF | |
|
69 | > httprequest GET ?cmd=capabilities | |
|
70 | > user-agent: test | |
|
71 | > x-hgupgrade-1: foo bar | |
|
72 | > EOF | |
|
73 | using raw connection to peer | |
|
74 | s> GET /?cmd=capabilities HTTP/1.1\r\n | |
|
75 | s> Accept-Encoding: identity\r\n | |
|
76 | s> user-agent: test\r\n | |
|
77 | s> x-hgupgrade-1: foo bar\r\n | |
|
78 | s> host: $LOCALIP:$HGPORT\r\n (glob) | |
|
79 | s> \r\n | |
|
80 | s> makefile('rb', None) | |
|
81 | s> HTTP/1.1 200 Script output follows\r\n | |
|
82 | s> Server: testing stub value\r\n | |
|
83 | s> Date: $HTTP_DATE$\r\n | |
|
84 | s> Content-Type: application/mercurial-0.1\r\n | |
|
85 | s> Content-Length: 458\r\n | |
|
86 | s> \r\n | |
|
87 | s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash | |
|
88 | ||
|
89 | X-HgUpgrade-<N> without known serialization in X-HgProto-<N> uses legacy response | |
|
90 | ||
|
91 | $ sendhttpraw << EOF | |
|
92 | > httprequest GET ?cmd=capabilities | |
|
93 | > user-agent: test | |
|
94 | > x-hgupgrade-1: foo bar | |
|
95 | > x-hgproto-1: some value | |
|
96 | > EOF | |
|
97 | using raw connection to peer | |
|
98 | s> GET /?cmd=capabilities HTTP/1.1\r\n | |
|
99 | s> Accept-Encoding: identity\r\n | |
|
100 | s> user-agent: test\r\n | |
|
101 | s> x-hgproto-1: some value\r\n | |
|
102 | s> x-hgupgrade-1: foo bar\r\n | |
|
103 | s> host: $LOCALIP:$HGPORT\r\n (glob) | |
|
104 | s> \r\n | |
|
105 | s> makefile('rb', None) | |
|
106 | s> HTTP/1.1 200 Script output follows\r\n | |
|
107 | s> Server: testing stub value\r\n | |
|
108 | s> Date: $HTTP_DATE$\r\n | |
|
109 | s> Content-Type: application/mercurial-0.1\r\n | |
|
110 | s> Content-Length: 458\r\n | |
|
111 | s> \r\n | |
|
112 | s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash | |
|
113 | ||
|
114 | X-HgUpgrade-<N> + X-HgProto-<N> headers trigger new response format | |
|
115 | ||
|
116 | $ sendhttpraw << EOF | |
|
117 | > httprequest GET ?cmd=capabilities | |
|
118 | > user-agent: test | |
|
119 | > x-hgupgrade-1: foo bar | |
|
120 | > x-hgproto-1: cbor | |
|
121 | > EOF | |
|
122 | using raw connection to peer | |
|
123 | s> GET /?cmd=capabilities HTTP/1.1\r\n | |
|
124 | s> Accept-Encoding: identity\r\n | |
|
125 | s> user-agent: test\r\n | |
|
126 | s> x-hgproto-1: cbor\r\n | |
|
127 | s> x-hgupgrade-1: foo bar\r\n | |
|
128 | s> host: $LOCALIP:$HGPORT\r\n (glob) | |
|
129 | s> \r\n | |
|
130 | s> makefile('rb', None) | |
|
131 | s> HTTP/1.1 200 OK\r\n | |
|
132 | s> Server: testing stub value\r\n | |
|
133 | s> Date: $HTTP_DATE$\r\n | |
|
134 | s> Content-Type: application/mercurial-cbor\r\n | |
|
135 | s> Content-Length: 496\r\n | |
|
136 | s> \r\n | |
|
137 | s> \xa3Dapis\xa0GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash | |
|
138 | cbor> {b'apibase': b'api/', b'apis': {}, b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'} | |
|
139 | ||
|
140 | Restart server to enable HTTPv2 | |
|
141 | ||
|
142 | $ killdaemons.py | |
|
143 | $ enablehttpv2 server | |
|
144 | $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log | |
|
145 | ||
|
146 | Only requested API services are returned | |
|
147 | ||
|
148 | $ sendhttpraw << EOF | |
|
149 | > httprequest GET ?cmd=capabilities | |
|
150 | > user-agent: test | |
|
151 | > x-hgupgrade-1: foo bar | |
|
152 | > x-hgproto-1: cbor | |
|
153 | > EOF | |
|
154 | using raw connection to peer | |
|
155 | s> GET /?cmd=capabilities HTTP/1.1\r\n | |
|
156 | s> Accept-Encoding: identity\r\n | |
|
157 | s> user-agent: test\r\n | |
|
158 | s> x-hgproto-1: cbor\r\n | |
|
159 | s> x-hgupgrade-1: foo bar\r\n | |
|
160 | s> host: $LOCALIP:$HGPORT\r\n (glob) | |
|
161 | s> \r\n | |
|
162 | s> makefile('rb', None) | |
|
163 | s> HTTP/1.1 200 OK\r\n | |
|
164 | s> Server: testing stub value\r\n | |
|
165 | s> Date: $HTTP_DATE$\r\n | |
|
166 | s> Content-Type: application/mercurial-cbor\r\n | |
|
167 | s> Content-Length: 496\r\n | |
|
168 | s> \r\n | |
|
169 | s> \xa3Dapis\xa0GapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash | |
|
170 | cbor> {b'apibase': b'api/', b'apis': {}, b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'} | |
|
171 | ||
|
172 | Request for HTTPv2 service returns information about it | |
|
173 | ||
|
174 | $ sendhttpraw << EOF | |
|
175 | > httprequest GET ?cmd=capabilities | |
|
176 | > user-agent: test | |
|
177 | > x-hgupgrade-1: exp-http-v2-0001 foo bar | |
|
178 | > x-hgproto-1: cbor | |
|
179 | > EOF | |
|
180 | using raw connection to peer | |
|
181 | s> GET /?cmd=capabilities HTTP/1.1\r\n | |
|
182 | s> Accept-Encoding: identity\r\n | |
|
183 | s> user-agent: test\r\n | |
|
184 | s> x-hgproto-1: cbor\r\n | |
|
185 | s> x-hgupgrade-1: exp-http-v2-0001 foo bar\r\n | |
|
186 | s> host: $LOCALIP:$HGPORT\r\n (glob) | |
|
187 | s> \r\n | |
|
188 | s> makefile('rb', None) | |
|
189 | s> HTTP/1.1 200 OK\r\n | |
|
190 | s> Server: testing stub value\r\n | |
|
191 | s> Date: $HTTP_DATE$\r\n | |
|
192 | s> Content-Type: application/mercurial-cbor\r\n | |
|
193 | s> Content-Length: 879\r\n | |
|
194 | s> \r\n | |
|
195 | s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash | |
|
196 | cbor> {b'apibase': b'api/', b'apis': {b'exp-http-v2-0001': {b'commands': {b'branchmap': {b'args': {}, b'permissions': [b'pull']}, b'capabilities': {b'args': {}, b'permissions': [b'pull']}, b'heads': {b'args': {b'publiconly': False}, b'permissions': [b'pull']}, b'known': {b'args': {b'nodes': [b'deadbeef']}, b'permissions': [b'pull']}, b'listkeys': {b'args': {b'namespace': b'ns'}, b'permissions': [b'pull']}, b'lookup': {b'args': {b'key': b'foo'}, b'permissions': [b'pull']}, b'pushkey': {b'args': {b'key': b'key', b'namespace': b'ns', b'new': b'new', b'old': b'old'}, b'permissions': [b'push']}}, b'compression': [{b'name': b'zstd'}, {b'name': b'zlib'}]}}, b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'} | |
|
197 | ||
|
198 | capabilities command returns expected info | |
|
9 | 199 | |
|
10 | 200 | $ sendhttpv2peer << EOF |
|
11 | 201 | > command capabilities |
General Comments 0
You need to be logged in to leave comments.
Login now