def get_response(): try: return self._httpConnection.getresponse() except httplib.BadStatusLine as ex: self._log.warn("{}: invalid http response, error= {!r} ", msg, ex) raise except OSError as ex: if ex.errno in (10053, 10054): self._log.warn( "{}: could not receive response, OSError={!r}", msg, ex) else: self._log.warn( "{}: could not receive response, OSError={} ({!r})\n{}", msg, ex.errno, ex, traceback.format_exc()) raise httplib.NotConnected() except socket.error as ex: self._log.warn( "{}: could not receive response, socket error={!r}", msg, ex) raise httplib.NotConnected() except Exception as ex: self._log.warn( "{}: POST to netloc='{}' path='{}': could not receive response, error={!r}\n{}", msg, self._netloc, path, ex, traceback.format_exc()) raise httplib.NotConnected()
def reopen_http_connection(): self._log.info("{}: will close and reopen the connection and then try again", msg) self._httpConnection.close() try: self._httpConnection.connect() except Exception as ex: self._log.error("{}: could not reopen the connection, error={!r}\n{}\ncall-stack ={}", msg, ex, traceback.format_exc(), ''.join(traceback.format_stack())) self._httpConnection.close() raise httplib.NotConnected()
def send(self, value): """Send ``value`` to the server. ``value`` can be a string object, a file-like object that supports a .read() method, or an iterable object that supports a .next() method. """ # Based on python 2.6's httplib.HTTPConnection.send() if self.sock is None: if self.auto_open: self.connect() else: raise http_client.NotConnected() # send the data to the server. if we get a broken pipe, then close # the socket. we want to reconnect when somebody tries to send again. # # NOTE: we DO propagate the error, though, because we cannot simply # ignore the error... the caller will know if they can retry. if self.debuglevel > 0: print("send:", repr(value)) try: blocksize = 8192 if hasattr(value, 'read') : if hasattr(value, 'seek'): value.seek(0) if self.debuglevel > 0: print("sendIng a read()able") data = value.read(blocksize) while data: self.sock.sendall(data) data = value.read(blocksize) elif hasattr(value, 'next'): if hasattr(value, 'reset'): value.reset() if self.debuglevel > 0: print("sendIng an iterable") for data in value: self.sock.sendall(data) else: self.sock.sendall(value) except socket.error as v: if v[0] == 32: # Broken pipe self.close() raise
def _sendSoapRequest(self, path, xml, msg): """Send SOAP request using HTTP""" if not isinstance(xml, bytes): xml = xml.encode('utf-8') headers = { 'Content-type': 'application/soap+xml; charset=utf-8', 'user_agent': 'pysoap', 'Connection': 'keep-alive', } commlog.defaultLogger.logSoapReqOut(xml, 'POST') if self.supportedEncodings: headers['Accept-Encoding'] = ','.join(self.supportedEncodings) if self.requestEncodings: for compr in self.requestEncodings: if compr in self.supportedEncodings: xml = self.compressPayload(compr, xml) headers['Content-Encoding'] = compr xml = bytearray( xml ) # cast to bytes, required to bypass httplib checks for is str break headers['Content-Length'] = str(len(xml)) self._log.debug("{}:POST to netloc='{}' path='{}'", msg, self._netloc, path) # header = ', '.join(["%s: %s" % (k, v) for k, v in headers.items()]) if sys.version < '3': # Ensure http_method, location and all headers are binary to prevent # UnicodeError inside httplib.HTTPConnection._send_output. # httplib in python3 do the same inside itself, don't need to convert it here headers = dict((str(k), str(v)) for k, v in headers.items()) response = None content = None def send_request(): do_reopen = False success = False try: self._httpConnection.request('POST', path, body=xml, headers=headers) return True, do_reopen # success = True except httplib.CannotSendRequest as ex: # for whatever reason the response of the previous call was not read. read it and try again self._log.warn( "{}: could not send request, got httplib.CannotSendRequest Error. Will read response and retry", msg) tmp = self._httpConnection.getresponse() tmp.read() except OSError as ex: if ex.errno in (10053, 10054): self._log.warn("{}: could not send request, OSError={!r}", msg, ex) else: self._log.warn("{}: could not send request, OSError={}", msg, traceback.format_exc()) do_reopen = True except socket.error as ex: self._log.warn("{}: could not send request, socket error={!r}", msg, ex) do_reopen = True except Exception as ex: self._log.warn( "{}: POST to netloc='{}' path='{}': could not send request, error={!r}\n{}", msg, self._netloc, path, ex, traceback.format_exc()) return success, do_reopen def get_response(): try: return self._httpConnection.getresponse() except httplib.BadStatusLine as ex: self._log.warn("{}: invalid http response, error= {!r} ", msg, ex) raise except OSError as ex: if ex.errno in (10053, 10054): self._log.warn( "{}: could not receive response, OSError={!r}", msg, ex) else: self._log.warn( "{}: could not receive response, OSError={} ({!r})\n{}", msg, ex.errno, ex, traceback.format_exc()) raise httplib.NotConnected() except socket.error as ex: self._log.warn( "{}: could not receive response, socket error={!r}", msg, ex) raise httplib.NotConnected() except Exception as ex: self._log.warn( "{}: POST to netloc='{}' path='{}': could not receive response, error={!r}\n{}", msg, self._netloc, path, ex, traceback.format_exc()) raise httplib.NotConnected() def reopen_http_connection(): self._log.info( "{}: will close and reopen the connection and then try again", msg) self._httpConnection.close() try: self._httpConnection.connect() except Exception as ex: self._log.error( "{}: could not reopen the connection, error={!r}\n{}\ncall-stack ={}", msg, ex, traceback.format_exc(), ''.join(traceback.format_stack())) self._httpConnection.close() raise httplib.NotConnected() with self._lock: _retry_send = 2 # ugly construct that allows to retry sending the request once while _retry_send > 0: _retry_send -= 1 success, _do_reopen = send_request() if not success: if _do_reopen: reopen_http_connection() else: raise httplib.NotConnected() else: try: response = get_response() _retry_send = -1 # -1 == SUCCESS except httplib.NotConnected: self._log.info( "{}: will reopen after get_response error", msg) reopen_http_connection() if _retry_send != -1: raise httplib.NotConnected() content = HTTPReader.read_response_body(response) if response.status >= 300: self._log.error( "{}: POST to netloc='{}' path='{}': could not send request, HTTP response={}\ncontent='{}'", msg, self._netloc, path, response.status, content) soapfault = soapenvelope.ReceivedSoapFault.fromXMLString( content) raise HTTPReturnCodeError(response.status, content, soapfault) responseHeaders = {k.lower(): v for k, v in response.getheaders()} self._log.debug('{}: response:{}; content has {} Bytes ', msg, responseHeaders, len(content)) commlog.defaultLogger.logSoapRespIn(content, 'POST') return content