##// 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 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 strargs:
214 if not data:
178 if not data:
215 data = strargs
179 data = strargs
216 else:
180 elif isinstance(data, basestring):
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