def __init__(self, data):
        req_line, headers = data.split('\r\n', 1)

        # HTTPMessage has no proper __repr__, so let's use the dictionary
        dict = HTTPMessage(StringIO(headers)).dict.copy()

        # all header names in the UPnP specs are uppercase
        self.headers = {k.upper(): v for k, v in dict.items()}

        method = req_line.split(' ')[0]

        self._notify = method == 'NOTIFY'

        # Unique Service Name => Unique Device Name + Type
        usn = self.headers.get('USN')
        self._udn, self._type = split_usn(usn) if usn else (None, None)
Beispiel #2
0
class MockHttpLibResponse(BytesIO):
  def __init__(self, data):
    BytesIO.__init__(self, data)
    self.status = 200
    self.version = 'HTTP/1.1'
    self.reason = 'OK'
    if PY2:
      self.msg = HTTPMessage(BytesIO('Content-Type: application/x-compressed\r\n'))
    else:
      self.msg = HTTPMessage()
      self.msg.add_header('Content-Type', 'application/x-compressed')

  def getheaders(self):
    return list(self.msg.items())

  def isclosed(self):
    return self.closed
Beispiel #3
0
class MockHttpLibResponse(BytesIO):
  def __init__(self, data):
    BytesIO.__init__(self, data)
    self.status = 200
    self.version = 'HTTP/1.1'
    self.reason = 'OK'
    if PY2:
      self.msg = HTTPMessage(BytesIO(b'Content-Type: application/x-compressed\r\n'))
    else:
      self.msg = HTTPMessage()
      self.msg.add_header('Content-Type', 'application/x-compressed')

  def getheaders(self):
    return list(self.msg.items())

  def isclosed(self):
    return self.closed
Beispiel #4
0
class ReplayHTTPResponse(object):
    """
    A replay response object, with just enough functionality to make
    the various HTTP/URL libraries out there happy.
    """
    __text_content_types = (
        'text/',
        'application/json',
    )

    def __init__(self, replay_response, method=None):
        self.reason = replay_response['status']['message']
        self.status = replay_response['status']['code']
        self.version = None

        if 'body_text' in replay_response:
            # JSON decoder returns unicode, not str, so this needs to be
            # encoded to properly reproduce content off the wire.
            self._content = replay_response['body_text'].encode('utf8')
        elif 'body_quoted_printable' in replay_response:
            # quopri.decodestring returns str, which is correct for content off
            # the wire.
            self._content = quopri.decodestring(replay_response['body_quoted_printable'])
        else:
            # .decode('base64') returns str, which is correct for content off
            # the wire.
            self._content = replay_response['body'].decode('base64')
        self.fp = StringIO(self._content)

        msg_fp = StringIO('\r\n'.join('{}: {}'.format(h, v)
            for h, v in replay_response['headers'].iteritems()))
        self.msg = HTTPMessage(msg_fp)
        self.msg.fp = None  # httplib does this, okay?

        length = self.msg.getheader('content-length')
        self.length = int(length) if length else None

        # Save method to handle HEAD specially as httplib does
        self._method = method

    @classmethod
    def make_replay_response(cls, response):
        """
        Converts real response to replay_response dict which can be saved
        and/or used to initialize a ReplayHTTPResponse.
        """
        replay_response = {}
        body = response.read()  # undecoded byte string

        # Add body to replay_response. Try to use simple text, falling back to
        # quoted printable or base64 as required for binary responses.
        if response.getheader('content-type', '') \
                .startswith(cls.__text_content_types):

            if response.getheader('content-encoding') in ['gzip', 'deflate']:
                # http://stackoverflow.com/questions/2695152
                body = zlib.decompress(body, 16 + zlib.MAX_WBITS)
                del response.msg['content-encoding']
                # decompression changes the length
                if 'content-length' in response.msg:
                    response.msg['content-length'] = str(len(body))

            try:
                # Store body directly as text if it will decode properly.
                body.decode('utf8')
                replay_response['body_text'] = body
            except UnicodeDecodeError:
                # Store body as quoted printable.
                # Remove unneccessary =\n pairs which make searching hard.
                # These exist for line-wrapping in email, which is entirely
                # pointless here.
                body_quoted_printable = quopri.encodestring(body)
                body_quoted_printable = body_quoted_printable.replace('=\n', '')
                replay_response['body_quoted_printable'] = body_quoted_printable

        else:
            replay_response['body'] = body.encode('base64')

        replay_response.update(dict(
            status=dict(code=response.status, message=response.reason),
            headers=dict(response.getheaders())))
        return replay_response

    def close(self):
        self.fp = None

    def isclosed(self):
        return self.fp is None

    def read(self, amt=None):
        """
        The important parts of HTTPResponse.read()
        """
        if self.fp is None:
            return ''

        if self._method == 'HEAD':
            self.close()
            return ''

        if self.length is not None:
            amt = min(amt, self.length)

        # StringIO doesn't like read(None)
        s = self.fp.read() if amt is None else self.fp.read(amt)
        if not s:
            self.close()

        if self.length is not None:
            self.length -= len(s)
            if not self.length:
                self.close()

        return s

    def getheader(self, name, default=None):
        return self.msg.getheader(name, default)

    def getheaders(self):
        return self.msg.items()
Beispiel #5
0
class ReplayHTTPResponse(object):
    """
    A replay response object, with just enough functionality to make
    the various HTTP/URL libraries out there happy.
    """
    __text_content_types = (
        'text/',
        'application/json',
    )

    def __init__(self, replay_response, method=None):
        self.reason = replay_response['status']['message']
        self.status = replay_response['status']['code']
        self.version = None
        if 'body_quoted_printable' in replay_response:
            self._content = quopri.decodestring(replay_response['body_quoted_printable'])
        else:
            self._content = replay_response['body'].decode('base64')
        self.fp = StringIO(self._content)

        msg_fp = StringIO('\r\n'.join('{}: {}'.format(h, v)
            for h, v in replay_response['headers'].iteritems()))
        self.msg = HTTPMessage(msg_fp)
        self.msg.fp = None  # httplib does this, okay?

        length = self.msg.getheader('content-length')
        self.length = int(length) if length else None

        # Save method to handle HEAD specially as httplib does
        self._method = method

    @classmethod
    def make_replay_response(cls, response):
        """
        Converts real response to replay_response dict which can be saved
        and/or used to initialize a ReplayHTTPResponse.
        """
        replay_response = {}
        body = response.read()  # undecoded byte string

        # Add body to replay_response, either as quoted printable for
        # text responses or base64 for binary responses.
        if response.getheader('content-type', '') \
                .startswith(cls.__text_content_types):
            if response.getheader('content-encoding') in ['gzip', 'deflate']:
                # http://stackoverflow.com/questions/2695152
                body = zlib.decompress(body, 16 + zlib.MAX_WBITS)
                del response.msg['content-encoding']
                # decompression changes the length
                if 'content-length' in response.msg:
                    response.msg['content-length'] = str(len(body))
            replay_response['body_quoted_printable'] = quopri.encodestring(body)
        else:
            replay_response['body'] = body.encode('base64')

        replay_response.update(dict(
            status=dict(code=response.status, message=response.reason),
            headers=dict(response.getheaders())))
        return replay_response

    def close(self):
        self.fp = None

    def isclosed(self):
        return self.fp is None

    def read(self, amt=None):
        """
        The important parts of HTTPResponse.read()
        """
        if self.fp is None:
            return ''

        if self._method == 'HEAD':
            self.close()
            return ''

        if self.length is not None:
            amt = min(amt, self.length)

        # StringIO doesn't like read(None)
        s = self.fp.read() if amt is None else self.fp.read(amt)
        if not s:
            self.close()

        if self.length is not None:
            self.length -= len(s)
            if not self.length:
                self.close()

        return s

    def getheader(self, name, default=None):
        return self.msg.getheader(name, default)

    def getheaders(self):
        return self.msg.items()
Beispiel #6
0
class ReplayHTTPResponse(object):
    """
    A replay response object, with just enough functionality to make
    the various HTTP/URL libraries out there happy.
    """
    __text_content_types = (
        'text/',
        'application/json',
    )

    def __init__(self, replay_response, method=None):
        self.reason = replay_response['status']['message']
        self.status = replay_response['status']['code']
        self.version = None
        if 'body_quoted_printable' in replay_response:
            self._content = quopri.decodestring(
                replay_response['body_quoted_printable'])
        else:
            self._content = replay_response['body'].decode('base64')
        self.fp = StringIO(self._content)

        msg_fp = StringIO('\r\n'.join(
            '{}: {}'.format(h, v)
            for h, v in replay_response['headers'].iteritems()))
        self.msg = HTTPMessage(msg_fp)
        self.msg.fp = None  # httplib does this, okay?

        length = self.msg.getheader('content-length')
        self.length = int(length) if length else None

        # Save method to handle HEAD specially as httplib does
        self._method = method

    @classmethod
    def make_replay_response(cls, response):
        """
        Converts real response to replay_response dict which can be saved
        and/or used to initialize a ReplayHTTPResponse.
        """
        replay_response = {}
        body = response.read()  # undecoded byte string

        # Add body to replay_response, either as quoted printable for
        # text responses or base64 for binary responses.
        if response.getheader('content-type', '') \
                .startswith(cls.__text_content_types):
            if response.getheader('content-encoding') in ['gzip', 'deflate']:
                # http://stackoverflow.com/questions/2695152
                body = zlib.decompress(body, 16 + zlib.MAX_WBITS)
                del response.msg['content-encoding']
                # decompression changes the length
                if 'content-length' in response.msg:
                    response.msg['content-length'] = str(len(body))
            replay_response['body_quoted_printable'] = quopri.encodestring(
                body)
        else:
            replay_response['body'] = body.encode('base64')

        replay_response.update(
            dict(status=dict(code=response.status, message=response.reason),
                 headers=dict(response.getheaders())))
        return replay_response

    def close(self):
        self.fp = None

    def isclosed(self):
        return self.fp is None

    def read(self, amt=None):
        """
        The important parts of HTTPResponse.read()
        """
        if self.fp is None:
            return ''

        if self._method == 'HEAD':
            self.close()
            return ''

        if self.length is not None:
            amt = min(amt, self.length)

        # StringIO doesn't like read(None)
        s = self.fp.read() if amt is None else self.fp.read(amt)
        if not s:
            self.close()

        if self.length is not None:
            self.length -= len(s)
            if not self.length:
                self.close()

        return s

    def getheader(self, name, default=None):
        return self.msg.getheader(name, default)

    def getheaders(self):
        return self.msg.items()