Server-side requests/responses #1527
Replies: 15 comments
-
Hey hey, Interesting stuff, but what would be some possible use cases for this? I'm thinking a use case of a Starlette server side app where we proxy requests from ASGI through HTTPX and responses back again. Is this discussion related to making this kind of things easier? |
Beta Was this translation helpful? Give feedback.
-
So heres an example of something you might use this for... class MockTransport():
"""
A transport class that simply always returns a single given response.
"""
def __init__(self, response: Response):
self.response = response
def request(self, ...):
return self.response.raw |
Beta Was this translation helpful? Give feedback.
-
Could this be used to build the httpx-equivalent of responses / aioresponses? |
Beta Was this translation helpful? Give feedback.
-
@jcugat There's already RESPX by @lundberg which I think was intended to be such an equivalent (although I believe the API has parted ways a bit). :-) But yes this |
Beta Was this translation helpful? Give feedback.
-
True @florimondmanca , the API has parted somewhat, it's hard to keep up with the speed About the transports...latest version of I really like the idea of making the request, response and URL from httpx "easier" to use for an external lib @tomchristie . Currently I needed to have some wrappers in respx to fully support http_core "alone". |
Beta Was this translation helpful? Give feedback.
-
What's left to be done on this? I had a lot of awkward stuff going on in my custom transport that was alleviated by using a httpx.Request internally, very welcome change. I'm planning to do the same with Responses. Am I right in thinking this is already good to go? |
Beta Was this translation helpful? Give feedback.
-
Yup you're good to go here. There are some bits & pieces that we might still pursue later. For example... for accessing JSON or Form encoded data on a request instance, we might want to add Aside to self: If we were going all the way with supporting server-side requests, then we'd also want to think about supporting |
Beta Was this translation helpful? Give feedback.
-
Is there anything left related to building requests/responses from "raw" data? Like… request = httpx.Request(raw=(method, url, headers, stream, ext))
response = httpx.Response(raw=(status_code, headers, stream, ext)) I think I saw this discussed on another issue or PR, but can't remember where. I think @johtso's experiments with caching hint that there might be a use case there…? (Maybe we already support it, btw, and I'm lacking behind?) |
Beta Was this translation helpful? Give feedback.
-
Hah, please ignore that horrid code, was written in a fit of frustration at having to repeat the list of raw request value types umpteen times. We're all groovy for easily using The only things are as you mention, having to explicitly unpack the raw Also, this may just be me misunderstanding the definition of I really like the idea of the |
Beta Was this translation helpful? Give feedback.
-
I'm not sure that we want to go quite that far. (Maybe, but?) Right now we've got... def request(method, url, stream, ext):
request = httpx.Request(method=method, url=url, stream=stream)
...
response = httpx.Response(...)
return (response.status_code, response.headers.raw, response.stream, response.ext) Which is probably the right balance of:
|
Beta Was this translation helpful? Give feedback.
-
We don't really want to be in the business of passing around arbitrary stuff in the extensions. We ought to define what extensions are supported, and guide users towards not treating it as an arbitrary value store. What are you considering using it for? I can see a use case for us adding Supposing we decided to add a support minimal API for server support to In that case, there's a couple of extra bits of information we'd need to pass in addition to the
Corresponding with those we'd also want to add the following properties to request instances...
☩: Actually that's not completely true. We could feasibly be using WSGI + ASGI instead of our transport API, for the dividing line between |
Beta Was this translation helpful? Give feedback.
-
@tomchristie I wanted to include 2 things in An indication whether or not the response is from the cache. Would it be so bad to allow attaching arbitrary stuff to Requests? One use case is per request options you want to send to a custom transport. Another use case is if for example you have some kind of multi step web scraping logic that needs context, and your handling of responses is separated from where the requests are sent. The only place that context can be is on the Just brainstorming! |
Beta Was this translation helpful? Give feedback.
-
Ah interesting...
We might want to fold that all into a (Eg. stay in line with a tentative ASGI proposal along those lines... django/asgiref#135)
Yes maybe. I think we'd need to talk specifics? I can see for example that Short version of this: Just like with any other API. Adding stuff is trivial. Removing something once added is nearly impossible. So in general we should tend towards trying to keep |
Beta Was this translation helpful? Give feedback.
-
Was more of a general idea really. Potentially there could be an option to make the caching transport ignore a request, but that can also be indicated by adding a
I do feel like there's two separate issues.
|
Beta Was this translation helpful? Give feedback.
-
Going to push this into an open ended discussion now. I think we've largely resolved the points bought up here, though there's a few bits that might(?) come up later as specific issues. |
Beta Was this translation helpful? Give feedback.
-
So, not something that we need to support as a primary use-case, but something we ought to just think about a little before 1.0, is making sure that our
Request
andResponse
models can be used on the server side as well.For instance...
starlette
were able to lean heavily onhttpx
.A couple of API/implementation notes to go along with this...
URL()
should accept the raw bytes URL 4-tuple format that thehttpcore
API uses as one of it's options.Request.prepare(...)
shouldn't be called automatically on__init__
. TheClient
should call it explicitly inbuild_request()
. This ensures that we'd be able to instantiate aRequest
instance from the raw HTTP coremethod
/url
/headers/
stream` information, without having additional headers automatically generated on the model.Request.raw
,Response.raw
,Headers.raw
properties, to match up with the existingURL.raw
property.Beta Was this translation helpful? Give feedback.
All reactions