Repository navigation
Conversation
0778d66 to
b46a2c5
Compare
| """ | ||
| Read some data from the network, and update the H2 state. | ||
| """ | ||
| data, addr = await self.socket.receive() |
There was a problem hiding this comment.
Do we need to apply the read timeout here?
| # send datagrams | ||
| now = await self.backend.time() | ||
| for data, addr in self._quic.datagrams_to_send(now=now): | ||
| await self.socket.send(data, addr) |
There was a problem hiding this comment.
Do we need to apply the write timeout here?
|
|
||
| return data, addr | ||
|
|
||
| async def send(self, data: bytes, addr: SocketAddr) -> None: |
There was a problem hiding this comment.
Is there something we should be "waiting" for? In other backends this calls an async operation, IDK if asyncio exposes any kind of equivalent "actually wait for something to happen" API, instead of just scheduling something for later?
There was a problem hiding this comment.
To my knowledge UDP APIs don't provide any kind of backpressure.
| async def aclose(self) -> None: | ||
| raise NotImplementedError() # pragma: no cover | ||
|
|
||
| async def receive(self) -> Tuple[bytes, SocketAddr]: |
There was a problem hiding this comment.
For consistency, should these be named read() and write()? Otherwise we might consider to update the doc string for this class to use the same receive/send lingo.
There was a problem hiding this comment.
I don't think read / write make sense here as we are also conveying another information: the remote address. The "classical" corresponding APIs are recvfrom and sendto but as I understand we're avoid abbreviations, I went for "receive" and "send".
anyio seems to have settled on the same names: https://github.com/agronholm/anyio/blob/3a0b805a3f4410009f2b6610d329fb9cc2b90e5a/src/anyio/_backends/_asyncio.py#L1258
| Origin = Tuple[bytes, bytes, int] | ||
| URL = Tuple[bytes, bytes, Optional[int], bytes] | ||
| Headers = List[Tuple[bytes, bytes]] | ||
| SocketAddr = Tuple |
There was a problem hiding this comment.
Anything more specific?
There was a problem hiding this comment.
It varies.. you can receive Tuple[str, int] or Tuple[str, int, int, int]
| loop = asyncio.get_event_loop() | ||
|
|
||
| infos = await loop.getaddrinfo(hostname, port, type=socket.SOCK_DGRAM) | ||
| _, local_addr, remote_addr = _utils.udp_socket_parameters(infos[0][4]) |
There was a problem hiding this comment.
Might be worth an intermediate variable for this obscure infos[0][4] thingy?
|
As @tomchristie mentioned in the issue, I'm not sure if we should be adding this as experimental to HTTPCore itself right away, or host the code separately? Perhaps we could start with a gist (although somewhat lengthy) that completely ignores any connection pooling, and just provides a fully functional standalone I'd also be curious about some docs draft, see how we'd frame this for users? |
|
I'm not sure "hosting it externally" makes much sense, there has been an I'm not sure I understand the rationale behind wanting to remove support for connection pooling, the behaviour is almost identical to HTTP/2? |
|
My suggestion to set pooling aside for now was to make separate hosting easier. :) The difference with your aioquic proof of concept would be that we'd be documenting HTTP/3 experimental support anyway (so even if that's as a separate thing we'd be targeting traffic at it). Honestly though, given how self-contained and additive this pull request is (and will likely remain), I'm personally pretty open to having this as experimental in core. We accepted the AnyIO backend as a similar low-complexity additive change. And although I share the same reservations as Tom in terms getting the framing right for users (ie "you probably don't need the complexity that comes with HTTP/3"), I'm quite excited at the idea of demonstrating functional HTTP/3 support in HTTPCore/HTTPX. Would kind of prove the point that this "transport" architecture allows the project to evolve with industry trends. |
So, the behaviour with this pull request between With In contrast, setting Really what we'd like to do with HTTP/3 support is determine if support is available or not based on the AltSrv header, and only switch up to HTTP/3 where available. But that's a whole other kettle of fish. What I would like to understand first, is what are the blockers to us instead starting with an incremental approach of http3-as-a-third-party-transport-to-start-with, and being able to document something like... import httpx, aioquic
# Use HTTP/3 support.
async with httpx.AsyncClient(transport=aioquic.HTTP3Transport()) as client:
...Working from that perspective is really important to me, because there's always a huge volume of unsurfaced complexities that come along with pulling in something mega like HTTP/3 support, and the incremental approach almost always does a better job of helping thrash those out in a manageable step-by-step way. There's a big difference between us advertising that support on https://www.python-httpx.org/ vs. example code in the aioquic GitHub repo. The obvious blockers I can see would be...
|
|
OK in essence we'll just maintain a variant of the status quo: the "transport" is a demo provided in the aioquic repo. It might graduate to being shipped with aioquic in an However note that it brings us no nearer to an eventual integration in httpcore or httpx, because the two are implemented very differently. This PR demonstrates my point, compare this code to the demo code in aioquic. For for the demo I don't have any incentive to use anything looking like the eventual "UDP socket abstraction" or "timer abstraction". If it's going to be async-io only, I can keep using the higher-level |
Right, which from my POV is actually okay, because we can start with thrashing out any remaining issues in an asyncio-only context to begin with. Later once we're super happy with the state of all that and we're getting real world feedback, we can look at the next steps of a built-in integration. I'm a bit absolute on the "take the smallest steps forward possible at each point" incremental approach. Anything else always seems to come back and bite ya. Hard. |
This PR is still a very rough draft, it:
only implements asyncioStill I am able to use the example from the README to perform an HTTP/3 requests against
quic.aiortc.orgport 443.