Esempio n. 1
0
    def replace(self, key, value):
        """
        Replace existing header with new value. If header doesn't exist this
        method work like ``__setitem__``. Replacing leads to deletion of all
        existing headers with the same name.
        """
        key = to_bytestring(key)
        indices = []
        for (i, (k, v)) in enumerate(self._items):
            if _keys_equal(k, key):
                indices.append(i)

        # If the key isn't present, this is easy: just append and abort early.
        if not indices:
            self._items.append((key, value))
            return

        # Delete all but the first. I swear, this is the correct slicing
        # syntax!
        base_index = indices[0]
        for i in indices[:0:-1]:
            self._items.pop(i)

        del self._items[base_index]
        self._items.insert(base_index, (key, value))
Esempio n. 2
0
    def __init__(self,
                 ip,
                 stream_id,
                 host,
                 task,
                 send_cb,
                 close_cb,
                 header_encoder,
                 header_decoder,
                 receive_window_manager,
                 remote_window_size,
                 max_frame_size):

        self.ip = ip
        self.stream_id = stream_id
        self.host = host
        self.task = task
        self.state = STATE_IDLE

        # There are two flow control windows: one for data we're sending,
        # one for data being sent to us.
        self.receive_window_manager = receive_window_manager
        self.remote_window_size = remote_window_size
        self.max_frame_size = max_frame_size

        # This is the callback handed to the stream by its parent connection.
        # It is called when the stream wants to send data. It expects to
        # receive a list of frames that will be automatically serialized.
        self._send_cb = send_cb

        # This is the callback to be called when the stream is closed.
        self._close_cb = close_cb

        # A reference to the header encoder and decoder objects belonging to
        # the parent connection.
        self._encoder = header_encoder
        self._decoder = header_decoder

        self.request_headers = HTTPHeaderMap()

        # Convert the body to bytes if needed.
        self.request_body = to_bytestring(self.task.body)

        # request body not send blocked by send window
        # the left body will send when send window opened.
        self.request_body_left = len(self.request_body)

        # data list before decode
        self.response_header_datas = []

        # Set to a key-value set of the response headers once their
        # HEADERS..CONTINUATION frame sequence finishes.
        self.response_headers = None

        # Unconsumed response data chunks
        self.response_body = []
        self.response_body_len = 0

        self.start_request()
Esempio n. 3
0
    def __init__(self, ip, stream_id, host, task, send_cb, close_cb,
                 header_encoder, header_decoder, receive_window_manager,
                 remote_window_size, max_frame_size):

        self.ip = ip
        self.stream_id = stream_id
        self.host = host
        self.task = task
        self.state = STATE_IDLE

        # There are two flow control windows: one for data we're sending,
        # one for data being sent to us.
        self.receive_window_manager = receive_window_manager
        self.remote_window_size = remote_window_size
        self.max_frame_size = max_frame_size

        # This is the callback handed to the stream by its parent connection.
        # It is called when the stream wants to send data. It expects to
        # receive a list of frames that will be automatically serialized.
        self._send_cb = send_cb

        # This is the callback to be called when the stream is closed.
        self._close_cb = close_cb

        # A reference to the header encoder and decoder objects belonging to
        # the parent connection.
        self._encoder = header_encoder
        self._decoder = header_decoder

        self.request_headers = HTTPHeaderMap()

        # Convert the body to bytes if needed.
        self.request_body = to_bytestring(self.task.body)

        # request body not send blocked by send window
        # the left body will send when send window opened.
        self.request_body_left = len(self.request_body)

        # data list before decode
        self.response_header_datas = []

        # Set to a key-value set of the response headers once their
        # HEADERS..CONTINUATION frame sequence finishes.
        self.response_headers = None

        # Unconsumed response data chunks
        self.response_body = []
        self.response_body_len = 0

        self.start_request()
Esempio n. 4
0
    def test_ping(self, frame_buffer):
        def data_callback(chunk, **kwargs):
            frame_buffer.add_data(chunk)

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._send_cb = data_callback
        opaque = '00000000'
        c.ping(opaque)

        frames = list(frame_buffer)
        assert len(frames) == 1
        f = frames[0]
        assert isinstance(f, PingFrame)
        assert f.opaque_data == to_bytestring(opaque)
Esempio n. 5
0
    def test_ping(self, frame_buffer):
        def data_callback(chunk, **kwargs):
            frame_buffer.add_data(chunk)

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._send_cb = data_callback
        opaque = '00000000'
        c.ping(opaque)

        frames = list(frame_buffer)
        assert len(frames) == 1
        f = frames[0]
        assert isinstance(f, PingFrame)
        assert f.opaque_data == to_bytestring(opaque)
Esempio n. 6
0
    def __delitem__(self, key):
        """
        Sadly, __delitem__ is kind of stupid here, but the best we can do is
        delete all headers with a given key. To correctly achieve the 'KeyError
        on missing key' logic from dictionaries, we need to do this slowly.
        """
        key = to_bytestring(key)
        indices = []
        for (i, (k, v)) in enumerate(self._items):
            if _keys_equal(k, key):
                indices.append(i)

        if not indices:
            raise KeyError("Nonexistent header key: {}".format(key))

        for i in indices[::-1]:
            self._items.pop(i)
Esempio n. 7
0
    def __getitem__(self, key):
        """
        Unlike the dict __getitem__, this returns a list of items in the order
        they were added. These items are returned in 'canonical form', meaning
        that comma-separated values are split into multiple values.
        """
        key = to_bytestring(key)
        values = []

        for k, v in self._items:
            if _keys_equal(k, key):
                values.extend(x[1] for x in canonical_form(k, v))

        if not values:
            raise KeyError("Nonexistent header key: {}".format(key))

        return values
Esempio n. 8
0
    def __delitem__(self, key):
        """
        Sadly, __delitem__ is kind of stupid here, but the best we can do is
        delete all headers with a given key. To correctly achieve the 'KeyError
        on missing key' logic from dictionaries, we need to do this slowly.
        """
        key = to_bytestring(key)
        indices = []
        for (i, (k, v)) in enumerate(self._items):
            if _keys_equal(k, key):
                indices.append(i)

        if not indices:
            raise KeyError("Nonexistent header key: {}".format(key))

        for i in indices[::-1]:
            self._items.pop(i)
Esempio n. 9
0
    def __getitem__(self, key):
        """
        Unlike the dict __getitem__, this returns a list of items in the order
        they were added. These items are returned in 'canonical form', meaning
        that comma-separated values are split into multiple values.
        """
        key = to_bytestring(key)
        values = []

        for k, v in self._items:
            if _keys_equal(k, key):
                values.extend(x[1] for x in canonical_form(k, v))

        if not values:
            raise KeyError("Nonexistent header key: {}".format(key))

        return values
Esempio n. 10
0
    def request(self, method, url, body=None, headers=None):
        headers = headers or {}
        if const.HOST_HEADER in headers:
            headers[':authority'] = headers[const.HOST_HEADER]

        with self._write_lock:
            stream_id = self.putrequest(method, url)
            self._stream_id_context.stream_id = stream_id
            default_headers = (':method', ':scheme', ':authority', ':path')
            for name, value in headers.items():
                is_default = util.to_native_string(name) in default_headers
                if isinstance(value, list):
                    for item in value:
                        self.putheader(name,
                                       item,
                                       stream_id,
                                       replace=is_default)
                else:
                    self.putheader(name, value, stream_id, replace=is_default)

            final = True
            message_body = body
            if body is not None:
                if callable(body):
                    final = False
                    message_body = None
                else:
                    if isinstance(body, (unicode, bytes)):
                        message_body = util.to_bytestring(body)
                    if len(message_body) == 0:
                        message_body = None

            self.endheaders(message_body=message_body,
                            final=final,
                            stream_id=stream_id)
            if not final:
                body(self)

            return stream_id
Esempio n. 11
0
 def __contains__(self, key):
     """
     If any header is present with this key, returns True.
     """
     key = to_bytestring(key)
     return any(_keys_equal(key, k) for k, _ in self._items)
Esempio n. 12
0
 def __contains__(self, key):
     """
     If any header is present with this key, returns True.
     """
     key = to_bytestring(key)
     return any(_keys_equal(key, k) for k, _ in self._items)