-
-
Notifications
You must be signed in to change notification settings - Fork 997
Description
What is the dispatcher API, and why is it useful?...
The dispatcher is the part of the system that's responsible for actually sending the request and returning a response to the client. Having an API to override the dispatcher used by the client allows you to take complete control over that process, and switch out the default behaviour with something else.
For instance the "plug in to a WSGI app" and "plug in to an ASGI app" cases that we support are implemented as dispatcher classes, that send the request to a Python web application, rather than sending a network request.
Currently the dispatchers are considered private API, but really we'd like a public API here at some point. This issue is for discussing what we think that API should be.
Right now the API is...
def send(request: Request, timeout: Timeout = None) -> Response:
...
def close():
...Withasync equivelents for the async case.
That's actually pretty okay, but if we're looking at a public API, we ought to figure out if it's actually what we want to expose. There's a case to be made for making the dispatcher API just take plain primitive datastructures, rather than dealing with Request/Response models. That'd make for a more portable interface, that could be used in other packages without importing httpx.
That might look something like this...
def send(self, method: bytes, url: Typle[bytes, bytes, int, bytes], headers: List[Tuple[bytes, bytes]], body: ClosableIterator[bytes] = None, timeout: Timeout = None):
...
return (status_code: int, http_version: bytes, reason_phrase: bytes, headers: List[Tuple[bytes, bytes]], body: ClosableIterator[bytes])
def close():
...Both the request and response bodies would be byte-iterable, closable interfaces (or byte async-iterable, closable interfaces). Everything else would be plain ol' Python datastructures.
Thoughts:
- It's feasible that
urlcould be defined as a tuple or url components instead, so that we can keep pass a parsed url objects from the client to a dispatcher interface? **Update: I've tweaked the interface to describe it that way around, as "scheme", "host", "port", "full_path". - We do need to have the timeout be part of the dispatch interface, since we want to be able to support configured-per-request timeout values - I'd guess we'd need to define that as an optional four-tuple of connect/read/write/pool float timeout values.
- We might want to think about defining expected exception types.
- There's no support for HTTP trailing headers in this interface. Perhaps we don't care about that, or could the
ContentStream.close()perhaps optionally return a list of headers, maybe?
Something that'd potentially be interesting about defining this interface in a really strict, primitive datastructures way, would be that we could pull out our dispatcher implementations into a really tightly scoped package httpcore, that'd just provide the plain network dispatchers, without any client smarts around them. (Interesting amongst other things because it'd provide a nice just-the-network-backend for other client libs to potentially use too / switch too.)
I think a useful first take onto all of this might? be an exploratory pull request that switches us over to using a plainer dispatch API, just to get a feel for how that'd look. A very first initial take on that could still use the URL, ContentStream, and Timeout primitives.
(This also potentially ties in with whatever the hip team's plans are. For instance, right now we're using our own dispatcher implementation - currently in the async case only, but planned for both cases - but we would have the option of using the hip backend, once it's available. It's not obvious to me if we'd want to do that, or if we'd prefer to continue with our existing backend, which is looking pretty nice now, but it could be a point of collaboration, or something to discuss.)
Alternately, we might decide that this falls into architecture astronauting territory, and that the existing API is "just fine thankyouverymuch".