Documentation
¶
Overview ¶
Package middleware makes it easy to chain net/http middleware in Go
Index ¶
- func AllHeadersPresent(requiredHeaders http.Header, requestHeaders http.Header) bool
- func DefaultValidation(params HmacParams) func(r *http.Request, message []byte) (bool, error)
- func FilterHeaders(headers http.Header) func(http.Handler) http.Handler
- func GithubValidation(params HmacParams) func(r *http.Request, message []byte) (bool, error)
- func HmacFilter(params HmacParams) func(http.Handler) http.Handler
- func IPFilter(ipRanges []string, header string) func(http.Handler) http.Handler
- type HmacParams
- type Middleware
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AllHeadersPresent ¶
func DefaultValidation ¶
func GithubValidation ¶
func HmacFilter ¶
func HmacFilter(params HmacParams) func(http.Handler) http.Handler
Example ¶
package main import ( "bytes" "fmt" "github.com/seb-ehm/middleware" "log" "net/http" ) func main() { mux := http.NewServeMux() //Some handler that prints both to stdout and the http response handler := func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hi!") } githubSignature := middleware.HmacFilter(middleware.HmacParams{Provider: "github", Secret: "ThisIsMySecret"}) authenticated := middleware.New().Append(githubSignature) mux.Handle("/authenticated", authenticated.ApplyToFunc(handler)) go func() { log.Fatal(http.ListenAndServe("localhost:9194", mux)) }() client := &http.Client{} validRequest, _ := http.NewRequest("POST", "http://localhost:9194/authenticated", bytes.NewBuffer([]byte("ThisIsARequest"))) validRequest.Header.Add("X-Hub-Signature", "sha1=8c08e9b7e2bdb4d87982f40d6bf6d36c0d0caab4") resp, _ := client.Do(validRequest) fmt.Println(resp.Status) invalidRequest, _ := http.NewRequest("POST", "http://localhost:9194/authenticated", bytes.NewBuffer([]byte("ThisIsARequest"))) invalidRequest.Header.Add("X-Hub-Signature", "sha1=1234") resp, _ = client.Do(invalidRequest) fmt.Println(resp.Status) }
Output: 200 OK 403 Forbidden
func IPFilter ¶
Example ¶
mux := http.NewServeMux() //Some handler that prints both to stdout and the http response handler := func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hi!") } allowSomeIP := middleware.IPFilter([]string{"123.240.189.1/32"}, "") noLocalhost := middleware.New().Append(allowSomeIP) allowLocalhost := middleware.IPFilter([]string{"localhost"}, "") localhost := middleware.New().Append(allowLocalhost) allowLocalhostInHeader := middleware.IPFilter([]string{"localhost"}, "X-FORWARDED-FOR") localhostInHeader := middleware.New().Append(allowLocalhostInHeader) mux.Handle("/nolocalhost", noLocalhost.ApplyToFunc(handler)) mux.Handle("/localhost", localhost.ApplyToFunc(handler)) mux.Handle("/localhostinheader", localhostInHeader.ApplyToFunc(handler)) go func() { log.Fatal(http.ListenAndServe("localhost:9192", mux)) }() _, status := GetWebsite("http://localhost:9192/nolocalhost") fmt.Println(status) content, _ := GetWebsite("http://localhost:9192/localhost") fmt.Println(content) content, _ = GetWebsiteWithHeader("http://localhost:9192/localhostinheader", "X-FORWARDED-FOR", "127.0.0.1") fmt.Println(content)
Output: 403 Forbidden Hi! Hi!
Types ¶
type HmacParams ¶
type Middleware ¶
Middleware is a type alias for the typical signature of a Go net/http middleware
Example ¶
package main import ( "fmt" "io/ioutil" "log" "net/http" "github.com/seb-ehm/middleware" ) // MiddlewareA is an example of a direct definition of a middleware. // It uses a cast to http.HandlerFunc to enable its own ServeHTTP function func MiddlewareA(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("Calling A") next.ServeHTTP(w, r) }) } // Greeting is an example of a middleware that uses a struct to keep state // and an explicit definition of a ServeHTTP function to be useable as http.Handler type Greeting struct { next http.Handler message string } // ServeHTTP prints both to the response body and stdout and calls the next middleware afterwards func (g Greeting) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, g.message) g.next.ServeHTTP(w, r) } // GetGreeting is a factory function to generate a handler that prints a certain message func GetGreeting(message string) func(http.Handler) http.Handler { fn := func(next http.Handler) http.Handler { return Greeting{next, message} } return fn } func GetWebsite(url string) (string, string) { resp, err := http.Get(url) defer resp.Body.Close() html, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } return string(html), resp.Status } func GetWebsiteWithHeader(url string, headerName string, headerValue string) (string, string) { client := &http.Client{} request, _ := http.NewRequest("GET", url, nil) request.Header.Add(headerName, headerValue) resp, err := client.Do(request) defer resp.Body.Close() html, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } return string(html), resp.Status } func main() { mux := http.NewServeMux() //Some handler that prints to the http response handler := func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hi!") } //Create two middlewares that output different greetings hello := GetGreeting("Hello!") namaste := GetGreeting("Namaste!") //Use middleware.New() as start of a new middleware chain greetings := middleware.New().Append(hello) greetings = greetings.Append(namaste) //Instead of using middleware.New(), any existing handler can be explicitely cast to type Middleware //to start a chain direct := middleware.Middleware(namaste).Append(hello) //Several middlewares can be assembled at once assembly := middleware.Assemble(hello, namaste, hello, namaste) //A middleware can be prepended to the beginning of the middleware stack assembly = assembly.Prepend(hello) //Because of the no-op ServeHTTP implementation, any middleware can be used //in a mux without an explicit final handler mux.Handle("/greetings", greetings) mux.Handle("/direct", direct) //middleware can also be applied to a final handler mux.Handle("/assembly", assembly.ApplyToFunc(handler)) go func() { log.Fatal(http.ListenAndServe("localhost:9191", mux)) }() content, _ := GetWebsite("http://localhost:9191/greetings") fmt.Println(content) content, _ = GetWebsite("http://localhost:9191/direct") fmt.Println(content) content, _ = GetWebsite("http://localhost:9191/assembly") fmt.Println(content) }
Output: Hello! Namaste! Namaste! Hello! Hello! Hello! Namaste! Hello! Namaste! Hi!
func Assemble ¶
func Assemble(middlewares ...Middleware) Middleware
Assemble can be used to chain an arbitrary number of middlewares
middlewares := middleware.Assemble(middlewareA, middlewareB, middlewareC)
func New ¶
func New() Middleware
New creates a new middleware that does nothing by itself, but can be used as a starting point for a chain of middlewares:
middleware := middleware.New() middleware.Append(someMiddleware)
func (Middleware) Append ¶
func (m Middleware) Append(other Middleware) Middleware
Append adds another middleware to the end of the middleware stack. Given two middlewares that print greetings to stdout:
hello := getGreeting("Hello!") namaste := getGreeting("Namaste!")
Using them as follows:
mux := http.NewServeMux() greetings := middleware.New().Append(hello) greetings = greetings.Append(namaste) mux.Handle("/greetings", greetings(middleware.End())
Will result in the following output:
Hello! Namaste!
func (Middleware) ApplyToFunc ¶
func (m Middleware) ApplyToFunc(fun http.HandlerFunc) http.Handler
ApplyToFunc is a convenience function to apply middleware to a HandlerFunc:
mux := http.NewServeMux() handler := func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi!") } middlewares := := middleware.Assemble(middlewareA, middlewareB, middlewareC) mux.Handle("/endpoint", middlewares.ApplyToFunc(handler))
func (Middleware) Prepend ¶
func (m Middleware) Prepend(other Middleware) Middleware
Prepend adds another middleware to the beginning of the middleware stack. Given two middlewares that print greetings to stdout:
hello := getGreeting("Hello!") namaste := getGreeting("Namaste!")
Using them as follows:
mux := http.NewServeMux() greetings := middleware.New().Append(hello) greetings = greetings.Prepend(namaste) mux.Handle("/greetings", greetings(middleware.End())
Will result in the following output:
Namaste! Hello!
func (Middleware) ServeHTTP ¶
func (m Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements the http.Handler interface with a no-op, thus any middleware can be used as a handler in a mux without an explicit final handler.
mux := http.NewServeMux() mux.Handle("/endpoint", someMiddleware)