-
-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use the Client interface to represent an HTTP client #70
Conversation
Github is having problems today, so it's eating my comments. |
Interesting. It feels sort of redundant with Transport/RoundTripper, but that’s a problem with the standard library (if there’s ever a standard library v2, it should turn http.Client into just a middleware RoundTripper that adds redirect following etc onto a base RoundTripper instead of having two basically identical interfaces with overlapping concerns). I don't like having setting the Transport fail silently. It should explicitly refuse to connect if given contradictory instructions. The question is whether it should fail by returning an error or panicking. Panicking is more “correct” because setting contradictory options is a programmatic failure, not a runtime failure, but it’s also pretty gross, and I don’t like it. I think the simpler option that would let us sidestep the question of failing transports is to have a function like this: // Doer is an interface with a Do method.
// It exists for compatibility with other libraries.
// Users should prefer Transport,
// because Do is a wrapper around http.Client
// which has higher level concerns.
type Doer interface {
Do(req *http.Request) (*http.Response, error)
}
// DoerTransport converts a Doer into a Transport (http.RoundTripper).
func DoerTransport(cl Doer) Transport {
return RoundTripFunc(func (req *http.Request) (*http.Response, error) {
return cl.Do(req)
})
} Is there some reason this wouldn’t work with your library? |
The problem with using Quoting from the documentation, "RoundTrip executes a single HTTP transaction" (and is therefore the wrong place to plug concerns like retries), and "RoundTrip should not attempt to handle higher-level protocol details such as redirects, authentication, or cookies" (which are all tasks that are anyway already handled via the Moreover, I should have read the contributing guidelines and started a conversation first, apologies. I just noticed that #56 would be a good match.
I think there are no good options at this point. I'm in favour for panicking, since setting both a RoundTripper and a custom client that is not an |
I think the docs are a little muddled and out of date. If you read the code for http.Client.Do, all it does is handle retries and apply a CookieJar. It really should just be a middleware RoundTripper, but the Go team is stuck with their old architecture because of the Go 1 guarantee. There are several libraries that handle retries as an http.RoundTripper, such as https://github.com/ybbus/httpretry#modify--customize-the-roundtripper-httptransport, and under the hood, the Google OAuth RoundTripper issues multiple requests (because that's how OAuth works). |
These are all good examples in favour of RoundTrippers as substitute, higher-level HTTP clients. I think your proposal of converting a |
Take a look at v0.23.3-alpha1 and see if it works for your usecase. |
It looks good! Thanks a lot for taking care of this, it will make using this library so much easier for me. I will close this PR, as the change is already in your own. |
Instead of using
*http.Client
directly, it would be nice ifrequests
used an interface to represent an HTTP client. This allows the user to plug different implementation of the client that implement cross-cutting concerns like retries.More specifically for me, I would love to use this project to simplify some of my code, but the projects I'm working on already define and pass around interfaces like this to represent an HTTP client:
Given this prerequisites, it's impossible for me to use this library without type-casting and failing at runtime. Instead, if this PR was merged, integrating with
requests
would be a piece of cake.