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 · 0 comments
Open
Labels
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.