コード例 #1
0
    def output(self, version="1.1", keep_alive=False, keep_alive_timeout=None):
        # This is all returned in a kind-of funky way
        # We tried to make this as fast as possible in pure python
        timeout_header = b''
        if keep_alive and keep_alive_timeout is not None:
            timeout_header = b'Keep-Alive: %d\r\n' % keep_alive_timeout

        body = b''
        if has_message_body(self.status):
            body = self.body
            self.headers['Content-Length'] = self.headers.get(
                'Content-Length', len(self.body))

        self.headers['Content-Type'] = self.headers.get(
            'Content-Type', self.content_type)

        if self.status in (304, 412):
            self.headers = remove_entity_headers(self.headers)

        headers = self._parse_headers()

        if self.status is 200:
            status = b'OK'
        else:
            status = STATUS_CODES.get(self.status, b'UNKNOWN RESPONSE')

        return (b'HTTP/%b %d %b\r\n'
                b'Connection: %b\r\n'
                b'%b'
                b'%b\r\n'
                b'%b') % (version.encode(), self.status, status,
                          b'keep-alive' if keep_alive else b'close',
                          timeout_header, headers, body)
コード例 #2
0
    def output(self, version="1.1", keep_alive=False, keep_alive_timeout=None):
        # This is all returned in a kind-of funky way
        # We tried to make this as fast as possible in pure python
        timeout_header = b""
        if keep_alive and keep_alive_timeout is not None:
            timeout_header = b"Keep-Alive: %d\r\n" % keep_alive_timeout

        body = b""
        if has_message_body(self.status):
            body = self.body
            self.headers["Content-Length"] = self.headers.get(
                "Content-Length", len(self.body))

        # self.headers get priority over content_type
        if self.content_type and "Content-Type" not in self.headers:
            self.headers["Content-Type"] = self.content_type

        if self.status in (304, 412):
            self.headers = remove_entity_headers(self.headers)

        headers = self._parse_headers()
        status = STATUS_CODES.get(self.status, b"UNKNOWN RESPONSE")
        return (b"HTTP/%b %d %b\r\n"
                b"Connection: %b\r\n"
                b"%b"
                b"%b\r\n"
                b"%b") % (
                    version.encode(),
                    self.status,
                    status,
                    b"keep-alive" if keep_alive else b"close",
                    timeout_header,
                    headers,
                    body,
                )
コード例 #3
0
    def output(self, version="1.1", keep_alive=False, keep_alive_timeout=None):
        body = b""
        if has_message_body(self.status):
            body = self.body
            self.headers["Content-Length"] = self.headers.get(
                "Content-Length", len(self.body))

        return self.get_headers(version, keep_alive, keep_alive_timeout, body)
コード例 #4
0
ファイル: test_helpers.py プロジェクト: wegroupwolves/sanic
def test_has_message_body():
    tests = (
        (100, False),
        (102, False),
        (204, False),
        (200, True),
        (304, False),
        (400, True),
    )
    for status_code, expected in tests:
        assert helpers.has_message_body(status_code) is expected
コード例 #5
0
    def processed_headers(self):
        """Obtain a list of header tuples encoded in bytes for sending.

        Add and remove headers based on status and content_type.
        """
        # 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())
コード例 #6
0
ファイル: http.py プロジェクト: shalevy1/sanic
    async def http1_response_header(self, data: bytes,
                                    end_stream: bool) -> None:
        res = self.response

        # Compatibility with simple response body
        if not data and getattr(res, "body", None):
            data, end_stream = res.body, True  # type: ignore

        size = len(data)
        headers = res.headers
        status = res.status

        if not isinstance(status, int) or status < 200:
            raise RuntimeError(f"Invalid response status {status!r}")

        if not has_message_body(status):
            # Header-only response status
            self.response_func = None
            if (data or not end_stream or "content-length" in headers
                    or "transfer-encoding" in headers):
                data, size, end_stream = b"", 0, True
                headers.pop("content-length", None)
                headers.pop("transfer-encoding", None)
                logger.warning(
                    f"Message body set in response on {self.request.path}. "
                    f"A {status} response may only have headers, no body.")
        elif self.head_only and "content-length" in headers:
            self.response_func = None
        elif end_stream:
            # Non-streaming response (all in one block)
            headers["content-length"] = size
            self.response_func = None
        elif "content-length" in headers:
            # Streaming response with size known in advance
            self.response_bytes_left = int(headers["content-length"]) - size
            self.response_func = self.http1_response_normal
        else:
            # Length not known, use chunked encoding
            headers["transfer-encoding"] = "chunked"
            data = b"%x\r\n%b\r\n" % (size, data) if size else b""
            self.response_func = self.http1_response_chunked

        if self.head_only:
            # Head request: don't send body
            data = b""
            self.response_func = self.head_response_ignored

        headers["connection"] = "keep-alive" if self.keep_alive else "close"
        ret = format_http1_response(status, res.processed_headers)
        if data:
            ret += data

        # Send a 100-continue if expected and not Expectation Failed
        if self.expecting_continue:
            self.expecting_continue = False
            if status != 417:
                ret = HTTP_CONTINUE + ret

        # Send response
        if self.protocol.access_log:
            self.log_response()

        await self._send(ret)
        self.stage = Stage.IDLE if end_stream else Stage.RESPONSE