예제 #1
0
 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()
예제 #2
0
 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()
예제 #3
0
    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
예제 #4
0
    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