Show More
@@ -75,6 +75,9 b' class webproto(wireproto.abstractserverp' | |||||
75 | return args |
|
75 | return args | |
76 | def getfile(self, fp): |
|
76 | def getfile(self, fp): | |
77 | length = int(self.req.env['CONTENT_LENGTH']) |
|
77 | length = int(self.req.env['CONTENT_LENGTH']) | |
|
78 | # If httppostargs is used, we need to read Content-Length | |||
|
79 | # minus the amount that was consumed by args. | |||
|
80 | length -= int(self.req.env.get('HTTP_X_HGARGS_POST', 0)) | |||
78 | for s in util.filechunkiter(self.req, limit=length): |
|
81 | for s in util.filechunkiter(self.req, limit=length): | |
79 | fp.write(s) |
|
82 | fp.write(s) | |
80 | def redirect(self): |
|
83 | def redirect(self): |
@@ -9,6 +9,7 b'' | |||||
9 | from __future__ import absolute_import |
|
9 | from __future__ import absolute_import | |
10 |
|
10 | |||
11 | import errno |
|
11 | import errno | |
|
12 | import io | |||
12 | import os |
|
13 | import os | |
13 | import socket |
|
14 | import socket | |
14 | import struct |
|
15 | import struct | |
@@ -86,6 +87,45 b' def _wraphttpresponse(resp):' | |||||
86 |
|
87 | |||
87 | resp.__class__ = readerproxy |
|
88 | resp.__class__ = readerproxy | |
88 |
|
89 | |||
|
90 | class _multifile(object): | |||
|
91 | def __init__(self, *fileobjs): | |||
|
92 | for f in fileobjs: | |||
|
93 | if not util.safehasattr(f, 'length'): | |||
|
94 | raise ValueError( | |||
|
95 | '_multifile only supports file objects that ' | |||
|
96 | 'have a length but this one does not:', type(f), f) | |||
|
97 | self._fileobjs = fileobjs | |||
|
98 | self._index = 0 | |||
|
99 | ||||
|
100 | @property | |||
|
101 | def length(self): | |||
|
102 | return sum(f.length for f in self._fileobjs) | |||
|
103 | ||||
|
104 | def read(self, amt=None): | |||
|
105 | if amt <= 0: | |||
|
106 | return ''.join(f.read() for f in self._fileobjs) | |||
|
107 | parts = [] | |||
|
108 | while amt and self._index < len(self._fileobjs): | |||
|
109 | parts.append(self._fileobjs[self._index].read(amt)) | |||
|
110 | got = len(parts[-1]) | |||
|
111 | if got < amt: | |||
|
112 | self._index += 1 | |||
|
113 | amt -= got | |||
|
114 | return ''.join(parts) | |||
|
115 | ||||
|
116 | def seek(self, offset, whence=os.SEEK_SET): | |||
|
117 | if whence != os.SEEK_SET: | |||
|
118 | raise NotImplementedError( | |||
|
119 | '_multifile does not support anything other' | |||
|
120 | ' than os.SEEK_SET for whence on seek()') | |||
|
121 | if offset != 0: | |||
|
122 | raise NotImplementedError( | |||
|
123 | '_multifile only supports seeking to start, but that ' | |||
|
124 | 'could be fixed if you need it') | |||
|
125 | for f in self._fileobjs: | |||
|
126 | f.seek(0) | |||
|
127 | self._index = 0 | |||
|
128 | ||||
89 | class httppeer(wireproto.wirepeer): |
|
129 | class httppeer(wireproto.wirepeer): | |
90 | def __init__(self, ui, path): |
|
130 | def __init__(self, ui, path): | |
91 | self._path = path |
|
131 | self._path = path | |
@@ -169,17 +209,19 b' class httppeer(wireproto.wirepeer):' | |||||
169 | # with infinite recursion when trying to look up capabilities |
|
209 | # with infinite recursion when trying to look up capabilities | |
170 | # for the first time. |
|
210 | # for the first time. | |
171 | postargsok = self._caps is not None and 'httppostargs' in self._caps |
|
211 | postargsok = self._caps is not None and 'httppostargs' in self._caps | |
172 | # TODO: support for httppostargs when data is a file-like |
|
212 | if postargsok and args: | |
173 | # object rather than a basestring |
|
|||
174 | canmungedata = not data or isinstance(data, basestring) |
|
|||
175 | if postargsok and canmungedata: |
|
|||
176 | strargs = urlreq.urlencode(sorted(args.items())) |
|
213 | strargs = urlreq.urlencode(sorted(args.items())) | |
177 |
if |
|
214 | if not data: | |
178 |
|
|
215 | data = strargs | |
179 | data = strargs |
|
216 | else: | |
180 |
|
|
217 | if isinstance(data, basestring): | |
181 | data = strargs + data |
|
218 | i = io.BytesIO(data) | |
182 | headers['X-HgArgs-Post'] = len(strargs) |
|
219 | i.length = len(data) | |
|
220 | data = i | |||
|
221 | argsio = io.BytesIO(strargs) | |||
|
222 | argsio.length = len(strargs) | |||
|
223 | data = _multifile(argsio, data) | |||
|
224 | headers['X-HgArgs-Post'] = len(strargs) | |||
183 | else: |
|
225 | else: | |
184 | if len(args) > 0: |
|
226 | if len(args) > 0: | |
185 | httpheader = self.capable('httpheader') |
|
227 | httpheader = self.capable('httpheader') |
General Comments 0
You need to be logged in to leave comments.
Login now