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

HTTP/3 support #173

Closed
raphaelauv opened this issue Sep 1, 2020 · 12 comments
Closed

HTTP/3 support #173

raphaelauv opened this issue Sep 1, 2020 · 12 comments
Labels
enhancement New feature or request

Comments

@raphaelauv
Copy link

Hello, a big thank for all your work ! I was looking around the python community for a http/3 webserver

Do you have any plans for HTTP/3 support ? If yes would you like to share your roadmap 😀

( an existing implementation of quic -> https://github.com/aiortc/aioquic )

@tomchristie
Copy link
Member

We've got an issue open for it yup - encode/httpx#275

Not particularly a high priority at the moment, but I'd expect us to have an implementation against it at some point.

@raphaelauv
Copy link
Author

raphaelauv commented Sep 1, 2020

Great ! thank you, but may I ask what is the relation between httpx and httpcore ? And why http3 should be implemented there and not inside httpcore ?

@florimondmanca
Copy link
Member

@raphaelauv

may I ask what is the relation between httpx and httpcore ?

HTTPCore provides the HTTP networking implementation and a tightly-defined HTTP client API on top of it (called the "transport API"). (I have a draft blog post about this, still hoping to finish this someday… 😄)

And why http3 should be implemented there and not inside httpcore ?

The issue happens to be on the HTTPX repo mainly because it was opened before HTTPCore even existed. :-) I'd say it's unclear yet how much of this would go between HTTPX and HTTPCore, but yup clearly I'd expect the bulk of the work to be in HTTPCore (at least for the core networking implementation).

So, dunno if we want to keep issues on both repos, but I guess it's okay to keep this open here for now. Any case, we have encode/httpx#1180 opened to unify issue trackers between HTTPx and HTTPCore soon-ish.

@jlaine
Copy link
Contributor

jlaine commented Mar 12, 2021

FYI I have updated my "httpx" demo of aioquic to use an httpcore.AsyncHTTPTransport, see:

https://github.com/aiortc/aioquic/blob/main/examples/httpx_client.py

Do you have any guidance about how to move this forward into an actual PR against httpcore?

@florimondmanca
Copy link
Member

Thanks for that @jlaine :-)

I anticipate there will be a long tail of small things to figure out.

From a quick lookover on the demo code, some open questions I can see:

  • Can aioquic allow support for streaming responses? I see the demo aggregates content to return a PlainByteStream.
  • Can aioquic support read/write timeouts (located in ext["timeout"])?
  • How will connection pooling look like (if connection pooling still makes sense under HTTP/3)?
  • How do we deal with this being asyncio-only for now? (HTTPCore is async agnostic by default.)

On the code side of things, can it be rewritten so that we have H3Transport(AsyncHTTPTransport), and a separate QuicConnectionProtocol subclass, rather than mixing both? I assume this would help answer the "which are the asyncio bits", and just make things more legible.

@florimondmanca florimondmanca added the enhancement New feature or request label Mar 12, 2021
@jlaine
Copy link
Contributor

jlaine commented Mar 12, 2021

Some answers:

  • Yes you can very much support streaming responses, I was just lazy. I'll look at what's done for h2, it will be quite similar. I assume calling aclose() before all data was received means "abort the request"?
  • I am not sure what these read/write timeouts are about? Tear down the connection if they are exceeded?
  • Pooling: again, I'm not familiar with the internals of httpcore. Is this about using the same connection for multiple client/requests? If so yes, the concept very much applies, especially since HTTP/3 doesn't have the head-of-line blocking problem.
  • It doesn't have to be asyncio-only. At its core, aioquic provides a sans-io API, but it does mean rebuilding the equivalent of QuicConnectionProtocol for whatever backends you support.

Sans-IO APIs:
https://aioquic.readthedocs.io/en/latest/quic.html
https://aioquic.readthedocs.io/en/latest/h3.html

I think the main stumbling block here is that I don't have an in-depth knowledge of httpcore's internals, and I wanted a minimal demo which shows where to plug into aioquic, and which works with httpcore/httpx's public APIs.

@jlaine
Copy link
Contributor

jlaine commented Mar 12, 2021

The very first step would be to introduce two new abstractions:

  • a UDP socket abstraction
  • a timer abstraction which can be set to fire in the future

The socket abstraction might look like:

class AsyncDatagramSocket:
    async def receive(self) -> Tuple[bytes, Tuple]:
        ...

    async def send(self, data: bytes, addr: Tuple) -> None:
        ...

I had a look at various implementations and here is what I've found:

  • asyncio : loop.create_datagram_endpoint + a protocol can be used to build the abstraction
  • curio : curio.socket can be used to create a UDP socket. It has two coroutines: sendto(data: bytes, addr: Tuple) and recvfrom(size: int) -> Tuple[bytes, Tuple]
  • trio : same as curio
  • anyio : it also provides UDP socket support, though its method signatures seem different, as far as I can tell its send method takes a tuple

@tomchristie
Copy link
Member

Hiya @jlaine!

I guess an initial steps that move us forward here could be...

A PR that adds an example of using H3Transport into the httpx documentation. We'd want to document the limitations at this point in time, which I guess are... (1) At this point right now today, it's currently asyncio-specific. (2) Not integrated with https's connection pooling etc, so you need to know in advance that it's an HTTP/3 service you're connecting with. (3) Newer tech, lookout(!) etc.

I think we also would want to try to be a bit careful around framing motivations. Plenty of users might see the "3" part of HTTP/3, and assume that there's some legitimate reasons they ought to be "upgrading". I think we need a nice clear push back on that default assumption, because typically I'd actually assume that a plain old HTTP/1.1 client is generally the best choice for most Python developers at this point in time. (I'd suggest this even over HTTP/2, because the complexity vs. potential-for-improved-concurrency seems like a premature optimisation, unless you've actually demo'ed to yourself a concrete requirement/improvement.)

Having it pointed to via the docs would start to drive some usage, which might get you some good feedback to help us prioritise the various other bits along the way to getting something to the point that we want to full integrate it. (?)

@jlaine
Copy link
Contributor

jlaine commented Mar 15, 2021

Hi @tomchristie : regarding point (1) as I've said there is nothing async-io specific here, I'm not proposing to use aioquic's asyncio code (which is a convenience wrapper around the events-based API) at all. As long as I have a factory for UDP sockets and a timer, the code which would go into the transport would be I/O framework agnostic.

@tomchristie
Copy link
Member

Okay, well I'm down for a docs PR at whatever point you think that's ready, and can work from there.

@jlaine
Copy link
Contributor

jlaine commented Mar 15, 2021

Here's a work-in-progress PR: #283

It's still rough around the edges (timeouts are not implemented, there is no packet retransmission), but it should give you a clearer idea of what I mean.

NOTE: what it does do is clearly demonstrate how this is not asyncio-specific, I have provided equal support for asyncio, curio and trio.

@tomchristie
Copy link
Member

I think it makes sense for us to close off the issues in httpcore, and just keep everything collated under httpx in terms of issues, so let's track this on encode/httpx#275

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants