Categorygithub.com/tiny-go/middleware
modulepackage
1.1.0
Repository: https://github.com/tiny-go/middleware.git
Documentation: pkg.go.dev

# README

go-middleware

GoDoc License [![Build Status][circleci-badge]][circleci-link] Report Card GoCover

Golang HTTP middleware

Installation

Since go-middleware is an open source project and repository is public you can simply install it with go get:

$ go get github.com/tiny-go/middleware

Currently available middleware

  • BodyClose - closes request body for each request
  • ContextDeadline - sets request timeout (demands additional logic in your app)
  • PanicRecover - catches the panics inside our chain, can be used as error handler (similar to try/catch) with corresponding panic handler
  • SetHeaders - provides an easy way to set response headers
  • JwtHS256 - verifies JWT (JSON Web Token) signed with HMAC signing method and parses its body to the provided receiver that is going to be available to next handlers through the request context
  • Codec - searches for suitable request/response codecs according to "Content-Type"/"Accept" headers and puts them into the context

Experimental middleware

It means that work is still in progress, a lot of things can be changed or even completely removed

  • AsyncRequest - allows to set request timeout (for HTTP request) and async timeout (for background execution), if request has not been processed during request timeout - middleware returns request ID and HTTP code 202 (Accepted). You can make a new request wtih given request ID later to obtain the result. The result can be provided only once and won't be available after that anymore. If handler did not finish its task during async timeout - middleware sends an HTTP error with code 408 (RequestTimeout) executing next async request with current request ID.

Examples

  1. Build the handler using middleware chaining functions:
  • New() - start the chain. Can accept 0 (zero) or more arguments.

  • Use() - add middleware to existing chain.

  • Then() - set the final handler (which is http.Handler).

    package main
    
    import (
    	"log"
    	"net/http"
    	"os"
    
    	"github.com/tiny-go/middleware"
    	"github.com/tiny-go/codec/driver"
    	"github.com/tiny-go/codec/driver/json"
    	"github.com/tiny-go/codec/driver/xml"
    )
    
    var (
        panicHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
    	    panic("something went wrong")
        }
    )
    
    func main() {
    	http.Handle(
    		"/",
    		middleware.
    			// with HTTP panic handler
    			New(middleware.PanicRecover(middleware.PanicHandler)).
    			Use(middleware.BodyClose).
    			Use(middleware.Codec(driver.DummyRegistry{&json.JSON{}, &xml.XML{}})).
    			Then(panicHandler),
    	)
    	log.Fatal(http.ListenAndServe(":8080", nil))
    }
    
    
  1. Build the handler with Chain() (variadic) func which accepts the next list of argument types:
  • http.Handler and everything else that implements this interface (for instance, http.HandlerFunc)

  • func(w http.ResponseWriter, r *http.Request)

  • MiddlewareFunc/func(http.ResponseWriter, *http.Request, http.Handler)

  • Middleware/func(http.Handler) http.Handler

    There is no sense to provide entire example since import and variable declaration sections are going to be the same, only main() func is going to be changed:

    func main() {
    	http.Handle(
    		"/",
    		middleware.Chain(
    			// with custom panic handler
    			middleware.PanicRecover(func(_ http.ResponseWriter, r interface{}) {
    				if r != nil {
    					log.Println(r)
    				}
    			}),
    			middleware.BodyClose,
    			panicHandler,
    		),
    	)
    	log.Fatal(http.ListenAndServe(":8080", nil))
    }
    

# Functions

AsyncRequest func creates a middleware that provides a mechanism to run the handler in a background (if HTTP request timeout was reached) and keep result until it is demanded again or result expires.
Bearer gets the bearer out of a given request object.
BodyClose is a middleware that closes the request body after each request.
Chain builds a http.Handler from passed arguments.
ClaimsFromContextTo retrieves claims from context and assigns to the provided receiver.
Codec middleware searches for suitable request/response codecs according to "Content-Type"/"Accept" headers and puts the correct codecs into the context.
ContextDeadline adds timeout to request's context.
ContextHandler reads from context.Done channel to handle deadline/timeout.
GetHandlerTask extracts current job from context.
Go function runs the handler and processes its execuion in a new goroutine.
JWT is a JSON Web token middleware that parses token with provided parser to the provided Claims receiver and puts it to the request context.
New is a Middleware constructor func.
NewBaseController is a constructor func for a basic HTTP controller.
PanicRecover returns a middleware that recovers from the panic.
RequestCodecFromContext pulls the Codec from a request context or returns nil.
RequestID is a middleware that injects a request ID into the context of each request.
RequestIDFromContext pulls request ID from the context or empty string.
RequestLimiter middleware apply concurrent request limit TODO: provide a choise either "wait" or "send error".
ResponseCodecFromContext pulls the Codec from a request context or returns nil.
SetHeaders allows to set response headers.
Throttle provides a middleware that limits the amount of messages processed per unit of time.

# Constants

StatusDone indicates that task was done.
StatusInProgress indicates that job is started but not finished yet.
StatusNoResponse is returned when request is canceled.
StatusWaiting is initial status - job is not started yet.

# Variables

DefaultTimeFormat contains default date/time layout to be used across middlewares of the package.
ErrAlreadyDone - current job has been already done.
ErrNotCompleted - current job was not completed.
ErrNotStarted - current job was not started.

# Structs

BaseController provides ability to register/unregister middleware for HTTP methods.This is a basic Controller implementation.

# Interfaces

Claims interface.
Codecs represents any kind of codec registry, thus it can be global registry or a custom list of codecs that is supposed to be used for particular route.
Controller represents simple HTTP controller containing middleware for each method.
HandlerTask represents sync/async handler task.
JWTParser interface is responsible for token validation, meanwhile it parses token to the provided receiver.

# Type aliases

ClaimsFactory is a func that returns a new custom claims when called.
JobStatus represents the status of asynchronous task.
Middleware in itself simply takes a http.Handler as the first parameter, wraps it and returns a new http.Handler for the server to call (wraps handlers with closures according to the principle of Russian doll).
MiddlewareFunc is a classic middleware - decides itself whether to call next handler or return an HTTP error directly to the client and breaks the chain.
OnPanic is a function that should contain the logic responsible for any kind of error/panic reporting (to the console, file, directly to the client or simply ignore them).