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
def start_request(self): """ Open the stream. Does this by encoding and sending the headers: no more calls to ``add_header`` are allowed after this method is called. The `end` flag controls whether this will be the end of the stream, or whether data will follow. """ # Strip any headers invalid in H2. #headers = h2_safe_headers(self.request_headers) host = self.connection.get_host(self.task.host) self.add_header(":Method", self.task.method) self.add_header(":Scheme", "https") self.add_header(":Authority", host) self.add_header(":Path", self.task.path) default_headers = (':method', ':scheme', ':authority', ':path') #headers = h2_safe_headers(self.task.headers) for name, value in self.task.headers.items(): is_default = to_native_string(name) in default_headers self.add_header(name, value, replace=is_default) # Encode the headers. encoded_headers = self._encoder(self.request_headers) # It's possible that there is a substantial amount of data here. The # data needs to go into one HEADERS frame, followed by a number of # CONTINUATION frames. For now, for ease of implementation, let's just # assume that's never going to happen (16kB of headers is lots!). # Additionally, since this is so unlikely, there's no point writing a # test for this: it's just so simple. if len(encoded_headers) > FRAME_MAX_LEN: # pragma: no cover raise ValueError("Header block too large.") header_frame = HeadersFrame(self.stream_id) header_frame.data = encoded_headers # If no data has been provided, this is the end of the stream. Either # way, due to the restriction above it's definitely the end of the # headers. header_frame.flags.add('END_HEADERS') # Send the header frame. self.task.set_state("start send header") self._send_cb(header_frame) # Transition the stream state appropriately. self.state = STATE_OPEN self.task.set_state("start send left body") self.send_left_body() self.task.set_state("end send left body") self.timeout_response()
def start_request(self): """ Open the stream. Does this by encoding and sending the headers: no more calls to ``add_header`` are allowed after this method is called. The `end` flag controls whether this will be the end of the stream, or whether data will follow. """ # Strip any headers invalid in H2. #headers = h2_safe_headers(self.request_headers) host = self.connection.get_host(self.task.host) self.add_header(":method", self.task.method) self.add_header(":scheme", "https") self.add_header(":authority", host) self.add_header(":path", self.task.path) default_headers = (':method', ':scheme', ':authority', ':path') #headers = h2_safe_headers(self.task.headers) for name, value in list(self.task.headers.items()): is_default = to_native_string(name) in default_headers self.add_header(name, value, replace=is_default) # Encode the headers. encoded_headers = self._encoder(self.request_headers) # It's possible that there is a substantial amount of data here. The # data needs to go into one HEADERS frame, followed by a number of # CONTINUATION frames. For now, for ease of implementation, let's just # assume that's never going to happen (16kB of headers is lots!). # Additionally, since this is so unlikely, there's no point writing a # test for this: it's just so simple. if len(encoded_headers) > FRAME_MAX_LEN: # pragma: no cover raise ValueError("Header block too large.") header_frame = HeadersFrame(self.stream_id) header_frame.data = encoded_headers # If no data has been provided, this is the end of the stream. Either # way, due to the restriction above it's definitely the end of the # headers. header_frame.flags.add('END_HEADERS') if self.request_body_left == 0: header_frame.flags.add('END_STREAM') # Send the header frame. self.task.set_state("start send header") self._send_cb(header_frame) # Transition the stream state appropriately. self.state = STATE_OPEN self.task.set_state("start send left body") if self.request_body_left > 0: self.send_left_body()