Exemplo n.º 1
0
    def get_response(self):
        try:
            self.response = self.conn.getresponse()
        except httplib.BadStatusLine:
            self.conn.close()
            raise
        self.response_etag = self.response.getheader('etag')

        log.debug("RESPONSE STATUS: %d" % self.response.status)
        # Redirect redirect to auth required for cli
        if self.response.status == 307:
            self.response.status = 401

        # Ensure we have the correct content-type
        content_type = self.response.getheader('content-type')
        length = self.response.getheader('content-length')
        expected_type = self.response_content_type if self._success() else \
            self.ERROR_RESPONSE_CONTENT_TYPE
        if length != "0" and content_type != expected_type:
            self.conn.close()
            raise APIException("Unexpected content-type of %s for length %s" %
                               (content_type, length))

        try:
            if self.response_file is None or not self._success():
                self._response_data = self.response.read()
            else:
                stream_writer(self.response, self.response_file)
        except:
            self.conn.close()
            raise

        # Close connection here if the server can't handle connection reuse
        if self.conninfo.must_close():
            self.conn.close()

        if not self._success():
            log.debug("Server replied: %d %s" %
                      (self._status(), self._reason()))

        if self._response_data and length != "0":
            try:
                self.response_obj = json.loads(self._response_data)
            except ValueError as e:
                if self._response_data:
                    raise APIException("Error loading data: %s" % str(e))
            else:
                log.debug("RESPONSE:")
                log.debug(self.response.msg)
                if self.response_obj is not None:
                    log.debug(self.response_obj)

        if not self._success():
            raise RequestError(self._status(), self._reason(),
                               self.response_obj)
Exemplo n.º 2
0
    def get_response(self):
        self.response = self.conn.getresponse()
        self.response_etag = self.response.getheader('etag')

        log.debug("RESPONSE STATUS: %d" % self.response.status)
        # Redirect redirect to auth required for cli
        if self.response.status == 307:
            log.debug("Server replied: %d %s, translating to 401" %
                      (self._status(), self._reason()))
            self.response.status = 401

        # Ensure we have the correct content-type
        content_type = self.response.getheader('content-type')
        length = self.response.getheader('content-length')
        log.debug("RESPONSE LENGTH = %s" % length)
        expected_type = self.response_content_type if self._success() else \
            self.ERROR_RESPONSE_CONTENT_TYPE
        if length != "0" and content_type != expected_type:
            log.debug("Unexpected content-type of %s for length %s" %
                      (content_type, length))
            if content_type in (CONTENT_TYPE_JSON, None):
                log.debug(self.response.getheaders())
                log.debug(self.response.read())
            self.conn.close()
            raise APIException("Unexpected content-type of %s for length %s" %
                               (content_type, length))

        if self.response_file is None or not self._success():
            self._response_data = self.response.read()
        else:
            stream_writer(self.response, self.response_file)

        self.conn.close()

        if not self._success():
            log.debug("Server replied: %d %s" %
                      (self._status(), self._reason()))

        if self._response_data and length != "0":
            try:
                self.response_obj = json.loads(self._response_data)
            except ValueError, e:
                if self._response_data:
                    raise APIException("Error loading data: %s" % str(e))
            else:
                log.debug("RESPONSE:")
                log.debug(self.response.msg)
                if self.response_obj is not None:
                    log.debug("\n" + pretty_json(self.response_obj))
                else:
                    log.debug("<no response body>")
Exemplo n.º 3
0
    def send_request(self):
        self._headers["Content-Type"] = self.request_content_type

        if self.chunked:
            self._headers['Transfer-Encoding'] = "chunked"
        else:
            self._headers['Content-Length'] = self.body_length

        if self.credentials:
            request_info = {
                'scheme': self.conninfo.scheme,
                'host': self.conninfo.host,
                'port': str(self.conninfo.port),
                'method': self.method,
                'uri': self.uri,
                'content_length': self.body_length,
                'body': self._body_text(),
                'content_type': self.request_content_type,
            }
            self._headers['Authorization'] = \
                self.credentials.auth_header(**request_info)

        log.debug("REQUEST: {method} {scheme}://{host}:{port}{uri}".format(
            method=self.method,
            scheme=self.conninfo.scheme,
            host=self.conninfo.host,
            port=self.conninfo.port,
            uri=self.uri))

        log.debug("REQUEST HEADERS:")
        for header in self._headers:
            log.debug("    %s: %s" % (header, self._headers[header]))

        if (self.body_length > 0):
            log.debug("REQUEST BODY:")
            if (self.request_content_type == CONTENT_TYPE_BINARY):
                log.debug("\tContent elided. File info: %s (%d bytes)" %
                          (self.body_file, self.body_length))
            else:
                log.debug(pretty_json(self._body_text(False)))
                self.body_file.seek(0)

        # Wrap any random errors in a HttpException to make them more palatable.
        try:
            if self.conn.sock is None:
                self.conn.connect()
        except ssl.SSLError as e:
            # If we see the SSL error "EOF occurred in violation of protocol",
            # we want to add more information, to help with better diagnosis.
            # See QFS-5396.
            if e.errno == ssl.SSL_ERROR_EOF:
                e.strerror = "{} - check server logs for cause (e.g. qfsd)"\
                    .format(e.strerror)

            # Re-raise, preserving the stack
            raise e, None, sys.exc_info()[2]
        except (httplib.HTTPException, socket.error):
            # Already an HTTPException, so just raise it and socket errors are
            # cool too.
            raise
        except Exception as e:
            # Wrap it, but save the type, message, and stack.
            message = os.strerror(e.errno) if hasattr(e,
                                                      'errno') else e.message
            wrap = httplib.HTTPException("{}: {}".format(
                sys.exc_info()[0], message))
            raise wrap, None, sys.exc_info()[2]

        try:
            self.conn.putrequest(self.method, self.uri)

            for name, value in self._headers.items():
                self.conn.putheader(name, value)

            self.conn.endheaders()

            # Chunked transfer encoding. Details:
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
            # On our server side chunks are processed by chunked_xfer_istream.h
            if self.chunked:
                if self.body_file is not None:
                    chunk = self.body_file.read(self.chunk_size)
                    while (len(chunk) > 0):
                        self.conn.send("%x\r\n%s\r\n" % (len(chunk), chunk))
                        log.debug("Sent chunk (%u bytes)" % len(chunk))
                        chunk = self.body_file.read(self.chunk_size)
                self.conn.send("0\r\n\r\n")
                log.debug("Sent final chunk")
            elif self.body_file is not None:
                self.conn.send(self.body_file)

        except socket.error as e:
            # Allow EPIPE, server probably sent us a response before breaking
            if e.errno != errno.EPIPE:
                raise
Exemplo n.º 4
0
    def send_request(self):
        self._headers["Content-Type"] = self.request_content_type
        if self.conninfo.must_close():
            self._headers["Connection"] = "close"

        # cf request.c: our http server actually returns an error
        # if we send an empty body for, for example, GET. Various
        # tests will set "chunked" on a connection and request
        # inherits that. Avoid sending empty bodies.
        if self.chunked and self._needs_body():
            self._headers['Transfer-Encoding'] = "chunked"
        else:
            self._headers['Content-Length'] = self.body_length

        if self.credentials:
            self._headers['Authorization'] = self.credentials.auth_header()

        log.debug("REQUEST: {method} {scheme}://{host}:{port}{uri}".format(
            method=self.method,
            scheme=self.conninfo.scheme,
            host=self.conninfo.host,
            port=self.conninfo.port,
            uri=self.uri))

        log.debug("REQUEST HEADERS:")
        for header in self._headers:
            log.debug("    %s: %s" % (header, self._headers[header]))

        if (self.body_length > 0):
            log.debug("REQUEST BODY:")
            if (self.request_content_type == CONTENT_TYPE_BINARY):
                log.debug("\tContent elided. File info: %s (%d bytes)" %
                          (self.body_file, self.body_length))
            else:
                log.debug(self._body_text(False))
                self.body_file.seek(0)

        # Wrap any random errors in a HttpException to make them more palatable.
        try:
            if self.conn.sock is None:
                self.conninfo.maybe_probe_reuse_flag()
                self.conn.connect()
        except (httplib.HTTPException, socket.error):
            # Already an HTTPException, so just raise it and socket errors are
            # cool too.
            raise
        except Exception as e:
            # Wrap it, but save the type, message, and stack.
            message = os.strerror(e.errno) if hasattr(e, 'errno') else str(e)
            wrap = httplib.HTTPException("{}: {}".format(
                sys.exc_info()[0], message))
            raise wrap, None, sys.exc_info()[2]

        try:
            self.conn.putrequest(self.method, self.uri)

            for name, value in self._headers.items():
                self.conn.putheader(name, value)

            self.conn.endheaders()

            # Chunked transfer encoding. Details:
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
            # On our server side chunks are processed by chunked_xfer_istream.h
            if self.chunked and self._needs_body():
                if self.body_file is not None:
                    chunk = self.body_file.read(self.chunk_size)
                    while (len(chunk) > 0):
                        self.conn.send("%x\r\n%s\r\n" % (len(chunk), chunk))
                        chunk = self.body_file.read(self.chunk_size)
                self.conn.send("0\r\n\r\n")
            elif self.body_file is not None:
                self.conn.send(self.body_file)

        except socket.error as e:
            # Allow EPIPE, server probably sent us a response before breaking
            if e.errno != errno.EPIPE:
                raise
Exemplo n.º 5
0
    def get_response(self):
        self.response = self.conn.getresponse()
        self.response_etag = self.response.getheader('etag')

        log.debug("RESPONSE STATUS: %d" % self.response.status)
        # Redirect redirect to auth required for cli
        if self.response.status == 307:
            log.debug("Server replied: %d %s, translating to 401" % (
                    self._status(), self._reason()))
            self.response.status = 401

        # Ensure we have the correct content-type
        content_type = self.response.getheader('content-type')
        length = self.response.getheader('content-length')
        log.debug("RESPONSE LENGTH = %s" % length)
        expected_type = self.response_content_type if self._success() else \
            self.ERROR_RESPONSE_CONTENT_TYPE
        if length != "0" and content_type != expected_type:
            log.debug("Unexpected content-type of %s for length %s" %
                (content_type, length))
            if content_type in (CONTENT_TYPE_JSON, None):
                log.debug(self.response.getheaders())
                log.debug(self.response.read())
            self.conn.close()
            raise APIException("Unexpected content-type of %s for length %s" %
                (content_type, length))

        if self.response_file is None or not self._success():
            self._response_data = self.response.read()
        else:
            stream_writer(self.response, self.response_file)

        self.conn.close()

        if not self._success():
            log.debug("Server replied: %d %s" % (self._status(),
                self._reason()))

        if self._response_data and length != "0":
            try:
                self.response_obj = json.loads(self._response_data)
            except ValueError, e:
                if self._response_data:
                    raise APIException("Error loading data: %s" % str(e))
            else:
                log.debug("RESPONSE:")
                log.debug(self.response.msg)
                if self.response_obj is not None:
                    log.debug("\n" + pretty_json(self.response_obj))
                else:
                    log.debug("<no response body>")
Exemplo n.º 6
0
    def send_request(self):
        self._headers["Content-Type"] = self.request_content_type

        if self.chunked:
            self._headers['Transfer-Encoding'] = "chunked"
        else:
            self._headers['Content-Length'] = self.body_length

        if self.credentials:
            request_info = {
                'scheme' : self.conninfo.scheme,
                'host' : self.conninfo.host,
                'port' : str(self.conninfo.port),
                'method' : self.method,
                'uri' : self.uri,
                'content_length': self.body_length,
                'body' : self._body_text(),
                'content_type' : self.request_content_type,
            }
            self._headers['Authorization'] = \
                self.credentials.auth_header(**request_info)

        log.debug("REQUEST: {method} {scheme}://{host}:{port}{uri}".format(
            method=self.method, scheme=self.conninfo.scheme,
            host=self.conninfo.host, port=self.conninfo.port,
            uri=self.uri))

        log.debug("REQUEST HEADERS:")
        for header in self._headers:
            log.debug("    %s: %s" % (header, self._headers[header]))

        if (self.body_length > 0):
            log.debug("REQUEST BODY:")
            if (self.request_content_type == CONTENT_TYPE_BINARY):
                log.debug(
                    "\tContent elided. File info: %s (%d bytes)" %
                    (self.body_file, self.body_length))
            else:
                log.debug(pretty_json(self._body_text(False)))
                self.body_file.seek(0)

        # Wrap any random errors in a HttpException to make them more palatable.
        try:
            if self.conn.sock is None:
                self.conn.connect()
        except ssl.SSLError as e:
            # If we see the SSL error "EOF occurred in violation of protocol",
            # we want to add more information, to help with better diagnosis.
            # See QFS-5396.
            if e.errno == ssl.SSL_ERROR_EOF:
                e.strerror = "{} - check server logs for cause (e.g. qfsd)"\
                    .format(e.strerror)

            # Re-raise, preserving the stack
            raise e, None, sys.exc_info()[2]
        except (httplib.HTTPException, socket.error):
            # Already an HTTPException, so just raise it and socket errors are
            # cool too.
            raise
        except Exception as e:
            # Wrap it, but save the type, message, and stack.
            message = os.strerror(e.errno) if hasattr(e, 'errno') else e.message
            wrap = httplib.HTTPException("{}: {}".format(sys.exc_info()[0],
                                                         message))
            raise wrap, None, sys.exc_info()[2]

        try:
            self.conn.putrequest(self.method, self.uri)

            for name, value in self._headers.items():
                self.conn.putheader(name, value)

            self.conn.endheaders()

            # Chunked transfer encoding. Details:
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
            # On our server side chunks are processed by chunked_xfer_istream.h
            if self.chunked:
                if self.body_file is not None:
                    chunk = self.body_file.read(self.chunk_size)
                    while (len(chunk) > 0):
                        self.conn.send("%x\r\n%s\r\n" % (len(chunk), chunk))
                        log.debug("Sent chunk (%u bytes)" % len(chunk))
                        chunk = self.body_file.read(self.chunk_size)
                self.conn.send("0\r\n\r\n")
                log.debug("Sent final chunk")
            elif self.body_file is not None:
                self.conn.send(self.body_file)

        except socket.error as e:
            # Allow EPIPE, server probably sent us a response before breaking
            if e.errno != errno.EPIPE:
                raise