requests
requests copied to clipboard
What about `before_request` hook?
Didn't find a correct place where to post my question.
Hook system is a cool idea but I'm wondered why there is no some kind of 'before_request' hook?
Let's assume I want to create requests.Session, and do some preparation steps for upcoming requests (like body formatting or simply log what URL and method). One of possible ways to do that is to override requests.Session.request method, but adding one more hook sounds more reasonable. It is possible to put it here https://github.com/requests/requests/blob/master/requests/sessions.py#L623
Is there any reason of not having this hook? Or is there some appropriate way to execute some piece of code before each request within Session?
We had many more hooks pre-1.0. They were removed. There hasn't been enough demand to add them back since. Further, as you might have read before creating this issue, Requests is under a feature-freeze so we will likely not accept this feature request
yeah, we used to have this.
We can consider it for 3.0 — can you explain your use case?
Here is an example, how I would implement some common logic for all requests within session without hooks by overriding requests.Session.request method
class CustomSession(requests.Session):
session = None
_base_url = None
def __init__(self, base_url):
requests.Session.__init__(self)
self._base_url = base_url
def request(self, method, url, *args, **kwargs):
"""
Overriden method of requests.Session.request.
You may add any request preprocessing or response postprocessing logic here.
"""
full_url = self._base_url + url # I want to make requests without specifying base url
LOGGER.debug("Sending request %s %s", method, full_url) #
return requests.Session.request(self, method, full_url, *args, **kwargs)
Here is how it can be used
session = CustomSession('http://test.com')
session.get('/v1/something')
session.delete('/v1/something/23')
session.post('/v1/something/23')
I think we can have some kind of hooks to do the same logic. That can be functions or callable objects like this :
class BaseURLHook(object):
def __init__(self, base_url):
self.base_url = base_url
def __call__(self, request, *args, **kwargs):
request.url = self.base_url + request.url
return request
def log_request_hook(request, *args, **kwargs):
LOGGER.debug("Sending request %s %s", request.method, request.url)
....
hooks = {
'before_request': [
BaseURLHook('http://test.com'),
log_request_hook
]
}
session = request.Session()
session.hooks = hooks
Having such kind of hooks can allow to perform preprocessing of request and postprocessing of response without overriding requests.Session methods.
I hope I clarified my idea :)
But probably hooks is a wrong abstraction for this purposes. What I'm thinking about is some king of Request Factory, that provides Prototypes of requests (it can be an extension of PreparedRequest).
This could also be useful for adding distributed tracing support to requests. I had thought about using a TransportAdapter for that though, so really before_request isn't entirely necessary
I have a vary similar idea about base url. I'm not sure if there is a need to have before_request hook, but it would be really useful to have base url.
Here is example:
s = requests.Session()
s.auth = ('user', 'pass')
s.base = 'https://httpbin.org'
s.get('/headers')
Under the hood, if base is set, then for each request, urljoin would be called.
I think, that would be really useful.
Now in most cases, I must configure base url somewhere else and pass it everywhere and construct urls manually.
Howdy.
If you support the concept of hooks in the requets API, they should be comprehensive and allow a lot of control over how the API works. So far only a "response" hook is partially useful.
My use case: I want to run the API in either capturing mode (write all responses to disk, for that the response hook works) or read back mode (for this case I'd need a "request" hook before the request is sent to produce a response. And/or, a global hook when a session is created so I can override the HTTPAdapters to an adapter that reads back from the cache.
Thank you.
In an effort to clean up the issue tracker to only have issues that are still relevant to the project we've done a quick pass and decided this issue may no longer be relevant for a variety of potential reasons, including:
- Applies to a much older version, unclear whether the issue still applies.
- Change requires a backwards incompatible release and it's unclear if the benefits are worth the migration effort from the community.
- There isn't a clear demand from the community on the change landing in Requests.
If you think the issue should remain open, please comment so below or open a new issue and link back to the original issue. Again, thank you for opening the issue and for the discussion, it's much appreciated.