Skip to content

Conversation

@synodriver
Copy link
Member

No description provided.

pgjones and others added 30 commits February 21, 2022 20:57
This allows for Hypercorn to be used behind servers/proxies that add
this header as well.
This removes warnings and ensures that pytest asyncio doesn't affect
the trio tests.
Even when the server tasks error, for example with a "ssl.SSLError:
[SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after
close notify".

Thanks to @jonathanslenders for the report and suggested fix.
This allows an alternative format to the default ini format used by
``fileConfig``. This can also be used on the command line,

    hypercorn --log-config json:file.json ...

for example.
This change makes the Keep-Alive timeout routines sensitive to the
global termination switch, so that a connection in a Keep-Alive state
will immediately close when termination is requested. It achieves this
by making the termination flag on the context an event instead.

We also fix a minor bug where the Keep-Alive timeout would never be
reset after the first time it was created.

More work is needed for HTTP/3, as the semantics of a connection in a
GOAWAY state are different than what is currently exposed as "idle" from
the UDP server's perspective.
This ensures that for HTTP/1 the returned headers match the casing as
sent by the ASGI app.
This allows an ASGI application to send link header values to
Hypercorn which Hypercorn will then send as an Early Hints response
(103).

Informational responses are ignored for HTTP/1 as it is likely clients
will not correctly understand the meaning.
This will allow the CI to run on github rather than gitlab, allowing
me to transfer.
This should, hopefully allow the docs to build and make it clearer to
other users how to setup and install the docs requirements.
GitHub has a better pricing model and is more popular for OSS, hence
the move.
RFC 7232 is clear that 204 and 304 bodies should be suppressed, but
says nothing for 412.
This ensures that the connection is marked as not idle before a
protocol upgrade takes place. This therefore ensures that on upgrading
a slow response is not timed out.
Forgot to check.
This allows Hypercorn to serve a wsgi application via:

    hypercorn module:app

With requests being run in threads via an asyncio executor or a trio
run_sync call.

The type of app will be determined automatically, however if it isn't
an additional prefix can be used to specify wsgi or asgi as:

    hypercorn wsgi:module:app
    hypercorn asgi:module:app

Note that this drops support for ASGI2 applications as it is unlikely
this is useful anymore.
The former is no longer supported.
Rather than the outdated access logger class.
I was too lazy with this change and didn't check.
Rather than using a single process with the reloader and restarting
the entire program there is now a main process that checks for changes
and restarts the process workers if so. This should resolve the
various bugs trying to restart the entire program.

A downside is that there is now always at least two processes and it
is harder to use a reloader when using the API method to serve an app.

Note the application must be loaded in the main process so that the
observer knows what files to check for changes.
As it doesn't reload it is pointless to load it again.
This extends the new functionality to the programatic usage.
I no longer test 3.7 locally.
alex-anthropic and others added 28 commits May 10, 2024 18:48
This occurs if the response is sent before the full request body has
been received.
These files are not script-like (no `if __name__ == "__main__":` or
interesting side effects) and have no shebang lines (`#!`), so there is
no reason for the executable bit to be set in their filesystem
permissions.
I wish to consider this solution, and also ensure any solution applies
in the same manner for asyncio and UDP servers.
All of the imports are already conditionalized on the Python interpreter
version; there is no need to install this backport package on current
interpreters.
This should make it clearer what the trusted_hops argument should be.
This is based on the Werkzeug docs.
This is necessary as the data is not known to be either websocket or
http data as the server must accept or reject the connection and hence
it is a bad request.

In practice this is rare as the upgrade request is a GET request which
rarely has body data and most websocket clients wait for acceptance.
This prevents Hypercorn calling aioquic's interface too many times,
due to many tasks running concurrently, triggering exponential backoff
and errors.

Many thanks to @rthalley from whom's work this is based.
This adds support for the ASGI http-trailers extension which allows
for trailing headers to be sent after a response.

Many thanks to @jeffsawatzky from whom parts of this implementation
are based.
This is required to use `NotRequired` when type hinting TypedDicts as
required in d8de5f2.
Better to handle the timer every time. With thanks to @rthalley.
This allows ASGI apps to store state during startup that is then
passed in every scope.
This was an ASGI specification condition that has now been relaxed.
The previous code was meant to ensure the response was not sent until
the first byte was recevied. However, as the response_body has been
set this should be enough and ensures that empty response bodies work.
The EndBody event should only be sent after the headers as this
results in the stream being closed.

It is acceptable to send no response and only trailing headers, in
which case a default 200 status code response is sent with the
headers.
This reverts commit a099217.

As get OSError: [Errno 92] Protocol not available in Docker containers
- needs further investigation.
This was a mistake in the recent QUIC work.

Odd that mypy didn't pick this up.
This reverts commit 74d5b95.

The issue wasn't Docker, but rather trying to set TCP properties on a
UDP socket, hence the additional condition in this version.
This brings Hypercorn in line with what is required for Python 3.13
onwards.
A lifespan.startup.failure should crash the server, however if these
became wrapped in an Exception group in the ASGI app the server
wouldn't crash, now fixed.
This fixes a regression caused by
bfb0877 whereby the cancellation
error was caught. It should instead be re-raised.
The path shouldn't have been adjusted, rather the root_path should
have been changed - this matches WSGI whereby the script_name is
changed. In addition the changes should have been made in a copied
scope to isolate them.
@synodriver synodriver requested a review from Copilot October 13, 2025 06:19
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces "Free threading" support to Hypercorn, implementing significant changes to modernize the codebase and add new functionality. The primary purpose is to add support for free-threading Python builds while updating Python compatibility and adding new features.

Key changes include:

  • Python version update: Minimum Python version increased from 3.7 to 3.8, with support added for 3.11 and 3.12
  • Free threading support: Added worker_type configuration option to choose between "process" and "thread" workers
  • Direct WSGI support: Added native WSGI application serving capabilities through new app wrapper system

Reviewed Changes

Copilot reviewed 80 out of 82 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tox.ini Updated Python versions and dependencies for testing
tests/ Updated test files to use new app wrappers, type annotations, and async fixtures
src/hypercorn/ Core implementation changes for WSGI support, worker threading, and modernized async patterns
docs/ Documentation updates for new features and configuration options
pyproject.toml Updated Python version requirements and dependencies

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

# changes, but only when the reloader is being used.
load_application(config.application_path, config.wsgi_max_body_size)

active = True
Copy link

Copilot AI Oct 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove trailing whitespace.

Suggested change
active = True
active = True

Copilot uses AI. Check for mistakes.
if args.max_requests is not sentinel:
config.max_requests = args.max_requests
if args.max_requests_jitter is not sentinel:
config.max_requests_jitter = args.max_requests
Copy link

Copilot AI Oct 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should assign args.max_requests_jitter instead of args.max_requests to config.max_requests_jitter.

Suggested change
config.max_requests_jitter = args.max_requests
config.max_requests_jitter = args.max_requests_jitter

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.