Skip to content
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

proposal: net/http: add `RoundTripperFunc` and `Middleware` for server & client #38479

Open
leaxoy opened this issue Apr 16, 2020 · 3 comments
Open
Labels
Projects
Milestone

Comments

@leaxoy
Copy link

@leaxoy leaxoy commented Apr 16, 2020

Now, in net/http, for server side, we have Handler & HandlerFunc, HandlerFunc is the convenient way for user to define new handler, but in client side, we only have RoundTripper, so I proposal to add RoundTripperFunc to net/http.

// RoundTripperFn implement http.RoundTripper for convenient usage.
type RoundTripperFunc func(request *http.Request) (*http.Response, error)
func (fn RoundTripperFunc) RoundTrip(request *http.Request) (*http.Response, error) { return fn(request) }

With this new type, we can easily implement RoundTripper interface.

In modern web application, middleware pattern is widely used. With Middleware we can add more action before/after handler/request call.
For the server side, we can define Middleware or similar:

type Middleware interface {
	Next(h http.Handler) http.Handler
}

// MiddlewareFn support wrap function with same signature as Middleware.
type MiddlewareFn func(h http.Handler) http.Handler

func (fn MiddlewareFn) Next(h http.Handler) http.Handler { return fn(h) }

// and compose chains of middleware
// ComposeInterceptor compose interceptors to given http.RoundTripper
func ComposeInterceptor(rt http.RoundTripper, interceptors ...Interceptor) http.RoundTripper {
	if len(interceptors) == 0 {
		return rt
	}
	return ComposeInterceptor(interceptors[0].Next(rt), interceptors[1:]...)
}

For the client side, we define Interceptor or similar:

type Interceptor interface {
	Next(fn http.RoundTripper) http.RoundTripper
}

// InterceptorFn implement Interceptor for convenient usage.
type InterceptorFn func(rt http.RoundTripper) http.RoundTripper

func (fn InterceptorFn) Next(rt http.RoundTripper) http.RoundTripper { return fn(rt) }

// and a function compose chains of interceptor
func ComposeInterceptor(rt http.RoundTripper, interceptors ...Interceptor) http.RoundTripper {
	if len(interceptors) == 0 {
		return rt
	}
	return ComposeInterceptor(interceptors[0].Next(rt), interceptors[1:]...)
}

All the above are not necessary, but can reduce and simplify user's boilerplate code.
Please consider this proposal.

The original code is middleware, interceptor & RoundTripperFunc

@bradfitz bradfitz changed the title net/http: add `RoundTripperFunc` and `Middleware` for server & client proposal: net/http: add `RoundTripperFunc` and `Middleware` for server & client Apr 16, 2020
@gopherbot gopherbot added this to the Proposal milestone Apr 16, 2020
@gopherbot gopherbot added the Proposal label Apr 16, 2020
@instabledesign
Copy link

@instabledesign instabledesign commented Jul 23, 2020

I've done a similare library
https://github.com/gol4ng/httpware

@bradfitz
Copy link
Contributor

@bradfitz bradfitz commented Oct 7, 2020

I definitely want the HTTP client to be composable like the server is and was assuming that would happen as part of the new HTTP client (#23707). I don't think there's a clean way to add it to the existing client so I'm not very excited about this particular proposal.

@leaxoy
Copy link
Author

@leaxoy leaxoy commented Oct 8, 2020

I definitely want the HTTP client to be composable like the server is and was assuming that would happen as part of the new HTTP client (#23707). I don't think there's a clean way to add it to the existing client so I'm not very excited about this particular proposal.

It's sound good to me, is there any plan on that issue.

@ianlancetaylor ianlancetaylor added this to Incoming in Proposals Jan 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Proposals
Incoming
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants