async def connect(self): tc = self.testclient app = tc.application headers, path, query_string_bytes = make_test_headers_path_and_query_string( app, self.path, self.headers ) if self.cookies is None: # use TestClient.cookie_jar cookie_jar = tc.cookie_jar else: cookie_jar = SimpleCookie(self.cookies) if cookie_jar and cookie_jar.output(header=""): headers.add("Cookie", cookie_jar.output(header="")) scope = { "type": "websocket", "headers": flatten_headers(headers), "path": path, "query_string": query_string_bytes, "root_path": "", "scheme": "http", "subprotocols": [], } create_monitored_task( app(scope, self.input_queue.get, self.output_queue.put), self.output_queue.put_nowait, ) await self._send({"type": "websocket.connect"}) msg = await self._receive() assert msg["type"] == "websocket.accept"
async def connect(self): self.headers.update({"host": "localhost"}) flat_headers = [(bytes(k.lower(), "utf8"), bytes(v, "utf8")) for k, v in self.headers.items()] scheme, netloc, path, query, fragment = urlsplit(self.path) scope = { "type": "websocket", "headers": flat_headers, "path": unquote(path), "query_string": query.encode(), "root_path": "", "scheme": scheme, "subprotocols": [], } create_monitored_task( self.app(scope, self.input_queue.get, self.output_queue.put), self.output_queue.put_nowait, ) await self.send({"type": "websocket.connect"}) msg = await self.receive() assert msg["type"] == "websocket.accept"
async def __aenter__(self): create_monitored_task( self.application( { "type": "lifespan", "asgi": { "version": "3.0" } }, self._lifespan_input_queue.get, self._lifespan_output_queue.put, ), self._lifespan_output_queue.put_nowait, ) await self.send_lifespan("startup") return self
async def open( self, path: str, *, method: str = "GET", headers: Optional[Union[dict, CIMultiDict]] = None, data: Any = None, form: Optional[dict] = None, query_string: Optional[dict] = None, json: Any = sentinel, scheme: str = "http", cookies: Optional[dict] = None, stream: bool = False, allow_redirects: bool = True, ): """Open a request to the app associated with this client. Arguments: path The path to request. If the query_string argument is not defined this argument will be partitioned on a '?' with the following part being considered the query_string. method The method to make the request with, defaults to 'GET'. headers Headers to include in the request. data Raw data to send in the request body or async generator form Data to send form encoded in the request body. query_string To send as a dictionary, alternatively the query_string can be determined from the path. json Data to send json encoded in the request body. scheme The scheme to use in the request, default http. cookies Cookies to send in the request instead of cookies in TestClient.cookie_jar stream Return the response in streaming instead of buffering allow_redirects If set to True follows redirects Returns: The response from the app handling the request. """ input_queue: asyncio.Queue[dict] = asyncio.Queue() output_queue: asyncio.Queue[dict] = asyncio.Queue() headers, path, query_string_bytes = make_test_headers_path_and_query_string( self.application, path, headers, query_string) if [json is not sentinel, form is not None, data is not None ].count(True) > 1: raise ValueError( "Test args 'json', 'form', and 'data' are mutually exclusive") request_data = b"" if isinstance(data, str): request_data = data.encode("utf-8") elif isinstance(data, bytes): request_data = data if json is not sentinel: request_data = dumps(json).encode("utf-8") headers["Content-Type"] = "application/json" if form is not None: request_data = urlencode(form).encode("utf-8") headers["Content-Type"] = "application/x-www-form-urlencoded" if cookies is None: # use TestClient.cookie_jar cookie_jar = self.cookie_jar else: cookie_jar = SimpleCookie(cookies) if cookie_jar and cookie_jar.output(header=""): headers.add("Cookie", cookie_jar.output(header="")) flat_headers: List[Tuple] = [(bytes(k.lower(), "utf8"), bytes(v, "utf8")) for k, v in headers.items()] scope = { "type": "http", "http_version": "1.1", "asgi": { "version": "3.0" }, "method": method, "scheme": scheme, "path": path, "query_string": query_string_bytes, "root_path": "", "headers": flat_headers, } create_monitored_task( self.application(scope, input_queue.get, output_queue.put), output_queue.put_nowait, ) send = input_queue.put_nowait receive_or_fail = partial(receive, output_queue, timeout=self.timeout) # Send request if inspect.isasyncgen(data): async for is_last, body in is_last_one(data): send({ "type": "http.request", "body": body, "more_body": not is_last }) else: send({"type": "http.request", "body": request_data}) response = Response(stream, receive_or_fail, send) # Receive response start message = await self.wait_response(receive_or_fail, "http.response.start") response.status_code = message["status"] response.headers = CIMultiDict([(k.decode("utf8"), v.decode("utf8")) for k, v in message["headers"]]) # Receive initial response body message = await self.wait_response(receive_or_fail, "http.response.body") response.raw.write(message["body"]) response._more_body = message.get("more_body", False) # Consume the remaining response if not in stream if not stream: bytes_io = BytesRW() bytes_io.write(response.raw.read()) async for chunk in response: bytes_io.write(chunk) response.raw = bytes_io response._content = bytes_io.read() response._content_consumed = True if cookie_jar is not None: cookies = SimpleCookie() for c in response.headers.getall("Set-Cookie", ""): cookies.load(c) response.cookies = requests.cookies.RequestsCookieJar() response.cookies.update(cookies) cookie_jar.update(cookies) if allow_redirects and response.is_redirect: path = response.headers["location"] return await self.get(path) else: return response