Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comply with new h11 #1744

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ classifiers = [
]
dependencies = [
"click>=7.0",
"h11>=0.8",
"h11 @ git+https://github.com/pgjones/h11.git@master",
"typing-extensions;python_version < '3.8'",
]

Expand Down Expand Up @@ -61,3 +61,6 @@ path = "uvicorn/__init__.py"
include = [
"/uvicorn",
]

[tool.hatch.metadata]
allow-direct-references = true
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ cryptography==38.0.1
coverage==6.5.0
coverage-conditional-plugin==0.7.0
httpx==0.23.0
httpcore @ git+https://github.com/encode/httpcore.git
watchgod==0.8.2

# Documentation
Expand Down
2 changes: 1 addition & 1 deletion scripts/check
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ set -x
./scripts/sync-version
${PREFIX}black --check --diff --target-version=py37 $SOURCE_FILES
${PREFIX}flake8 $SOURCE_FILES
${PREFIX}mypy --show-error-codes
${PREFIX}mypy
${PREFIX}isort --check --diff --project=uvicorn $SOURCE_FILES
${PREFIX}python -m tools.cli_usage --check
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ max-line-length = 88
disallow_untyped_defs = True
ignore_missing_imports = True
follow_imports = silent
show_error_codes = True
files =
uvicorn/lifespan,
uvicorn/config.py,
Expand Down
29 changes: 14 additions & 15 deletions uvicorn/protocols/http/h11_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ def handle_events(self) -> None:
return
event_type = type(event)

if event_type is h11.NEED_DATA:
if event is h11.NEED_DATA:
break

elif event_type is h11.PAUSED:
elif event is h11.PAUSED:
# This case can occur in HTTP pipelining, so we need to
# stop reading any more data, and ensure that at the end
# of the active request/response cycle we handle any
Expand All @@ -205,6 +205,7 @@ def handle_events(self) -> None:
break

elif event_type is h11.Request:
event = cast(h11.Request, event)
self.headers = [(key.lower(), value) for key, value in event.headers]
raw_path, _, query_string = event.target.partition(b"?")
self.scope = { # type: ignore[typeddict-item]
Expand Down Expand Up @@ -258,6 +259,7 @@ def handle_events(self) -> None:
self.tasks.add(task)

elif event_type is h11.Data:
event = cast(h11.Data, event)
if self.conn.our_state is h11.DONE:
continue
self.cycle.body += event.data
Expand All @@ -266,14 +268,15 @@ def handle_events(self) -> None:
self.cycle.message_event.set()

elif event_type is h11.EndOfMessage:
event = cast(h11.EndOfMessage, event)
if self.conn.our_state is h11.DONE:
self.transport.resume_reading()
self.conn.start_next_cycle()
continue
self.cycle.more_body = False
self.cycle.message_event.set()

def handle_websocket_upgrade(self, event: H11Event) -> None:
def handle_websocket_upgrade(self, event: h11.Request) -> None:
if self.logger.level <= TRACE_LOG_LEVEL:
prefix = "%s:%d - " % self.client if self.client else ""
self.logger.log(TRACE_LOG_LEVEL, "%sUpgrading to WebSocket", prefix)
Expand All @@ -300,11 +303,9 @@ def send_400_response(self, msg: str) -> None:
event = h11.Response(status_code=400, headers=headers, reason=reason)
output = self.conn.send(event)
self.transport.write(output)
event = h11.Data(data=msg.encode("ascii"))
output = self.conn.send(event)
output = self.conn.send(h11.Data(data=msg.encode("ascii")))
self.transport.write(output)
event = h11.EndOfMessage()
output = self.conn.send(event)
output = self.conn.send(h11.EndOfMessage())
self.transport.write(output)
self.transport.close()

Expand Down Expand Up @@ -506,18 +507,17 @@ async def send(self, message: "ASGISendEvent") -> None:

# Write response body
if self.scope["method"] == "HEAD":
event = h11.Data(data=b"")
data = b""
else:
event = h11.Data(data=body)
output = self.conn.send(event)
data = body
output = self.conn.send(h11.Data(data=data))
self.transport.write(output)

# Handle response completion
if not more_body:
self.response_complete = True
self.message_event.set()
event = h11.EndOfMessage()
output = self.conn.send(event)
output = self.conn.send(h11.EndOfMessage())
self.transport.write(output)

else:
Expand All @@ -527,15 +527,14 @@ async def send(self, message: "ASGISendEvent") -> None:

if self.response_complete:
if self.conn.our_state is h11.MUST_CLOSE or not self.keep_alive:
event = h11.ConnectionClosed()
self.conn.send(event)
self.conn.send(h11.ConnectionClosed())
self.transport.close()
self.on_response()

async def receive(self) -> "ASGIReceiveEvent":
if self.waiting_for_100_continue and not self.transport.is_closing():
event = h11.InformationalResponse(
status_code=100, headers=[], reason="Continue"
status_code=100, headers=[], reason="Continue" # type: ignore[arg-type]
)
output = self.conn.send(event)
self.transport.write(output)
Expand Down