Repository navigation
Closed
Labels
Description
Now that we've got a really tightly spec'ed Transport API, one useful thing we can do for the ecosystem is show our users how to do nifty things like adding in extra behaviour.
For example, here's a simple implementation of a throttle...
class ThrottleTransport:
"""
A custom httpx transport that adds some basic rate-throttling functionality.
transport = ThrottleTransport('100/minute', **connection_pool_options)
client = httpx.Client(transport=transport)
"""
def __init__(self, throttle, **kwargs):
self.pool = httpcore.SyncConnectionPool(**kwargs)
self.history = []
# Parse the thottle, which should be a string, like '100/minute'.
count, _, duration = throttle.partition('/')
self.max_in_history = int(count)
self.cutoff = {'second': 1.0, 'minute': 60.0, 'hour': 3600.0}[duration]
def request(method, url, headers, stream, timeout):
now = time.time()
while len(self.history) >= self.max_in_history:
expiry = now - self.cutoff
# Expiry old entries in the history.
self.history = [timestamp for timestamp in self.history if timestamp > expiry]
# Sleep for a bit if we've exceeded the throttle rate.
if len(self.history) >= self.max_in_history:
time.sleep(0.1)
now = time.time()
self.history.append(now)
return self.pool.request(method, url, headers, stream, timeout)
def close(self):
self.pool.close()I've not tested this out, just looks about right to me. Might well be worth making sure I've got this right, and then adding it as an example in the docs?
Slightly dependant on #983, since really users need that in order to configure the httpcore pool nicely.
Reacted by elonzh
Activity
[-]More advance Transport API example.[/-][+]More advanced Transport API example.[/+]florimondmanca commentedon May 24, 2020
I'm thinking it might also be possible to build features like retries (#784) and others using this sort of style.
However, I'm still not certain these shouldn't belong to some sort of "transport wrapper" concept…
E.g. throttling (or retries, or any sort of "modify the request/response flow" thing) should be fairly independent of how the actual request is made - we can also want to throttle requests to ASGI apps, over UDS, to a proxy, etc.
(And… this is when I come back again with my "middleware" idea? 😅 #345)
lazka commentedon May 29, 2020
Transparent caching would also be nice imho, using HTTP cache headers and connecting it to something like https://github.com/argaen/aiocache
stale commentedon Feb 20, 2022
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.