def set_request(wsgi_environ, app=None, transport=None): """ Test helper context manager that mocks the sanic request """ environ = {} headers = Header() environ.update(wsgi_environ) for k, v in REQUEST_DEFAULTS.items(): environ.setdefault(k, v) url_bytes = b"%s://%s" % (environ['SCHEME'], environ['HOST']) headers.setdefault('Host', environ['HOST'].decode('utf-8')) if environ['SCHEME'] == b"http" and environ['PORT'] in (80, b"80"): pass elif environ['SCHEME'] == b"https" and environ['PORT'] in (443, b"443"): pass else: port = environ['PORT'] if isinstance(port, int): port = str(port) if isinstance(port, str): port = port.encode('latin-1') url_bytes = b"%s:%s" % (url_bytes, port) if environ['PATH'] == b"": pass else: path = environ['PATH'] if path == b"/": path = b"" url_bytes = b"%s/%s" % (url_bytes, path) if environ['QUERY_STRING'] == b"": pass else: url_bytes = b"%s?%s" % (url_bytes, environ['QUERY_STRING']) version = environ['VERSION'].decode('utf-8') method = environ['METHOD'].decode('utf-8') if app is None: app = set_request.app if transport is None: transport = DummyTransport() r = SanicRequest(url_bytes, headers, version, method, transport, app) with mock.patch.dict(extract_params.__globals__, {'request': r}): yield
class BaseHTTPResponse: """ The base class for all HTTP Responses """ def __init__(self): self.asgi: bool = False self.body: Optional[bytes] = None self.content_type: Optional[str] = None self.stream: Http = None self.status: int = None self.headers = Header({}) self._cookies: Optional[CookieJar] = None def _encode_body(self, data: Optional[AnyStr]): if data is None: return b"" return ( data.encode() if hasattr(data, "encode") else data # type: ignore ) @property def cookies(self) -> CookieJar: """ The response cookies. Cookies should be set and written as follows: .. code-block:: python response.cookies["test"] = "It worked!" response.cookies["test"]["domain"] = ".yummy-yummy-cookie.com" response.cookies["test"]["httponly"] = True `See user guide <https://sanicframework.org/guide/basics/cookies.html>`_ :return: the cookie jar :rtype: CookieJar """ if self._cookies is None: self._cookies = CookieJar(self.headers) return self._cookies @property def processed_headers(self) -> Iterator[Tuple[bytes, bytes]]: """ Obtain a list of header tuples encoded in bytes for sending. Add and remove headers based on status and content_type. :return: response headers :rtype: Tuple[Tuple[bytes, bytes], ...] """ # TODO: Make a blacklist set of header names and then filter with that if self.status in (304, 412): # Not Modified, Precondition Failed self.headers = remove_entity_headers(self.headers) if has_message_body(self.status): self.headers.setdefault("content-type", self.content_type) # Encode headers into bytes return ( (name.encode("ascii"), f"{value}".encode(errors="surrogateescape")) for name, value in self.headers.items() ) async def send( self, data: Optional[Union[AnyStr]] = None, end_stream: Optional[bool] = None, ) -> None: """ Send any pending response headers and the given data as body. :param data: str or bytes to be written :param end_stream: whether to close the stream after this block """ if data is None and end_stream is None: end_stream = True if end_stream and not data and self.stream.send is None: return data = ( data.encode() # type: ignore if hasattr(data, "encode") else data or b"" ) await self.stream.send(data, end_stream=end_stream)