##// END OF EJS Templates
httppeer: add support for httppostargs when we're sending a file...
Augie Fackler -
r33820:3c91cc0c default
parent child Browse files
Show More
@@ -75,6 +75,9 b' class webproto(wireproto.abstractserverp'
75 75 return args
76 76 def getfile(self, fp):
77 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 81 for s in util.filechunkiter(self.req, limit=length):
79 82 fp.write(s)
80 83 def redirect(self):
@@ -9,6 +9,7 b''
9 9 from __future__ import absolute_import
10 10
11 11 import errno
12 import io
12 13 import os
13 14 import socket
14 15 import struct
@@ -86,6 +87,45 b' def _wraphttpresponse(resp):'
86 87
87 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 129 class httppeer(wireproto.wirepeer):
90 130 def __init__(self, ui, path):
91 131 self._path = path
@@ -169,16 +209,18 b' class httppeer(wireproto.wirepeer):'
169 209 # with infinite recursion when trying to look up capabilities
170 210 # for the first time.
171 211 postargsok = self._caps is not None and 'httppostargs' in self._caps
172 # TODO: support for httppostargs when data is a file-like
173 # object rather than a basestring
174 canmungedata = not data or isinstance(data, basestring)
175 if postargsok and canmungedata:
212 if postargsok and args:
176 213 strargs = urlreq.urlencode(sorted(args.items()))
177 if strargs:
178 214 if not data:
179 215 data = strargs
180 elif isinstance(data, basestring):
181 data = strargs + data
216 else:
217 if isinstance(data, basestring):
218 i = io.BytesIO(data)
219 i.length = len(data)
220 data = i
221 argsio = io.BytesIO(strargs)
222 argsio.length = len(strargs)
223 data = _multifile(argsio, data)
182 224 headers['X-HgArgs-Post'] = len(strargs)
183 225 else:
184 226 if len(args) > 0:
General Comments 0
You need to be logged in to leave comments. Login now