-
-
Notifications
You must be signed in to change notification settings - Fork 971
Description
Our yardstick for 1.0 has generally been to achieve feature parity with requests, plus the following additional support...
- Sync + Async support.
- HTTP/2 support.
- Strict timeout defaults.
- Type annotations throughtout.
- Streaming multipart uploads.
Something we've so far omitted is retires=..., which are not included in either the requests QuickStart guide, or in the Advanced Usage section. However requests does have some retry support, can be enabled by mounting a custom adapter... https://requests.readthedocs.io/en/master/api/#requests.adapters.HTTPAdapter
I'd suggest that if we do want to add retry support we should start off by doing so in a limited fashion, and only provide a simply retries=<int> argument on the client, which matches the same "only retry on connection failures" behaviour that requests defaults to for integer retry arguments.
That doesn't necessarily preclude that we could consider more complex retry behaviour at some point in the future, but I'm prefer we push back on that for as long as possible.
Having more dials for configuration is something we should generally avoid where possible. Also, we've gone to a great deal of effort over nicely spec'ing our Transport API, and it's perfectly feasible for developers to build against that to deal with any more complex behaviours that they'd like to see.
With all that in mind, I'd suggest something we might consider would be...
class Client(..., retries: int=0):
...With the implementation handled inside our _send_single_request method. Something like...
transport = self._transport_for_url(request.url)
retries = self.retries
while True:
with map_exceptions(HTTPCORE_EXC_MAP, request=request):
try:
(
http_version,
status_code,
reason_phrase,
headers,
stream,
) = transport.request(
request.method.encode(),
request.url.raw,
headers=request.headers.raw,
stream=request.stream,
timeout=timeout.as_dict(),
)
except (httpcore.ConnectError, httpcore.ConnectTimeout):
if retries <= 0:
raise
retries -= 1
response = Response(
status_code,
http_version=http_version.decode("ascii"),
headers=headers,
stream=stream, # type: ignore
request=request,
)
self.cookies.extract_cookies(response)
status = f"{response.status_code} {response.reason_phrase}"
response_line = f"{response.http_version} {status}"
logger.debug(f'HTTP Request: {request.method} {request.url} "{response_line}"')
return responseI'm still not 100% sure that we want this, but perhaps this is a decent low-impact feature.
Any thoughts?
