author | Gregory Szorc <gregory.szorc@gmail.com> |
Tue, 02 Oct 2018 10:31:36 -0700 | |
changeset 40177 | 41e2633bcd00 |
parent 40176 | 41263df08109 |
child 40178 | 46a40bce3ae0 |
permissions | -rw-r--r-- |
5598
d534ba1c4eb4
separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff
changeset
|
1 |
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> |
d534ba1c4eb4
separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff
changeset
|
2 |
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
d534ba1c4eb4
separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff
changeset
|
3 |
# |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8109
diff
changeset
|
4 |
# This software may be used and distributed according to the terms of the |
10263 | 5 |
# GNU General Public License version 2 or any later version. |
5598
d534ba1c4eb4
separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff
changeset
|
6 |
|
27046
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
20903
diff
changeset
|
7 |
from __future__ import absolute_import |
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
20903
diff
changeset
|
8 |
|
36066
2ad145fbde54
wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36065
diff
changeset
|
9 |
import contextlib |
40021
c537144fdbef
wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39995
diff
changeset
|
10 |
import hashlib |
27046
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
20903
diff
changeset
|
11 |
|
35859
1bf5263fe5cc
wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35858
diff
changeset
|
12 |
from .i18n import _ |
39630
9c2c77c73f23
wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
13 |
from .node import ( |
39639
0e03e6a44dee
wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39637
diff
changeset
|
14 |
hex, |
39630
9c2c77c73f23
wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
15 |
nullid, |
9c2c77c73f23
wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
16 |
) |
35856
ef3a24a023ec
wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35750
diff
changeset
|
17 |
from . import ( |
39630
9c2c77c73f23
wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
18 |
discovery, |
37546
3a2367e6c6f2
wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37545
diff
changeset
|
19 |
encoding, |
34509
e21f274cccea
hgweb: in protocol adapter, avoid control reaching end of non-void function
Augie Fackler <augie@google.com>
parents:
33821
diff
changeset
|
20 |
error, |
39811
ae20f52437e9
wireprotov2: advertise recognized path filter prefixes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39810
diff
changeset
|
21 |
narrowspec, |
34742
5a9cad0dfddb
hgweb: when unpacking args from request form, convert to bytes
Augie Fackler <augie@google.com>
parents:
34740
diff
changeset
|
22 |
pycompat, |
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
23 |
wireprotoframing, |
36073
cd6ab329c5c7
wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36072
diff
changeset
|
24 |
wireprototypes, |
27046
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
20903
diff
changeset
|
25 |
) |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37784
diff
changeset
|
26 |
from .utils import ( |
40021
c537144fdbef
wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39995
diff
changeset
|
27 |
cborutil, |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37784
diff
changeset
|
28 |
interfaceutil, |
39837
69b4a5b89dc5
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39828
diff
changeset
|
29 |
stringutil, |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37784
diff
changeset
|
30 |
) |
35856
ef3a24a023ec
wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35750
diff
changeset
|
31 |
|
40133
762ef19a07e3
wireprotov2: send protocol settings frame from client
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40129
diff
changeset
|
32 |
FRAMINGTYPE = b'application/mercurial-exp-framing-0006' |
11595
368cd5325348
protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents:
11594
diff
changeset
|
33 |
|
37644
77c9ee77687c
wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37557
diff
changeset
|
34 |
HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2 |
35976
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35900
diff
changeset
|
35 |
|
37784
ee0d5e9d77b2
wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37783
diff
changeset
|
36 |
COMMANDS = wireprototypes.commanddict() |
ee0d5e9d77b2
wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37783
diff
changeset
|
37 |
|
40021
c537144fdbef
wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39995
diff
changeset
|
38 |
# Value inserted into cache key computation function. Change the value to |
c537144fdbef
wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39995
diff
changeset
|
39 |
# force new cache keys for every command request. This should be done when |
c537144fdbef
wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39995
diff
changeset
|
40 |
# there is a change to how caching works, etc. |
c537144fdbef
wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39995
diff
changeset
|
41 |
GLOBAL_CACHE_VERSION = 1 |
c537144fdbef
wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39995
diff
changeset
|
42 |
|
37545
93397c4633f6
wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37535
diff
changeset
|
43 |
def handlehttpv2request(rctx, req, res, checkperm, urlparts): |
37047
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
44 |
from .hgweb import common as hgwebcommon |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
45 |
|
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
46 |
# URL space looks like: <permissions>/<command>, where <permission> can |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
47 |
# be ``ro`` or ``rw`` to signal read-only or read-write, respectively. |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
48 |
|
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
49 |
# Root URL does nothing meaningful... yet. |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
50 |
if not urlparts: |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
51 |
res.status = b'200 OK' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
52 |
res.headers[b'Content-Type'] = b'text/plain' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
53 |
res.setbodybytes(_('HTTP version 2 API handler')) |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
54 |
return |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
55 |
|
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
56 |
if len(urlparts) == 1: |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
57 |
res.status = b'404 Not Found' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
58 |
res.headers[b'Content-Type'] = b'text/plain' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
59 |
res.setbodybytes(_('do not know how to process %s\n') % |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
60 |
req.dispatchpath) |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
61 |
return |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
62 |
|
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
63 |
permission, command = urlparts[0:2] |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
64 |
|
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
65 |
if permission not in (b'ro', b'rw'): |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
66 |
res.status = b'404 Not Found' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
67 |
res.headers[b'Content-Type'] = b'text/plain' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
68 |
res.setbodybytes(_('unknown permission: %s') % permission) |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
69 |
return |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
70 |
|
37048
fc5e261915b9
wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37047
diff
changeset
|
71 |
if req.method != 'POST': |
fc5e261915b9
wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37047
diff
changeset
|
72 |
res.status = b'405 Method Not Allowed' |
fc5e261915b9
wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37047
diff
changeset
|
73 |
res.headers[b'Allow'] = b'POST' |
fc5e261915b9
wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37047
diff
changeset
|
74 |
res.setbodybytes(_('commands require POST requests')) |
fc5e261915b9
wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37047
diff
changeset
|
75 |
return |
fc5e261915b9
wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37047
diff
changeset
|
76 |
|
37047
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
77 |
# At some point we'll want to use our own API instead of recycling the |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
78 |
# behavior of version 1 of the wire protocol... |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
79 |
# TODO return reasonable responses - not responses that overload the |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
80 |
# HTTP status line message for error reporting. |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
81 |
try: |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
82 |
checkperm(rctx, req, 'pull' if permission == b'ro' else 'push') |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
83 |
except hgwebcommon.ErrorResponse as e: |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
84 |
res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e)) |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
85 |
for k, v in e.headers: |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
86 |
res.headers[k] = v |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
87 |
res.setbodybytes('permission denied') |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
88 |
return |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
89 |
|
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
90 |
# We have a special endpoint to reflect the request back at the client. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
91 |
if command == b'debugreflect': |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
92 |
_processhttpv2reflectrequest(rctx.repo.ui, rctx.repo, req, res) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
93 |
return |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
94 |
|
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
95 |
# Extra commands that we handle that aren't really wire protocol |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
96 |
# commands. Think extra hard before making this hackery available to |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
97 |
# extension. |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
98 |
extracommands = {'multirequest'} |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
99 |
|
37784
ee0d5e9d77b2
wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37783
diff
changeset
|
100 |
if command not in COMMANDS and command not in extracommands: |
37047
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
101 |
res.status = b'404 Not Found' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
102 |
res.headers[b'Content-Type'] = b'text/plain' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
103 |
res.setbodybytes(_('unknown wire protocol command: %s\n') % command) |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
104 |
return |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
105 |
|
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
106 |
repo = rctx.repo |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
107 |
ui = repo.ui |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
108 |
|
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
109 |
proto = httpv2protocolhandler(req, ui) |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
110 |
|
37784
ee0d5e9d77b2
wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37783
diff
changeset
|
111 |
if (not COMMANDS.commandavailable(command, proto) |
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
112 |
and command not in extracommands): |
37047
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
113 |
res.status = b'404 Not Found' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
114 |
res.headers[b'Content-Type'] = b'text/plain' |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
115 |
res.setbodybytes(_('invalid wire protocol command: %s') % command) |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
116 |
return |
fddcb51b5084
wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37046
diff
changeset
|
117 |
|
37129
aaabd709df72
wireproto: review fixups
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37120
diff
changeset
|
118 |
# TODO consider cases where proxies may add additional Accept headers. |
37051
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37050
diff
changeset
|
119 |
if req.headers.get(b'Accept') != FRAMINGTYPE: |
37050
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
120 |
res.status = b'406 Not Acceptable' |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
121 |
res.headers[b'Content-Type'] = b'text/plain' |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
122 |
res.setbodybytes(_('client MUST specify Accept header with value: %s\n') |
37051
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37050
diff
changeset
|
123 |
% FRAMINGTYPE) |
37050
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
124 |
return |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
125 |
|
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
126 |
if req.headers.get(b'Content-Type') != FRAMINGTYPE: |
37050
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
127 |
res.status = b'415 Unsupported Media Type' |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
128 |
# TODO we should send a response with appropriate media type, |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
129 |
# since client does Accept it. |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
130 |
res.headers[b'Content-Type'] = b'text/plain' |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
131 |
res.setbodybytes(_('client MUST send Content-Type header with ' |
37051
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37050
diff
changeset
|
132 |
'value: %s\n') % FRAMINGTYPE) |
37050
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
133 |
return |
37d7a1d18b97
wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37048
diff
changeset
|
134 |
|
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
135 |
_processhttpv2request(ui, repo, req, res, permission, command, proto) |
37046
1cfef5693203
wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36877
diff
changeset
|
136 |
|
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
137 |
def _processhttpv2reflectrequest(ui, repo, req, res): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
138 |
"""Reads unified frame protocol request and dumps out state to client. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
139 |
|
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
140 |
This special endpoint can be used to help debug the wire protocol. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
141 |
|
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
142 |
Instead of routing the request through the normal dispatch mechanism, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
143 |
we instead read all frames, decode them, and feed them into our state |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
144 |
tracker. We then dump the log of all that activity back out to the |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
145 |
client. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
146 |
""" |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
147 |
import json |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
148 |
|
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
149 |
# Reflection APIs have a history of being abused, accidentally disclosing |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
150 |
# sensitive data, etc. So we have a config knob. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
151 |
if not ui.configbool('experimental', 'web.api.debugreflect'): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
152 |
res.status = b'404 Not Found' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
153 |
res.headers[b'Content-Type'] = b'text/plain' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
154 |
res.setbodybytes(_('debugreflect service not available')) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
155 |
return |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
156 |
|
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
157 |
# We assume we have a unified framing protocol request body. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
158 |
|
40129
293835e0fff7
wireprotov2: pass ui into clientreactor and serverreactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40122
diff
changeset
|
159 |
reactor = wireprotoframing.serverreactor(ui) |
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
160 |
states = [] |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
161 |
|
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
162 |
while True: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
163 |
frame = wireprotoframing.readframe(req.bodyfh) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
164 |
|
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
165 |
if not frame: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
166 |
states.append(b'received: <no frame>') |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
167 |
break |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
168 |
|
37061
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
169 |
states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags, |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
170 |
frame.requestid, |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
171 |
frame.payload)) |
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
172 |
|
37061
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
173 |
action, meta = reactor.onframerecv(frame) |
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
174 |
states.append(json.dumps((action, meta), sort_keys=True, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
175 |
separators=(', ', ': '))) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
176 |
|
37056
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
177 |
action, meta = reactor.oninputeof() |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
178 |
meta['action'] = action |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
179 |
states.append(json.dumps(meta, sort_keys=True, separators=(', ',': '))) |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
180 |
|
37052
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
181 |
res.status = b'200 OK' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
182 |
res.headers[b'Content-Type'] = b'text/plain' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
183 |
res.setbodybytes(b'\n'.join(states)) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37051
diff
changeset
|
184 |
|
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
185 |
def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto): |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
186 |
"""Post-validation handler for HTTPv2 requests. |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
187 |
|
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
188 |
Called when the HTTP request contains unified frame-based protocol |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
189 |
frames for evaluation. |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
190 |
""" |
37056
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
191 |
# TODO Some HTTP clients are full duplex and can receive data before |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
192 |
# the entire request is transmitted. Figure out a way to indicate support |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
193 |
# for that so we can opt into full duplex mode. |
40129
293835e0fff7
wireprotov2: pass ui into clientreactor and serverreactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40122
diff
changeset
|
194 |
reactor = wireprotoframing.serverreactor(ui, deferoutput=True) |
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
195 |
seencommand = False |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
196 |
|
40138
b5bf3dd6ec5b
wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40133
diff
changeset
|
197 |
outstream = None |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
198 |
|
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
199 |
while True: |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
200 |
frame = wireprotoframing.readframe(req.bodyfh) |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
201 |
if not frame: |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
202 |
break |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
203 |
|
37061
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
204 |
action, meta = reactor.onframerecv(frame) |
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
205 |
|
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
206 |
if action == 'wantframe': |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
207 |
# Need more data before we can do anything. |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
208 |
continue |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
209 |
elif action == 'runcommand': |
40138
b5bf3dd6ec5b
wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40133
diff
changeset
|
210 |
# Defer creating output stream because we need to wait for |
b5bf3dd6ec5b
wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40133
diff
changeset
|
211 |
# protocol settings frames so proper encoding can be applied. |
b5bf3dd6ec5b
wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40133
diff
changeset
|
212 |
if not outstream: |
b5bf3dd6ec5b
wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40133
diff
changeset
|
213 |
outstream = reactor.makeoutputstream() |
b5bf3dd6ec5b
wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40133
diff
changeset
|
214 |
|
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
215 |
sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm, |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
216 |
reqcommand, reactor, outstream, |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
217 |
meta, issubsequent=seencommand) |
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
218 |
|
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
219 |
if sentoutput: |
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
220 |
return |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
221 |
|
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
222 |
seencommand = True |
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
223 |
|
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
224 |
elif action == 'error': |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
225 |
# TODO define proper error mechanism. |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
226 |
res.status = b'200 OK' |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
227 |
res.headers[b'Content-Type'] = b'text/plain' |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
228 |
res.setbodybytes(meta['message'] + b'\n') |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
229 |
return |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
230 |
else: |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
231 |
raise error.ProgrammingError( |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
232 |
'unhandled action from frame processor: %s' % action) |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
233 |
|
37056
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
234 |
action, meta = reactor.oninputeof() |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
235 |
if action == 'sendframes': |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
236 |
# We assume we haven't started sending the response yet. If we're |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
237 |
# wrong, the response type will raise an exception. |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
238 |
res.status = b'200 OK' |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
239 |
res.headers[b'Content-Type'] = FRAMINGTYPE |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
240 |
res.setbodygen(meta['framegen']) |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
241 |
elif action == 'noop': |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
242 |
pass |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
243 |
else: |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
244 |
raise error.ProgrammingError('unhandled action from frame processor: %s' |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
245 |
% action) |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
246 |
|
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
247 |
def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor, |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
248 |
outstream, command, issubsequent): |
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
249 |
"""Dispatch a wire protocol command made from HTTPv2 requests. |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
250 |
|
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
251 |
The authenticated permission (``authedperm``) along with the original |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
252 |
command from the URL (``reqcommand``) are passed in. |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
253 |
""" |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
254 |
# We already validated that the session has permissions to perform the |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
255 |
# actions in ``authedperm``. In the unified frame protocol, the canonical |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
256 |
# command to run is expressed in a frame. However, the URL also requested |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
257 |
# to run a specific command. We need to be careful that the command we |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
258 |
# run doesn't have permissions requirements greater than what was granted |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
259 |
# by ``authedperm``. |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
260 |
# |
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
261 |
# Our rule for this is we only allow one command per HTTP request and |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
262 |
# that command must match the command in the URL. However, we make |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
263 |
# an exception for the ``multirequest`` URL. This URL is allowed to |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
264 |
# execute multiple commands. We double check permissions of each command |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
265 |
# as it is invoked to ensure there is no privilege escalation. |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
266 |
# TODO consider allowing multiple commands to regular command URLs |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
267 |
# iff each command is the same. |
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
268 |
|
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
269 |
proto = httpv2protocolhandler(req, ui, args=command['args']) |
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
270 |
|
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
271 |
if reqcommand == b'multirequest': |
37784
ee0d5e9d77b2
wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37783
diff
changeset
|
272 |
if not COMMANDS.commandavailable(command['command'], proto): |
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
273 |
# TODO proper error mechanism |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
274 |
res.status = b'200 OK' |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
275 |
res.headers[b'Content-Type'] = b'text/plain' |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
276 |
res.setbodybytes(_('wire protocol command not available: %s') % |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
277 |
command['command']) |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
278 |
return True |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
279 |
|
37129
aaabd709df72
wireproto: review fixups
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37120
diff
changeset
|
280 |
# TODO don't use assert here, since it may be elided by -O. |
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
281 |
assert authedperm in (b'ro', b'rw') |
37784
ee0d5e9d77b2
wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37783
diff
changeset
|
282 |
wirecommand = COMMANDS[command['command']] |
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
283 |
assert wirecommand.permission in ('push', 'pull') |
37054
e7a012b60d6e
wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37053
diff
changeset
|
284 |
|
37059
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
285 |
if authedperm == b'ro' and wirecommand.permission != 'pull': |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
286 |
# TODO proper error mechanism |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
287 |
res.status = b'403 Forbidden' |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
288 |
res.headers[b'Content-Type'] = b'text/plain' |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
289 |
res.setbodybytes(_('insufficient permissions to execute ' |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
290 |
'command: %s') % command['command']) |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
291 |
return True |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
292 |
|
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
293 |
# TODO should we also call checkperm() here? Maybe not if we're going |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
294 |
# to overhaul that API. The granted scope from the URL check should |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
295 |
# be good enough. |
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|
296 |
|
bbea991635d0
wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37057
diff
changeset
|