middleware

package
v1.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2022 License: Apache-2.0 Imports: 13 Imported by: 0

README

Middleware

A collections of mux / router agnostic middlewares.

All middleware takes and returns http.Handler; you can of course use http.HandlerFunc instead by casting your http.Handler with http.HandlerFunc(myHandler).

For usage examples please refer to:

Documentation

Overview

Package middleware please refer to README.md

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CSP

func CSP(handler http.Handler, config *csp.Config) http.HandlerFunc

CSP sends Content Security Policy header.

Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP https://www.html5rocks.com/en/tutorials/security/content-security-policy/

Example (AllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.CSP(http.DefaultServeMux, &csp.Config{Script: []string{csp.Self, "https://apis.google.com"}})))
Output:

Example (SingleEndpoint)
http.Handle("/foo", middleware.CSP(http.HandlerFunc(fooHandler), &csp.Config{Script: []string{csp.Self, "https://apis.google.com"}}))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func CSRF

func CSRF(headerKey string, handler http.Handler, logger CSRFLogger, ignoredPaths ...string) http.HandlerFunc

CSRF sends custom header that in turn causes the request to considered "complex" and therefore CORS will apply.

Reference: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Protecting_REST_Services:_Use_of_Custom_Request_Headers

Example (AllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.CSRF("x-my-site", http.DefaultServeMux, nil, "/health")))
Output:

Example (SingleEndpoint)
http.Handle("/foo", middleware.CSRF("x-my-site", http.HandlerFunc(fooHandler), nil))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func Cache

func Cache(handler http.Handler, cacheClient *cache.Client, generator func(*http.Request) string) http.HandlerFunc

Cache will store the response bytes into cache based on the key generated supplied.

Note: only responses with `http.StatusOK` response code will be cached

Example (TrackAllEndpoints)
cacheClient := &cache.Client{}
keyGenerator := func(req *http.Request) string {
	// use the request details to generate a unique cache key
	return req.Form.Get("ID")
}

http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.Cache(http.DefaultServeMux, cacheClient, keyGenerator)))
Output:

Example (TrackSingleEndpoint)
cacheClient := &cache.Client{}

keyGenerator := func(req *http.Request) string {
	// use the request details to generate a unique cache key
	return req.Form.Get("ID")
}

http.Handle("/foo", middleware.Cache(http.HandlerFunc(fooHandler), cacheClient, keyGenerator))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func ContentNoSniff

func ContentNoSniff(handler http.Handler) http.HandlerFunc

ContentNoSniff sends X-Content-Type-Options header.

Reference: https://msdn.microsoft.com/en-us/library/gg622941%28v=vs.85%29.aspx

Example (AllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.ContentNoSniff(http.DefaultServeMux)))
Output:

Example (SingleEndpoint)
http.Handle("/foo", middleware.ContentNoSniff(http.HandlerFunc(fooHandler)))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func Duration

func Duration(handler http.Handler, metrics MetricsClient, extraTags ...string) http.HandlerFunc

Duration will track the duration (and usage) of the method. It is based on statsD but it could be used with other metrics clients. Note: this middleware should typically be applied first (in order to run last)

Example (TrackAllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.Duration(http.DefaultServeMux, &myMetricsClient{})))
Output:

Example (TrackSingleEndpoint)
http.Handle("/foo", middleware.Duration(http.HandlerFunc(fooHandler), &myMetricsClient{}))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

Example (TrackSingleEndpointWithTag)
http.Handle("/foo", middleware.Duration(http.HandlerFunc(fooHandler), &myMetricsClient{}, "/foo"))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func DurationStatus

func DurationStatus(handler http.Handler, metrics MetricsClient, extraTags ...string) http.HandlerFunc

DurationStatus is similar to Duration but also tracks the HTTP response code (via tags) It is based on statsD but it could be used with other metrics clients. Note: this middleware should typically be applied first (in order to run last)

Example (TrackAllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.DurationStatus(http.DefaultServeMux, &myMetricsClient{})))
Output:

Example (TrackSingleEndpoint)
http.Handle("/foo", middleware.DurationStatus(http.HandlerFunc(fooHandler), &myMetricsClient{}))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

Example (TrackSingleEndpointWithTag)
http.Handle("/foo", middleware.DurationStatus(http.HandlerFunc(fooHandler), &myMetricsClient{}, "/foo"))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func HSTS

func HSTS(handler http.Handler, maxAge time.Duration, excludeSubDomains ...bool) http.HandlerFunc

HSTS sends HTTP Strict Transport Security header.

By default the "includeSubDomains" is added; which is recommended.

Reference: https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet

Example (AllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.HSTS(http.DefaultServeMux, 365*24*time.Hour)))
Output:

Example (SingleEndpoint)
http.Handle("/foo", middleware.HSTS(http.HandlerFunc(fooHandler), 365*24*time.Hour))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func InputBody

func InputBody(handler http.Handler, dto interface{}, client ...InputBodyLogger) http.HandlerFunc

InputBody will attempt to populate a copy of the supplied struct and store it in request context.

Example
package main

import (
	"log"
	"net/http"

	"github.com/corsc/go-commons/http/middleware"
)

func main() {
	http.Handle("/foo", middleware.InputBody(http.HandlerFunc(fooHandler), &fooRequestDTO{}))

	log.Fatal(http.ListenAndServe(":8080", nil))
}

// request format for foo
type fooRequestDTO struct {
	Name  string `json:"name"`
	Email string `json:"email"`
	Age   int    `json:"age"`
}
Output:

func InputBodyDTO

func InputBodyDTO(req *http.Request) interface{}

InputBodyDTO returns the populated DTO for this request (or nil). NOTE: this method should be used in conjunction with `InputBody()`

func InputBodySetDTO

func InputBodySetDTO(req *http.Request, dto interface{}) *http.Request

InputBodySetDTO sets the supplied DTO into the context. This method will generally be used only during testing.

func OutputJSON

func OutputJSON(resp http.ResponseWriter, dto interface{}) error

OutputJSON will attempt to encode the supplied DTO into JSON bytes and add to the response. On success it will add status header of HTTP 200 (OK)

Example
package main

import (
	"log"
	"net/http"

	"github.com/corsc/go-commons/http/middleware"
)

func main() {
	http.Handle("/foo", http.HandlerFunc(fooJSONHandler))

	log.Fatal(http.ListenAndServe(":8080", nil))
}

// handle foo JSON requests
func fooJSONHandler(resp http.ResponseWriter, _ *http.Request) {
	outputDTO := &fooResponseDTO{
		Name: "my name",
	}

	_ = middleware.OutputJSON(resp, outputDTO)
}

// request format for foo
type fooResponseDTO struct {
	Name  string `json:"name"`
	Email string `json:"email"`
	Age   int    `json:"age"`
}
Output:

func Panic

func Panic(handler http.Handler, logger ...func(format string, args ...interface{})) http.HandlerFunc

Panic will catch all panics, optionally log the stack trace and set the response to `http.StatusInternalServerError`

Example (AllEndpoints)
http.Handle("/foo", http.HandlerFunc(panicHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.Panic(http.DefaultServeMux, log.Printf)))
Output:

Example (SingleEndpoint)
http.Handle("/foo", middleware.Panic(http.HandlerFunc(panicHandler), log.Printf))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func Version

func Version(handler http.Handler, header string, version string) http.HandlerFunc

Version will apply a version header to all responses

Example (AllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.Version(http.DefaultServeMux, "X-Version", "1.2.3")))
Output:

Example (SingleEndpoint)
http.Handle("/foo", middleware.Version(http.HandlerFunc(fooHandler), "X-Version", "1.2.3"))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

func XXSS

func XXSS(handler http.Handler, block ...bool) http.HandlerFunc

XXSS sends X-XSS-Protection response header

By default the "mode=block" is not sent.

Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection

Example (AllEndpoints)
http.Handle("/foo", http.HandlerFunc(fooHandler))

log.Fatal(http.ListenAndServe(":8080", middleware.XXSS(http.DefaultServeMux, true)))
Output:

Example (SingleEndpoint)
http.Handle("/foo", middleware.XXSS(http.HandlerFunc(fooHandler), true))

log.Fatal(http.ListenAndServe(":8080", nil))
Output:

Types

type CSRFLogger

type CSRFLogger interface {
	// log requests that fail CSRF check
	BadRequest(req *http.Request, msg string, args ...interface{})
}

CSRFLogger allows for logging

type InputBodyLogger

type InputBodyLogger interface {
	// Log bad requests
	BadRequest(req *http.Request, msg string, args ...interface{})

	// Log request bodies
	Request(req *http.Request, body []byte)
}

InputBodyLogger allows for logging

type MetricsClient

type MetricsClient interface {
	Duration(key string, start time.Time, tags ...string)
}

MetricsClient allows for tracking the endpoint via StatsD or similar

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL