Go
Need help with negroni?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.
urfave

Description

Idiomatic HTTP Middleware for Golang

6.8K Stars 551 Forks MIT License 409 Commits 8 Opened issues

Services available

Need anything else?

Negroni

GoDoc Build Status codebeat codecov

Notice: This is the library formerly known as

github.com/codegangsta/negroni
-- Github will automatically redirect requests to this repository, but we recommend updating your references for clarity.

Negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of

net/http
Handlers.

If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit.

Language Translations: * Deutsch (de_DE) * Português Brasileiro (pt_BR) * 简体中文 (zh_CN) * 繁體中文 (zh_TW) * 日本語 (ja_JP) * Français (fr_FR) * 한국어 (ko_KR)

Getting Started

After installing Go and setting up your GOPATH, create your first

.go
file. We'll call it
server.go
.
package main

import (
  "fmt"
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.Classic() // Includes some default middlewares
  n.UseHandler(mux)

  http.ListenAndServe(":3000", n)
}

Then install the Negroni package (NOTE: >= go 1.1 is required):

go get github.com/urfave/negroni

Then run your server:

go run server.go

You will now have a Go

net/http
webserver running on
localhost:3000
.

Packaging

If you are on Debian,

negroni
is also available as a package that you can install via
apt install golang-github-urfave-negroni-dev
(at the time of writing, it is in the
sid
repositories).

Is Negroni a Framework?

Negroni is not a framework. It is a middleware-focused library that is designed to work directly with

net/http
.

Routing?

Negroni is BYOR (Bring your own Router). The Go community already has a number of great http routers available, and Negroni tries to play well with all of them by fully supporting

net/http
. For instance, integrating with Gorilla Mux looks like so:
router := mux.NewRouter()
router.HandleFunc("/", HomeHandler)

n := negroni.New(Middleware1, Middleware2) // Or use a middleware with the Use() function n.Use(Middleware3) // router goes last n.UseHandler(router)

http.ListenAndServe(":3001", n)

negroni.Classic()

negroni.Classic()
provides some default middleware that is useful for most applications:

This makes it really easy to get started with some useful features from Negroni.

Handlers

Negroni provides a bidirectional middleware flow. This is done through the

negroni.Handler
interface:
type Handler interface {
  ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
}

If a middleware hasn't already written to the

ResponseWriter
, it should call the next
http.HandlerFunc
in the chain to yield to the next middleware handler. This can be used for great good:
func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  // do some stuff before
  next(rw, r)
  // do some stuff after
}

And you can map it to the handler chain with the

Use
function:
n := negroni.New()
n.Use(negroni.HandlerFunc(MyMiddleware))

You can also map plain old

http.Handler
s:
n := negroni.New()

mux := http.NewServeMux() // map your routes

n.UseHandler(mux)

http.ListenAndServe(":3000", n)

With()

Negroni has a convenience function called

With
.
With
takes one or more
Handler
instances and returns a new
Negroni
with the combination of the receiver's handlers and the new handlers.
// middleware we want to reuse
common := negroni.New()
common.Use(MyMiddleware1)
common.Use(MyMiddleware2)

// specific is a new negroni with the handlers from common combined with the // the handlers passed in specific := common.With( SpecificMiddleware1, SpecificMiddleware2 )

Run()

Negroni has a convenience function called

Run
.
Run
takes an addr string identical to
http.ListenAndServe
.
package main

import (
  "github.com/urfave/negroni"
)

func main() {
  n := negroni.Classic()
  n.Run(":8080")
}

If no address is provided, the

PORT
environment variable is used instead. If the
PORT
environment variable is not defined, the default address will be used. See Run for a complete description.

In general, you will want to use

net/http
methods and pass
negroni
as a
Handler
, as this is more flexible, e.g.:
package main

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

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.Classic() // Includes some default middlewares
  n.UseHandler(mux)

  s := &http.Server{
    Addr:           ":8080",
    Handler:        n,
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
  }
  log.Fatal(s.ListenAndServe())
}

Route Specific Middleware

If you have a route group of routes that need specific middleware to be executed, you can simply create a new Negroni instance and use it as your route handler.

router := mux.NewRouter()
adminRoutes := mux.NewRouter()
// add admin routes here

// Create a new negroni for the admin middleware router.PathPrefix("/admin").Handler(negroni.New( Middleware1, Middleware2, negroni.Wrap(adminRoutes), ))

If you are using Gorilla Mux, here is an example using a subrouter:

router := mux.NewRouter()
subRouter := mux.NewRouter().PathPrefix("/subpath").Subrouter().StrictSlash(true)
subRouter.HandleFunc("/", someSubpathHandler) // "/subpath/"
subRouter.HandleFunc("/:id", someSubpathHandler) // "/subpath/:id"

// "/subpath" is necessary to ensure the subRouter and main router linkup router.PathPrefix("/subpath").Handler(negroni.New( Middleware1, Middleware2, negroni.Wrap(subRouter), ))

With()
can be used to eliminate redundancy for middlewares shared across routes.
router := mux.NewRouter()
apiRoutes := mux.NewRouter()
// add api routes here
webRoutes := mux.NewRouter()
// add web routes here

// create common middleware to be shared across routes common := negroni.New( Middleware1, Middleware2, )

// create a new negroni for the api middleware // using the common middleware as a base router.PathPrefix("/api").Handler(common.With( APIMiddleware1, negroni.Wrap(apiRoutes), )) // create a new negroni for the web middleware // using the common middleware as a base router.PathPrefix("/web").Handler(common.With( WebMiddleware1, negroni.Wrap(webRoutes), ))

Bundled Middleware

Static

This middleware will serve files on the filesystem. If the files do not exist, it proxies the request to the next middleware. If you want the requests for non-existent files to return a

404 File Not Found
to the user you should look at using http.FileServer as a handler.

Example:

package main

import (
  "fmt"
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  // Example of using a http.FileServer if you want "server-like" rather than "middleware" behavior
  // mux.Handle("/public", http.FileServer(http.Dir("/home/public")))

  n := negroni.New()
  n.Use(negroni.NewStatic(http.Dir("/tmp")))
  n.UseHandler(mux)

  http.ListenAndServe(":3002", n)
}

Will serve files from the

/tmp
directory first, but proxy calls to the next handler if the request does not match a file on the filesystem.

Recovery

This middleware catches

panic
s and responds with a
500
response code. If any other middleware has written a response code or body, this middleware will fail to properly send a 500 to the client, as the client has already received the HTTP response code. Additionally, an
PanicHandlerFunc
can be attached to report 500's to an error reporting service such as Sentry or Airbrake.

Example:

package main

import (
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    panic("oh no")
  })

  n := negroni.New()
  n.Use(negroni.NewRecovery())
  n.UseHandler(mux)

  http.ListenAndServe(":3003", n)
}

Will return a

500 Internal Server Error
to each request. It will also log the stack traces as well as print the stack trace to the requester if
PrintStack
is set to
true
(the default).

Example with error handler:

package main

import ( "net/http"

"github.com/urfave/negroni" )

func main() { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { panic("oh no") })

n := negroni.New() recovery := negroni.NewRecovery() recovery.PanicHandlerFunc = reportToSentry n.Use(recovery) n.UseHandler(mux)

http.ListenAndServe(":3003", n) }

func reportToSentry(info *negroni.PanicInformation) { // write code here to report error to Sentry }

The middleware simply output the informations on STDOUT by default. You can customize the output process by using the

SetFormatter()
function.

You can use also the

HTMLPanicFormatter
to display a pretty HTML when a crash occurs.
package main

import (
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    panic("oh no")
  })

  n := negroni.New()
  recovery := negroni.NewRecovery()
  recovery.Formatter = &negroni.HTMLPanicFormatter{}
  n.Use(recovery)
  n.UseHandler(mux)

  http.ListenAndServe(":3003", n)
}

Logger

This middleware logs each incoming request and response.

Example:

package main

import (
  "fmt"
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.New()
  n.Use(negroni.NewLogger())
  n.UseHandler(mux)

  http.ListenAndServe(":3004", n)
}

Will print a log similar to:

[negroni] 2017-10-04T14:56:25+02:00 | 200 |      378µs | localhost:3004 | GET /

on each request.

You can also set your own log format by calling the

SetFormat
function. The format is a template string with fields as mentioned in the
LoggerEntry
struct. So, as an example -
l.SetFormat("[{{.Status}} {{.Duration}}] - {{.Request.UserAgent}}")

will show something like -

[200 18.263µs] - Go-User-Agent/1.1

Third Party Middleware

Here is a current list of Negroni compatible middlware. Feel free to put up a PR linking your middleware if you have built one:

| Middleware | Author | Description | | -----------|--------|-------------| | authz | Yang Luo | ACL, RBAC, ABAC Authorization middlware based on Casbin | | binding | Matt Holt | Data binding from HTTP requests into structs | | cloudwatch | Colin Steele | AWS cloudwatch metrics middleware | | cors | Olivier Poitrey | Cross Origin Resource Sharing (CORS) support | | csp | Awake Networks | Content Security Policy (CSP) support | | delay | Jeff Martinez | Add delays/latency to endpoints. Useful when testing effects of high latency | | New Relic Go Agent | Yadvendar Champawat | Official New Relic Go Agent (currently in beta) | | gorelic | Jingwen Owen Ou | New Relic agent for Go runtime | | Graceful | Tyler Bunnell | Graceful HTTP Shutdown | | gzip | phyber | GZIP response compression | | JWT Middleware | Auth0 | Middleware checks for a JWT on the

Authorization
header on incoming requests and decodes it| | JWT Middleware | Marcelo Fuentes | JWT middleware for golang | | logrus | Dan Buch | Logrus-based logger | | oauth2 | David Bochenski | oAuth2 middleware | | onthefly | Alexander Rødseth | Generate TinySVG, HTML and CSS on the fly | | permissions2 | Alexander Rødseth | Cookies, users and permissions | | prometheus | Rene Zbinden | Easily create metrics endpoint for the prometheus instrumentation tool | | prometheus | Xabier Larrakoetxea | Prometheus metrics with multiple options that follow standards and try to be measured in a efficent way | | render | Cory Jacobsen | Render JSON, XML and HTML templates | | RestGate | Prasanga Siripala | Secure authentication for REST API endpoints | | secure | Cory Jacobsen | Middleware that implements a few quick security wins | | sessions | David Bochenski | Session Management | | stats | Florent Messa | Store information about your web application (response time, etc.) | | VanGoH | Taylor Wrobel | Configurable AWS-Style HMAC authentication middleware | | xrequestid | Andrea Franz | Middleware that assigns a random X-Request-Id header to each request | | mgo session | Joel James | Middleware that handles creating and closing mgo sessions per request | | digits | Bilal Amarni | Middleware that handles Twitter Digits authentication | | stats | Chirag Gupta | Middleware that manages qps and latency stats for your endpoints and asynchronously flushes them to influx db | | Chaos | Marc Falzon | Middleware for injecting chaotic behavior into application in a programmatic way |

Examples

Alexander Rødseth created mooseware, a skeleton for writing a Negroni middleware handler.

Prasanga Siripala created an effective skeleton structure for web-based Go/Negroni projects: Go-Skeleton

Live code reload?

gin and fresh both live reload negroni apps.

Essential Reading for Beginners of Go & Negroni

About

Negroni is obsessively designed by none other than the Code Gangsta

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.