def get(event_generator): request = next(event_generator, None) if not isinstance(request, h11.Request): return token = dict(request.headers).get(b"authorization") if token is None or token.decode("utf-8") != _token: yield h11.Response( status_code=403, headers=[], ) return cursor = database.connection.cursor() giveaway_view = next(cursor.execute(model.get_current_giveaway), None) if False and giveaway_view is None: yield h11.Response( status_code=404, headers=[], ) else: #giveaway_id, _ = giveaway_view from uuid import UUID obj = presenter.registrations( UUID("15718946-d2d9-47b5-bbf4-7878266349d3").bytes) yield h11.Response(status_code=200, headers=[ ("content-type", "application/json"), ]) yield h11.Data(data=json.dumps(obj).encode("utf-8"))
def post(event_generator): request = next(event_generator, None) if not isinstance(request, h11.Request): return data = next(event_generator, None) if not isinstance(data, h11.Data): yield h11.Response( status_code=400, headers=[], ) return # these forms should be *way* under 32k eom = next(event_generator, None) if not isinstance(eom, h11.EndOfMessage): yield h11.Response( status_code=400, headers=[], ) return qsl = parse.parse_qsl(data.data.decode('utf-8')) fields = list(schema.validate(qsl)) invalid_fields = list( starfilter(lambda _a, _b, explain: explain is not None, fields)) if invalid_fields: yield from presenter.form({k: (v, e) for k, v, e in fields}) else: status = presenter.insert_registration({k: v for k, v, _ in fields}) yield from presenter.status(status)
def _send_fatal_error(self, exc): status_code = getattr(exc, 'error_status_hint', 500) self._logger.debug('sending error response, status %d', status_code) try: self.send_event( h11.Response( status_code=status_code, reason=turq.util.http.default_reason(status_code).encode(), headers=[ (b'Date', turq.util.http.date().encode()), (b'Content-Type', b'text/plain'), (b'Connection', b'close'), ], )) self.send_event(h11.Data(data=('Error: %s\r\n' % exc).encode())) self.send_event(h11.EndOfMessage()) except Exception as e: self._logger.debug('cannot send error response: %s', e) # A crude way to avoid the TCP reset problem (RFC 7230 Section 6.6). try: self._socket.shutdown(socket.SHUT_WR) while self._socket.recv(1024): self._logger.debug('discarding data from client') except OSError: # The client may have already closed the connection pass
async def handle_client_http(self, stream, event, conn): # TODO: right now we handle a single request then close the connection # hence HTTP 1.1 keep-alive is not supported req = HTTPRequest.from_h11_req(event) rep = await self.http.handle_request(req) if self.config.debug: server_header = f"guardata/{guardata_version} {h11.PRODUCT_ID}" else: server_header = "guardata" rep.headers.append(("server", server_header)) # Tell no support for keep-alive (h11 will know what to do from there) rep.headers.append(("connection", "close")) try: response_data = bytearray( conn.send( h11.Response( status_code=rep.status_code, headers=rep.headers, reason=rep.reason ) ) ) if rep.data: response_data += conn.send(h11.Data(data=rep.data)) response_data += conn.send(h11.EndOfMessage()) await stream.send_all(response_data) except trio.BrokenResourceError: # Peer is already gone, nothing to do pass
async def send_headers(self, status, headers): if self._headers_sent: raise RuntimeError("Headers already sent") response = h11.Response(status_code=status, headers=headers) print(type(self._request)) await self.conn.send(response) self._headers_sent = True
async def respond_to_h11(self, h11_conn, event): """ Most generic response to an h11 connection possible. """ stream = H11Stream(h11_conn, event, (None, None)) print("stream:", stream) handler = self.router.match(stream) print("handler:", handler) print("htype:", type(handler)) handler_result = await handler(stream) if handler_result is not None: status, response = handler_result else: status, response = None, None print("response:", response) if not stream._headers_sent: content_type, response = response_to_bytes(handler, response) content_length = str(len(response)) headers = h11_conn.basic_headers() headers.append(('Content-Type', content_type)) headers.append(('Content-Length', content_length)) resp = h11.Response(status_code=status, headers=headers) await h11_conn.send(resp) if response: await h11_conn.send(h11.Data(data=response)) await h11_conn.send(h11.EndOfMessage()) await h11_conn.close()
def handle(self): with closing(self.request) as s: c = h11.Connection(h11.SERVER) request = None while True: event = c.next_event() if event is h11.NEED_DATA: # Use a small read buffer to make things more challenging # and exercise more paths :-) c.receive_data(s.recv(10)) continue if type(event) is h11.Request: request = event if type(event) is h11.EndOfMessage: break info = json.dumps({ "method": request.method.decode("ascii"), "target": request.target.decode("ascii"), "headers": { name.decode("ascii"): value.decode("ascii") for (name, value) in request.headers }, }) s.sendall(c.send(h11.Response(status_code=200, headers=[]))) s.sendall(c.send(h11.Data(data=info.encode("ascii")))) s.sendall(c.send(h11.EndOfMessage()))
async def handle_request( server_handle: ServerHandle, wrapper: ClientWrapper, request: h11.Request, ) -> None: body = b"" while True: event = await wrapper.next_event() if isinstance(event, h11.EndOfMessage): break body += cast(h11.Data, event).data method_name, args = parse_request(body, dict(request.headers)) try: method = lookup_method(server_handle, method_name) result = await method(*args) root = format_success(result) status_code = 200 except Exception as exc: root = format_error(exc) status_code = 500 data = build_xml(root) headers = wrapper.basic_headers() headers.append((b"Content-length", str(len(data)).encode())) response = h11.Response(status_code=status_code, headers=headers) await wrapper.send(response) await wrapper.send(h11.Data(data=data)) await wrapper.send(h11.EndOfMessage())
def send_3xx(status_code, reason_phrase, client_handler, headers=None, data=None): response_data = data or str(status_code).encode() response_headers = [ ("location", client_handler.http_test_url), ("connection", "close"), create_content_len_header(response_data), ] if headers is not None: response_headers = _add_external_headers(response_headers, headers) client_handler.http_send( h11.Response( status_code=status_code, http_version=b"1.1", reason=reason_phrase.encode(), headers=response_headers, )) client_handler.http_send(h11.Data(data=response_data))
async def send(self, wrapper): headers = wrapper.server.create_headers() + self.headers await wrapper.send( h11.Response(status_code=self.status_code, headers=headers)) if self.body: await wrapper.send(h11.Data(data=self.body)) await wrapper.send(h11.EndOfMessage())
def request_handler(event_generator): request = next(event_generator, None) if not isinstance(request, h11.Request): return def gen(): yield request yield from event_generator handler = routes.get((request.method, request.target), None) print(threading.get_native_id(), "router", request.method, request.target, handler_name(handler), file=sys.stdout) if handler is None: yield h11.Response( status_code=404, headers=[ ("content-type", "text/plain"), ], ) yield h11.Data(data=b"404 Not Found\n\nsubscribe to Lulu-chan\n") else: yield from handler(gen())
async def _handle_websocket(self, websocket: Websocket) -> None: response = await self.app.handle_websocket(websocket) if response is not None: if self.active: self.connection.close( wsproto.connection.CloseReason.INTERNAL_ERROR) self.write(self.connection.bytes_to_send()) else: headers = chain( ((key, value) for key, value in response.headers.items()), self.response_headers(), ) self.write( self.connection._upgrade_connection.send( h11.Response(status_code=response.status_code, headers=headers), ), ) if not suppress_body('GET', response.status_code): async for data in response.response: self.write( self.connection._upgrade_connection.send( h11.Data(data=data)), ) await self.drain() self.write( self.connection._upgrade_connection.send( h11.EndOfMessage()), ) self.close()
async def stream_send(self, event: StreamEvent) -> None: if isinstance(event, Response): if event.status_code >= 200: await self._send_h11_event( h11.Response( headers=chain(event.headers, self.config.response_headers("h11")), status_code=event.status_code, )) else: await self._send_h11_event( h11.InformationalResponse( headers=chain(event.headers, self.config.response_headers("h11")), status_code=event.status_code, )) elif isinstance(event, Body): await self._send_h11_event(h11.Data(data=event.data)) elif isinstance(event, EndBody): await self._send_h11_event(h11.EndOfMessage()) elif isinstance(event, Data): await self.send(RawData(data=event.data)) elif isinstance(event, EndData): pass elif isinstance(event, StreamClosed): await self._maybe_recycle()
def send_error(self, event: h11.Request, status: HTTPStatus, msg: str = None, explain: str = None): try: short_msg, long_msg = responses[status] except KeyError: short_msg, long_msg = '???', '???' if msg is None: msg = short_msg if explain is None: explain = long_msg headers = [] self.log.error('code {}, message {}'.format(status, msg)) body = None if status >= 200 and status not in (HTTPStatus.NO_CONTENT, HTTPStatus.RESET_CONTENT, HTTPStatus.NOT_MODIFIED): body = self.error_message_format.format(code=status, message=msg, explain=explain).encode('UTF-8', 'replace') headers.extend([('Content-Type', self.error_content_type), ('Content-Length', str(len(body)))]) headers.append(('Connection', 'close')) response = h11.Response(status_code=status, headers=headers) self.send(response) if event.method != 'HEAD' and body: self.send(h11.Data(data=body)) self.send(h11.EndOfMessage())
def error_response(self, status_code: int) -> h11.Response: return h11.Response( status_code=status_code, headers=chain( [(b"content-length", b"0"), (b"connection", b"close")], self.response_headers() ), )
async def asgi_send(self, message: dict) -> None: """Called by the ASGI instance to send a message.""" if message['type'] == 'http.response.start' and self.state == ASGIState.REQUEST: self.response = message elif ( message['type'] == 'http.response.body' and self.state in {ASGIState.REQUEST, ASGIState.RESPONSE} ): if self.state == ASGIState.REQUEST: headers = chain( ( (bytes(key).strip(), bytes(value).strip()) for key, value in self.response['headers'] ), self.response_headers(), ) self.send(h11.Response(status_code=int(self.response['status']), headers=headers)) self.state = ASGIState.RESPONSE if ( not suppress_body(self.scope['method'], int(self.response['status'])) and message.get('body', b'') != b'' ): self.send(h11.Data(data=bytes(message['body']))) await self.drain() if not message.get('more_body', False): if self.state != ASGIState.CLOSED: self.send(h11.EndOfMessage()) self.app_queue.put_nowait({'type': 'http.disconnect'}) self.state = ASGIState.CLOSED else: raise Exception( f"Unexpected message type, {message['type']} given the state {self.state}", )
async def _send_http_reply( self, stream: Stream, conn: h11.Connection, status_code: int, headers: Dict[bytes, bytes] = {}, data: Optional[bytes] = None, ) -> None: reason = HTTPStatus(status_code).phrase headers = list({ **headers, # Add default headers b"server": self.server_header, b"date": format_date_time(None).encode("ascii"), b"content-Length": str(len(data or b"")).encode("ascii"), # Inform we don't support keep-alive (h11 will know what to do from there) b"connection": b"close", }.items()) try: await stream.send_all( conn.send( h11.Response(status_code=status_code, headers=headers, reason=reason))) if data: await stream.send_all(conn.send(h11.Data(data=data))) await stream.send_all(conn.send(h11.EndOfMessage())) except trio.BrokenResourceError: # Given we don't support keep-alive, the connection is going to be # shutdown anyway, so we can safely ignore the fact peer has left pass
def _handle_error(self) -> None: self._send(h11.Response( status_code=400, headers=chain( [('content-length', '0'), ('connection', 'close')], self.response_headers(), ), )) self._send(h11.EndOfMessage())
def test_handshake_rejection_with_body() -> None: events = _make_handshake_rejection(400, body=b"Hello") assert events == [ h11.Response(headers=[(b"content-length", b"5")], status_code=400), h11.Data(data=b"Hello"), h11.EndOfMessage(), ]
async def asgi_send(self, message: dict) -> None: """Called by the ASGI instance to send a message.""" if message["type"] == "http.response.start" and self.state == ASGIHTTPState.REQUEST: self.response = message elif message["type"] == "http.response.body" and self.state in { ASGIHTTPState.REQUEST, ASGIHTTPState.RESPONSE, }: if self.state == ASGIHTTPState.REQUEST: headers = chain( ( (bytes(key).strip(), bytes(value).strip()) for key, value in self.response["headers"] ), self.response_headers(), ) await self.asend( h11.Response(status_code=int(self.response["status"]), headers=headers) ) self.state = ASGIHTTPState.RESPONSE if ( not suppress_body(self.scope["method"], int(self.response["status"])) and message.get("body", b"") != b"" ): await self.asend(h11.Data(data=bytes(message["body"]))) if not message.get("more_body", False): if self.state != ASGIHTTPState.CLOSED: await self.asend(h11.EndOfMessage()) await self.asgi_put({"type": "http.disconnect"}) self.state = ASGIHTTPState.CLOSED else: raise UnexpectedMessage(self.state, message["type"])
async def send_simple_response(wrapper, status_code, content_type, body): headers = wrapper.basic_headers() headers.append(("Content-Type", content_type)) headers.append(("Content-Length", str(len(body)))) res = h11.Response(status_code=status_code, headers=headers) await wrapper.send(res) await wrapper.send(h11.Data(data=body)) await wrapper.send(h11.EndOfMessage())
async def send_simple_response(self, status_code, body=None, headers=None): headers = self.server.create_headers() + (headers or []) if body: headers.append(('Content-Length', str(len(body)))) else: headers.append(('Content-Length', '0')) res = h11.Response(status_code=status_code, headers=headers) await self.send_response(res, body)
def handle_upgrade(self, event: h11.Request): upgrade_value = None for name, value in self.headers: if name == b"upgrade": upgrade_value = value.lower() break if upgrade_value == b"websocket" and self.ws_protocol_class: self.connections.discard(self) output = [event.method, b" ", event.target, b" HTTP/1.1\r\n"] for name, value in self.headers: output += [name, b": ", value, b"\r\n"] output.append(b"\r\n") protocol = self.ws_protocol_class( config=self.config, server_state=self.server_state, on_connection_lost=self.on_connection_lost ) protocol.connection_made(self.transport) protocol.data_received(b"".join(output)) self.transport.set_protocol(protocol) elif upgrade_value == b"h2c": self.connections.discard(self) self.transport.write( self.conn.send( h11.InformationalResponse( status_code=101, headers=self.headers ) ) ) protocol = self.h2_protocol_class( config=self.config, server_state=self.server_state, on_connection_lost=self.on_connection_lost, _loop=self.loop ) protocol.handle_upgrade_from_h11(self.transport, event, self.headers) self.transport.set_protocol(protocol) else: msg = "Unsupported upgrade request." self.logger.warning(msg) reason = STATUS_PHRASES[400] headers = [ (b"content-type", b"text/plain; charset=utf-8"), (b"connection", b"close"), ] event = h11.Response(status_code=400, headers=headers, reason=reason) output = self.conn.send(event) self.transport.write(output) event = h11.Data(data=b"Unsupported upgrade request.") output = self.conn.send(event) self.transport.write(output) event = h11.EndOfMessage() output = self.conn.send(event) self.transport.write(output) self.transport.close()
async def send_response(self, stream_id: int, response: Response, suppress_body: bool) -> None: headers = chain( ((key, value) for key, value in response.headers.items()), self.response_headers(), ) self._send(h11.Response(status_code=response.status_code, headers=headers)) if not suppress_body: async for data in response.response: self._send(h11.Data(data=data)) self._send(h11.EndOfMessage())
async def _send_error_response(self, status_code: int) -> None: await self._send_h11_event( h11.Response( status_code=status_code, headers=chain( [(b"content-length", b"0"), (b"connection", b"close")], self.config.response_headers("h11"), ), )) await self._send_h11_event(h11.EndOfMessage())
def send_response(self, response: HAPResponse) -> None: """Send a HAPResponse object.""" self.write( self.conn.send( h11.Response( status_code=response.status_code, reason=response.reason, headers=response.headers, )) + self.conn.send(h11.Data(data=response.body)) + self.conn.send(h11.EndOfMessage()))
async def send_response(connection, response): headers = {name: value for (name, value) in connection.basic_headers()} headers[b'Content-Type'] = response.content_type headers[b'Content-Length'] = str(len(response.body)) headers.update(response.headers) res = h11.Response(status_code=response.status_code, headers=headers.items()) await connection.send(res) await connection.send(h11.Data(data=response.body)) await connection.send(h11.EndOfMessage())
def send_response(self, event): body = b"%s %s" % (event.method.upper(), event.target) headers = [ ('content-type', 'text/plain'), ('content-length', str(len(body))), ] response = h11.Response(status_code=200, headers=headers) self.send(response) self.send(h11.Data(data=body)) self.send(h11.EndOfMessage())
async def write_simple_response(self, status_code=200, reason=b'OK', headers=(), body={}): data = h11.Data(data=json.dumps(body).encode('utf-8')) response = h11.Response(status_code=status_code, headers=headers + ( ('Content-type', 'application/json'), ('Content-length', str(len(data.data))), ), reason=reason) self.writer.write(self.connection.send(response) + self.connection.send(data) + self.connection.send(h11.EndOfMessage())) await self.writer.drain()
async def send_error(self, error: HTTPException) -> None: response = error.get_response() headers = ((key, value) for key, value in response.headers.items()) self.connection._outgoing += self.connection._upgrade_connection.send( h11.Response(status_code=response.status_code, headers=headers), ) async for data in response.response: self.connection._outgoing += self.connection._upgrade_connection.send( h11.Data(data=data), ) self.connection._outgoing += self.connection._upgrade_connection.send( h11.EndOfMessage()) self._send()