middleware

package module
v0.0.0-...-18744b3 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2016 License: MIT Imports: 1 Imported by: 0

README

Build Status Coverage Status Go Report Card

Middleware for Golang Services

This is an easy, yet powerful, tool for adding middleware to your standared http or gorilla/mux routes.

This package is as simple and lightweight as it gets. Just take a look at the source code, it's only a few lines and has no 3rd party dependencies

For more information and examples, visit the godoc.

Documentation

Overview

Package middleware - is an easy, yet powerful, tool for adding middleware to your standard http or gorilla/mux routes.

This package is as simple and lightweight as it gets. Just take a look at the source code, it's only 29 lines (not counting the unit tests and documentation, of course) and has no 3rd party dependencies.

Middleware is used to enhance the functionality of route handlers without bloating your handler functions or duplicating code across multiple handlers. For those familiar with aspect oriented programming or cross-cutting concerns, middleware is roughly analogous.

The canonical example of middleware is adding request logging across all of your http handlers. You you may want it to do some logging before the handler is invoked and some additional logging after the response is sent to the client. This is not logic that you want to include in the handler method and have it detract from the actual business logic, nor is it code that you want to repeat in every handler method that it applies to.

Another common example is adding authentication/authorization across multiple routes. As with logging, you want to keep this logic isolated and easily apply it to each route that requires it.

The best way to understand is by example, so here is a fleshed out, fully operational example of an http service that exposes two endpoints: "/" and "/secret". logging is applied across both routes, however security is only applied to the "/secret" route.

Example:

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/UrbanGopher/middleware"
)

func main() {
	mw := &middleware.Wrapper{}

	mw.Append(loggingMiddleware) // add logging middleware
	http.HandleFunc("/", mw.WrapHandler(handler))

	mw.Append(securityMiddleware) // add some security middleware
	http.HandleFunc("/secret", mw.WrapHandler(secretHandler))

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

func handler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello, world!"))
}

func secretHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("You got in!"))
}

// A function that adheres to the middleware.Middleware specification
func loggingMiddleware(next middleware.RouteHandler) middleware.RouteHandler {
	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Handling the request")
		defer func(begin time.Time) {
			fmt.Println("Request took: ", time.Since(begin))
		}(time.Now())

		next(w, r)
	}
}

// Another function that adheres to middleware.Middleware
func securityMiddleware(next middleware.RouteHandler) middleware.RouteHandler {
	return func(w http.ResponseWriter, r *http.Request) {
		qp := r.URL.Query()

		if len(qp) > 0 && len(qp["word"]) > 0 && qp["word"][0] == "please" {
			next(w, r)
		} else {
			w.WriteHeader(403)
			w.Write([]byte("You didn't say the magic word!"))
		}
	}
}

This middleware package can easily be applied to gorilla/mux routes as well since they rely on handler functions with signatures that are identical to the standard go http.HandleFunc handler functions. To demonstrate, the above example's main method could be rewritten as follows:

import (
  ...
  "github.com/gorilla/mux"
)

func main() {
  router := mux.NewRouter()
	mw := &middleware.Wrapper{}

	mw.Append(loggingMiddleware) // add logging middleware
	router.HandleFunc("/", mw.WrapHandler(handler))

	mw.Append(securityMiddleware) // add some security middleware
	router.HandleFunc("/secret", mw.WrapHandler(secretHandler))

  http.Handle("/", router)
	http.ListenAndServe(":8080", nil)
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Decorator

type Decorator interface {
	// Append - Add Middleware to the beginning of the decorator chain. This
	// Middleware will wrap all existing middleware.
	Append(Middleware) Decorator

	// Prepend - Add Middleware to the end of the decorator chain. This Middleware
	// will be wrapped by all existing Middleware.
	Prepend(Middleware) Decorator

	// WrapHandler - Wraps the http.HandlerFunc with the Middleware added via the
	// Append and Prepend methods
	WrapHandler(http.HandlerFunc) http.HandlerFunc
}

Decorator - Interface for defining a middleware wrapping mechanism. This interface exists for the purpose of testing, but, of course, can be used at your discretion.

type Middleware

type Middleware func(http.HandlerFunc) http.HandlerFunc

Middleware - A function type for defining middleware

type Wrapper

type Wrapper struct {
	// contains filtered or unexported fields
}

Wrapper - Concrete implementation of the Decorator interface

func (*Wrapper) Append

func (w *Wrapper) Append(mw Middleware) Decorator

Append - Concrete implementation of the Decorator.Append method

func (*Wrapper) Prepend

func (w *Wrapper) Prepend(m Middleware) Decorator

Prepend - Concrete implementation of the Decorator.Prepend method

func (*Wrapper) WrapHandler

func (w *Wrapper) WrapHandler(h http.HandlerFunc) http.HandlerFunc

WrapHandler - Concrete implementation of the Decorator.WrapHandler method

Jump to

Keyboard shortcuts

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