You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Most web developers are familiar with the concept of middleware, which has been adopted in many HTTP routers and web frameworks. This proposal suggests officially introducing the concept of middleware into the net/http package.
Background
Middleware is a design pattern that elegantly allows the addition of cross-cutting concerns such as logging, authentication handling, or recovering from a panic, minimizing the need for multiple code contact points. It acts as a layer between the core application logic and the underlying infrastructure or components. Typically, it intercepts requests or responses and performs certain actions or transformations before passing them along to the next component in the processing pipeline.
In Go, middleware is usually provided by an HTTP router or web framework because the net/http package lacks built-in support for it. However, there are actually functions within the net/http package that essentially act as middlewares. These functions include AllowQuerySemicolons, MaxBytesHandler, StripPrefix, and TimeoutHandler. It's just that they all avoid describing themselves as middlewares. This design choice brings some downsides. For example, it's hard to modify them without breaking compatibility, like we can't add parameters to them. And since their parameters are usually different, we cannot easily form them into a handler chain, but can only call them one by one.
There are already numerous middlewares available in the community. However, most of them are designed specifically for a particular HTTP router or web framework. This is because, without the support of the standard library, it is difficult for people to design a general-purpose middleware without compromising extensibility.
This proposal aims to solve the above problems by officially introducing the middleware design pattern to the net/http package.
Proposal
I propose to add a 1-method interface named "Middleware" to the net/http package. This interface should contain only one method: func(Handler) Handler. The purpose of this method is to chain the Handler passed to it and perform some specific processing before or after the actual execution of the inputted Handler.
Additionally, for ease of use, I propose to add a func(Handler, ...Middleware) Handler to the net/http package. This function is used to associate one or more middlewares with the provided Handler and compose them into a new Handler.
Implementation
This proposal will introduce the following API changes to the net/http package:
package http
// Middleware is used to chain the [Handler].
type Middleware interface {
// ChainHTTPHandler chains the next to the returned [Handler].
//
// Typically, the returned [Handler] is a closure which does something
// with the [ResponseWriter] and [Request] passed to it, and then calls
// the next.ServeHTTP.
ChainHTTPHandler(next Handler) Handler
}
// ApplyMiddleware applies the provided middlewares to the h to form a handler
// chain, and returns a new [Handler] to execute the chain.
//
// For example, ApplyMiddleware(h, m1, m2).ServeHTTP(rw, r) is equivalent to
// m1.ChainHTTPHandler(m2.ChainHTTPHandler(h)).ServeHTTP(rw, r).
func ApplyMiddleware(h Handler, m ...Middleware) Handler { ... }
(Note that the absence of MiddlewareFunc is intentional, giving that #47487 is likely to be accepted. If #47487 is unfortunately rejected, or if this proposal is accepted before #47487, MiddlewareFunc should be added.)
For the implementation of this proposal, the difficult part is naming. For the Middleware interface, some people may use Next(next Handler) Handler as its method. However, in my opinion, "Next" is not an appropriate name, because it says almost nothing. The purpose of the method itself is to return a closure that does something and executes the next handler passed to it. Web developers often describe this behavior as "chaining". And considering the existing ServeHTTP method of the Handler, I think ChainHTTPHandler is a good choice for our Middleware. Alternatively, WithNextHandler could also be a viable option.
The text was updated successfully, but these errors were encountered:
Most web developers are familiar with the concept of middleware, which has been adopted in many HTTP routers and web frameworks. This proposal suggests officially introducing the concept of middleware into the
net/http
package.Background
Middleware is a design pattern that elegantly allows the addition of cross-cutting concerns such as logging, authentication handling, or recovering from a panic, minimizing the need for multiple code contact points. It acts as a layer between the core application logic and the underlying infrastructure or components. Typically, it intercepts requests or responses and performs certain actions or transformations before passing them along to the next component in the processing pipeline.
In Go, middleware is usually provided by an HTTP router or web framework because the
net/http
package lacks built-in support for it. However, there are actually functions within thenet/http
package that essentially act as middlewares. These functions includeAllowQuerySemicolons
,MaxBytesHandler
,StripPrefix
, andTimeoutHandler
. It's just that they all avoid describing themselves as middlewares. This design choice brings some downsides. For example, it's hard to modify them without breaking compatibility, like we can't add parameters to them. And since their parameters are usually different, we cannot easily form them into a handler chain, but can only call them one by one.There are already numerous middlewares available in the community. However, most of them are designed specifically for a particular HTTP router or web framework. This is because, without the support of the standard library, it is difficult for people to design a general-purpose middleware without compromising extensibility.
This proposal aims to solve the above problems by officially introducing the middleware design pattern to the
net/http
package.Proposal
I propose to add a 1-method interface named "Middleware" to the
net/http
package. This interface should contain only one method:func(Handler) Handler
. The purpose of this method is to chain theHandler
passed to it and perform some specific processing before or after the actual execution of the inputtedHandler
.Additionally, for ease of use, I propose to add a
func(Handler, ...Middleware) Handler
to thenet/http
package. This function is used to associate one or more middlewares with the providedHandler
and compose them into a newHandler
.Implementation
This proposal will introduce the following API changes to the
net/http
package:(Note that the absence of
MiddlewareFunc
is intentional, giving that #47487 is likely to be accepted. If #47487 is unfortunately rejected, or if this proposal is accepted before #47487,MiddlewareFunc
should be added.)For the implementation of this proposal, the difficult part is naming. For the
Middleware
interface, some people may useNext(next Handler) Handler
as its method. However, in my opinion, "Next" is not an appropriate name, because it says almost nothing. The purpose of the method itself is to return a closure that does something and executes thenext
handler passed to it. Web developers often describe this behavior as "chaining". And considering the existingServeHTTP
method of theHandler
, I thinkChainHTTPHandler
is a good choice for ourMiddleware
. Alternatively,WithNextHandler
could also be a viable option.The text was updated successfully, but these errors were encountered: