Skip to content

Commit

Permalink
Merge branch 'master' into str-repr
Browse files Browse the repository at this point in the history
  • Loading branch information
ahopkins authored Mar 3, 2021
2 parents f8b139e + a733d32 commit 1a97310
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 17 deletions.
5 changes: 5 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,8 @@ def setup(app):
True,
)
app.add_transform(AutoStructify)


html_theme_options = {
"style_external_links": True,
}
8 changes: 8 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
.. include:: ../README.rst

User Guide
==========

To learn about using Sanic, checkout the `User Guide <https://sanicframework.org/guide/>`_.

API
======

.. toctree::
:maxdepth: 4

👥 User Guide <https://sanicframework.org/guide/>
sanic/api_reference
💻 Source code <https://github.com/sanic-org/sanic/>
❓ Support <https://community.sanicframework.org/>


Module Documentation
Expand Down
4 changes: 2 additions & 2 deletions docs/sanic/api_reference.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
API Reference
=============
📑 API Reference
================

sanic.app
---------
Expand Down
1 change: 1 addition & 0 deletions sanic/constants.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
HTTP_METHODS = ("GET", "POST", "PUT", "HEAD", "OPTIONS", "PATCH", "DELETE")
DEFAULT_HTTP_CONTENT_TYPE = "application/octet-stream"
8 changes: 5 additions & 3 deletions sanic/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,9 @@ async def http1_request_header(self):

# Parse header content
try:
raw_headers = buf[:pos].decode(errors="surrogateescape")
reqline, *raw_headers = raw_headers.split("\r\n")
head = buf[:pos]
raw_headers = head.decode(errors="surrogateescape")
reqline, *split_headers = raw_headers.split("\r\n")
method, self.url, protocol = reqline.split(" ")

if protocol == "HTTP/1.1":
Expand All @@ -204,7 +205,7 @@ async def http1_request_header(self):
request_body = False
headers = []

for name, value in (h.split(":", 1) for h in raw_headers):
for name, value in (h.split(":", 1) for h in split_headers):
name, value = h = name.lower(), value.lstrip()

if name in ("content-length", "transfer-encoding"):
Expand All @@ -223,6 +224,7 @@ async def http1_request_header(self):
request = self.protocol.request_class(
url_bytes=self.url.encode(),
headers=headers_instance,
head=bytes(head),
version=protocol[5:],
method=method,
transport=self.protocol.transport,
Expand Down
4 changes: 2 additions & 2 deletions sanic/mixins/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from sanic_routing.route import Route # type: ignore

from sanic.compat import stat_async
from sanic.constants import HTTP_METHODS
from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE, HTTP_METHODS
from sanic.exceptions import (
ContentRangeError,
FileNotFound,
Expand Down Expand Up @@ -689,7 +689,7 @@ async def _static_request_handler(
content_type = (
content_type
or guess_type(file_path)[0]
or "application/octet-stream"
or DEFAULT_HTTP_CONTENT_TYPE
)

if "charset=" not in content_type and (
Expand Down
20 changes: 14 additions & 6 deletions sanic/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from httptools import parse_url # type: ignore

from sanic.compat import CancelledErrors, Header
from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE
from sanic.exceptions import InvalidUsage
from sanic.headers import (
Options,
Expand All @@ -49,12 +50,6 @@
except ImportError:
from json import loads as json_loads # type: ignore

DEFAULT_HTTP_CONTENT_TYPE = "application/octet-stream"

# HTTP/1.1: https://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1
# > If the media type remains unknown, the recipient SHOULD treat it
# > as type "application/octet-stream"


class RequestParameters(dict):
"""
Expand Down Expand Up @@ -95,6 +90,7 @@ class Request:
"conn_info",
"ctx",
"endpoint",
"head",
"headers",
"method",
"name",
Expand All @@ -121,6 +117,7 @@ def __init__(
method: str,
transport: TransportProtocol,
app: Sanic,
head: bytes = b"",
):
self.raw_url = url_bytes
# TODO: Content-Encoding detection
Expand All @@ -132,6 +129,7 @@ def __init__(
self.version = version
self.method = method
self.transport = transport
self.head = head

# Init but do not inhale
self.body = b""
Expand Down Expand Up @@ -207,6 +205,16 @@ async def receive_body(self):
if not self.body:
self.body = b"".join([data async for data in self.stream])

@property
def raw_headers(self):
_, headers = self.head.split(b"\r\n", 1)
return bytes(headers)

@property
def request_line(self):
reqline, _ = self.head.split(b"\r\n", 1)
return bytes(reqline)

@property
def id(self) -> Optional[Union[uuid.UUID, str, int]]:
"""
Expand Down
3 changes: 2 additions & 1 deletion sanic/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from warnings import warn

from sanic.compat import Header, open_async
from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE
from sanic.cookies import CookieJar
from sanic.helpers import has_message_body, remove_entity_headers
from sanic.http import Http
Expand Down Expand Up @@ -297,7 +298,7 @@ def raw(
body: Optional[AnyStr],
status: int = 200,
headers: Optional[Dict[str, str]] = None,
content_type: str = "application/octet-stream",
content_type: str = DEFAULT_HTTP_CONTENT_TYPE,
) -> HTTPResponse:
"""
Returns response object without encoding the body.
Expand Down
36 changes: 33 additions & 3 deletions tests/test_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

import pytest

from sanic import Sanic, headers
from sanic.compat import Header
from sanic import headers, text
from sanic.exceptions import PayloadTooLarge
from sanic.http import Http
from sanic.request import Request


@pytest.mark.parametrize(
Expand Down Expand Up @@ -85,3 +83,35 @@ async def _receive_more():

with pytest.raises(PayloadTooLarge):
await http.http1_request_header()


def test_raw_headers(app):
app.route("/")(lambda _: text(""))
request, _ = app.test_client.get(
"/",
headers={
"FOO": "bar",
"Host": "example.com",
"User-Agent": "Sanic-Testing",
},
)

assert request.raw_headers == (
b"Host: example.com\r\nAccept: */*\r\nAccept-Encoding: gzip, "
b"deflate\r\nConnection: keep-alive\r\nUser-Agent: "
b"Sanic-Testing\r\nFOO: bar"
)


def test_request_line(app):
app.route("/")(lambda _: text(""))
request, _ = app.test_client.get(
"/",
headers={
"FOO": "bar",
"Host": "example.com",
"User-Agent": "Sanic-Testing",
},
)

assert request.request_line == b"GET / HTTP/1.1"

0 comments on commit 1a97310

Please sign in to comment.