middleware

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2021 License: MIT Imports: 17 Imported by: 2

Documentation

Overview

The middleware package defines what a middleware is in trails and a set of basic middlewares.

The available middlewares are: - CORS - CurrentUser - ForceHTTPS - InjectSession - LogRequest - RateLimit - RequestID

Due to the amount of configuration required, middleware does not provide a default middleware chain Instead, the following can be copy-pasted:

vs := middleware.NewVisitors()
adpts := []middleware.Adapter{
	middleware.RateLimit(vs),
	middleware.ForceHTTPS(env),
	middleware.RequestID(requestIDKey),
	middleware.LogRequest(log),
	middleware.InjectSession(sessionStore, sessionKey),
	middleware.CurrentUser(responder, userStore, userKey),
}

Index

Constants

View Source
const IpAddrCtxKey = "trails/middleware/ip-address" // TODO(dlk): change to key provided by app?

Variables

This section is empty.

Functions

func Chain

func Chain(handler http.Handler, adapters ...Adapter) http.Handler

Chain glues the set of adapters to the handler.

func GetIPAddress

func GetIPAddress(hm http.Header) string

GetIPAddress parses "X-Forward-For" and "X-Real-Ip" headers for the IP address from the request.

GetIPAddress skips addresses from non-public ranges.

func NoopAdapter

func NoopAdapter(h http.Handler) http.Handler

NoopAdapter is a pass-through Adapter, often returned by Adapters available in this package when they are misconfigured.

func ReportPanic

func ReportPanic(env string) func(http.HandlerFunc) http.HandlerFunc

ReportPanic encloses the env and returns a function that when called, wraps the passed in http.HandlerFunc in sentryhttp.HandleFunc in order to recover and report panics.

Types

type Adapter

type Adapter func(http.Handler) http.Handler

An Adapter enables chaining middlewares together.

func CORS

func CORS(base string) Adapter

CORS sets "Access-Control-Allowed" style headers on a response. The handler including this middleware must also handle the http.MethodOptions method and not just the HTTP method it's designed for.

If base is it's zero-value, NoopAdapter returns and this middleware does nothing.

func CurrentUser

func CurrentUser(d *resp.Responder, store UserStorer, sessionKey, userKey ctx.CtxKeyable) Adapter

CurrentUser pulls the User out of the session.UserSessionable stored in the *http.Request.Context.

A *resp.Responder is needed to handle cases a CurrentUser cannot be retrieved or does not have access.

CurrentUser checks the MIME types of the *http.Request "Accept" header in order to handle those cases. CurrentUser checks whether the "Accept" MIME type is "application/json" and write a status code if so. If it isn't, CurrentUser redirects to the Responder's root URL.

func ForceHTTPS

func ForceHTTPS(env string) Adapter

ForceHTTPS redirects HTTP requests to HTTPS if the environment is not "development".

The "X-Forwarded-Proto" is used to check whether HTTP was requested due to a trails application running behind a proxy.

TODO(dlk): configurable headers to check.

func InjectIPAddress

func InjectIPAddress() Adapter

InjectIPAddress grabs the IP address in the *http.Request.Header and promotes it to *http.Request.Context under IpAddrCtxKey.

func InjectSession

func InjectSession(store session.SessionStorer, key ctx.CtxKeyable) Adapter

InjectSession stores the session associated with the *http.Request in *http.Request.Context.

If store or key are their zero-values, NoopAdapter returns and this middleware does nothing.

func LogRequest

func LogRequest(ls logger.Logger) Adapter

LogRequest logs the request's method, requested URL, and originating IP address using the enclosed implementation of logger.Logger.

LogRequest scrubs the values for the following keys: - password

if logger.Logger is nil, NoopAdapter returns and this middleware does nothing.

func RateLimit

func RateLimit(visitors *Visitors) Adapter

RateLimit encloses the Visitors map and serves the http.Handler

NOTE: cribbed from https://www.alexedwards.net/blog/how-to-rate-limit-http-requests

If we need anything more sophisticated, check https://github.com/didip/tollbooth

func RedirectAuthed

func RedirectAuthed(key ctx.CtxKeyable) Adapter

RedirectAuthed returns a middleware.Adapter that checks whether a user is authenticated that is set in the *http.Request.Context given the key.

context and so can be redirected to their HomePath or hands off to the next part of the middleware chain.

func RedirectUnauthed

func RedirectUnauthed(key ctx.CtxKeyable, loginUrl, logoffUrl string) Adapter

/ RedirectUnauthed returns a middleware.Adapter that checks whether a user is authenticated, that is set in the *http.Request.Context given the key.

If not, the user is redirected to the loginUrl with a "next" query param added; otherwise, hands off to the next part of the middleware chain.

func RequestID

func RequestID(key ctx.CtxKeyable) Adapter

RequestID adds a uuid to the request context.

If key is nil, then NoopAdapter returns and this middleware does nothing.

type User

type User interface {
	HasAccess() bool
	HomePath() string
}

type UserStorer

type UserStorer interface {
	GetByID(id uint) (User, error)
}

type Visitor

type Visitor struct {
	LastSeen time.Time
	Limiter  *rate.Limiter
}

A Visitor tracks a rate limiter and last seen time.

type Visitors

type Visitors struct {
	sync.Mutex
	// contains filtered or unexported fields
}

A Visitors maps a Visitor to an IP address.

func NewVisitors

func NewVisitors() *Visitors

func (*Visitors) Fetch

func (vs *Visitors) Fetch(ip string) Visitor

Fetch retrieves the Visitor for the given ip creating a new Visitor if not seen.

Newly created visitors are limited to 5 requests every second with bursts of up to 20.

Jump to

Keyboard shortcuts

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