def __call__(self, method, args): try: self._client.putrequest('POST', self._uri.path) for header in self._headers: self._client.putheader(*header) request = encode_object( Call(method, args, overload=self._overload, version=self.version)) self._client.putheader("Content-Length", str(len(request))) self._client.endheaders() self._client.send(six.binary_type(request)) response = self._client.getresponse() if response.status != 200: raise ProtocolError(self._uri.geturl(), response.status, response.reason) length = response.getheader('Content-Length', -1) if length == '0': raise ProtocolError(self._uri.geturl(), 'FATAL:', 'Server sent zero-length response') reply = self._parser.parse_stream( BufferedReader(response, buffer_size=self._buffer_size)) self._client.close() if isinstance(reply.value, Fault): raise self._error_factory(reply.value) else: return reply.value except: self._client.close() raise
def parse_stream(self, stream): self._result = None if hasattr(stream, 'read') and hasattr(stream.read, '__call__'): self._stream = stream else: raise TypeError( 'Stream parser can only handle objects supporting read()') while True: code = self._read(1) if not self._result: if code == b'H' and not self.version: if self._result: raise ParseError('Encountered duplicate type header') self.read_version() elif not self.version and code == b'c': self.read_version() self._result = Call(version=self.version) elif self.version == 2 and code == b'R': self._result = Reply(version=self.version) elif self.version == 2 and code == b'C': method_name = self.read_object() self._result = Call(method=method_name, version=self.version) elif not self._result and code == b'r': self.read_version() self._result = Reply(version=self.version) elif self.version == 2 and not self._result and code == b'F': self._result = Reply(value=self._adapter._read_fault(), version=self.version) break else: raise ParseError("Invalid Hessian message marker: %r" % (code, )) else: if self.version == 1 and code == b'H': key, value = self._read_keyval() self._result.headers[key] = value elif self.version == 1 and code == b'm': if not isinstance(self._result, Call): raise ParseError( 'Encountered illegal method name within reply') if self._result.method: raise ParseError( 'Encountered duplicate method name definition') self._result.method = self._read( unpack('>H', self._read(2))[0]) continue elif self.version == 1 and code == b'f': if not isinstance(self._result, Reply): raise ParseError( 'Encountered illegal fault within call') if self._result.value: raise ParseError( 'Encountered illegal extra object within reply') self._result.value = self._adapter._read_fault() break elif self.version == 1 and code == b'z': break else: if isinstance(self._result, Call): if self.version == 2: num_args = self.read_object(code) for i in range(0, num_args): self._result.args.append(self.read_object()) break else: self._result.args.append(self.read_object(code)) else: if self._result.value: raise ParseError( 'Encountered illegal extra object within reply' ) self._result.value = self.read_object(code) if self.version == 2: break # have to hit a 'z' to land here, TODO derefs? return self._result