{"id":13416745,"url":"https://github.com/urfave/negroni","last_synced_at":"2025-12-16T21:29:54.871Z","repository":{"id":17155425,"uuid":"19922293","full_name":"urfave/negroni","owner":"urfave","description":"Idiomatic HTTP Middleware for Golang","archived":false,"fork":false,"pushed_at":"2025-05-03T19:46:24.000Z","size":5523,"stargazers_count":7515,"open_issues_count":9,"forks_count":581,"subscribers_count":223,"default_branch":"master","last_synced_at":"2025-05-05T17:20:42.251Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/urfave.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-05-18T22:09:10.000Z","updated_at":"2025-05-03T19:46:29.000Z","dependencies_parsed_at":"2023-01-13T19:11:20.959Z","dependency_job_id":"22c5bf0f-863c-48c5-a0fa-975c92bb223e","html_url":"https://github.com/urfave/negroni","commit_stats":{"total_commits":276,"total_committers":96,"mean_commits":2.875,"dds":0.8260869565217391,"last_synced_commit":"1447d858d0ecb1c309050e37304c8e4f2a67453d"},"previous_names":["codegangsta/negroni"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfave%2Fnegroni","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfave%2Fnegroni/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfave%2Fnegroni/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfave%2Fnegroni/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/urfave","download_url":"https://codeload.github.com/urfave/negroni/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253112071,"owners_count":21856070,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T22:00:21.251Z","updated_at":"2025-12-16T21:29:49.503Z","avatar_url":"https://github.com/urfave.png","language":"Go","funding_links":[],"categories":["Popular","开源类库","Misc","Web Frameworks","Go","Middlewares \u0026 framework add-ons","Open source library","Go (531)","Service Toolkits","Middlewares","XML","Web框架","中间件","中间件### 中间件","Libraries for creating HTTP middlewares"],"sub_categories":["中间件","Middlewares","Middleware","Go","Microsoft Word","Fail injection","创建http中间件的代码库","中間件"],"readme":"# Negroni\n[![GoDoc](https://godoc.org/github.com/urfave/negroni/v3?status.svg)](http://godoc.org/github.com/urfave/negroni/v3)\n[![Build Status](https://travis-ci.org/urfave/negroni.svg?branch=master)](https://travis-ci.org/urfave/negroni)\n[![codebeat](https://codebeat.co/badges/47d320b1-209e-45e8-bd99-9094bc5111e2)](https://codebeat.co/projects/github-com-urfave-negroni)\n[![codecov](https://codecov.io/gh/urfave/negroni/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/negroni)\n\n**Notice:** This is the library formerly known as\n`github.com/codegangsta/negroni` -- Github will automatically redirect requests\nto this repository, but we recommend updating your references for clarity.\n\nNegroni is an idiomatic approach to web middleware in Go. It is tiny,\nnon-intrusive, and encourages use of `net/http` Handlers.\n\nIf you like the idea of [Martini](https://github.com/go-martini/martini), but\nyou think it contains too much magic, then Negroni is a great fit.\n\nLanguage Translations:\n* [Deutsch (de_DE)](translations/README_de_de.md)\n* [Português Brasileiro (pt_BR)](translations/README_pt_br.md)\n* [简体中文 (zh_CN)](translations/README_zh_CN.md)\n* [繁體中文 (zh_TW)](translations/README_zh_tw.md)\n* [日本語 (ja_JP)](translations/README_ja_JP.md)\n* [Français (fr_FR)](translations/README_fr_FR.md)\n* [한국어 (ko_KR)](translations/README_ko_KR.md)\n\n## Getting Started\n\nAfter installing Go and setting up your\n[GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file.\nWe'll call it `server.go`.\n\n\u003c!-- { \"interrupt\": true } --\u003e\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  n := negroni.Classic() // Includes some default middlewares\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3000\", n)\n}\n```\n\nThen install the Negroni package (**NOTE**: \u0026gt;= **go 1.1** is required):\n\n```\ngo get github.com/urfave/negroni/v3\n```\n\nThen run your server:\n\n```\ngo run server.go\n```\n\nYou will now have a Go `net/http` webserver running on `localhost:3000`.\n\n### Packaging\n\nIf you are on Debian, `negroni` is also available as [a\npackage](https://packages.debian.org/sid/golang-github-urfave-negroni-dev) that\nyou can install via `apt install golang-github-urfave-negroni-dev` (at the time\nof writing, it is in the `sid` repositories).\n\n## Is Negroni a Framework?\n\nNegroni is **not** a framework. It is a middleware-focused library that is\ndesigned to work directly with `net/http`.\n\n## Routing?\n\nNegroni is BYOR (Bring your own Router). The Go community already has a number\nof great http routers available, and Negroni tries to play well with all of them\nby fully supporting `net/http`. For instance, integrating with [Gorilla Mux]\nlooks like so:\n\n``` go\nrouter := mux.NewRouter()\nrouter.HandleFunc(\"/\", HomeHandler)\n\nn := negroni.New(Middleware1, Middleware2)\n// Or use a middleware with the Use() function\nn.Use(Middleware3)\n// router goes last\nn.UseHandler(router)\n\nhttp.ListenAndServe(\":3001\", n)\n```\n\n## `negroni.Classic()`\n\n`negroni.Classic()` provides some default middleware that is useful for most\napplications:\n\n* [`negroni.Recovery`](#recovery) - Panic Recovery Middleware.\n* [`negroni.Logger`](#logger) - Request/Response Logger Middleware.\n* [`negroni.Static`](#static) - Static File serving under the \"public\"\n  directory.\n\nThis makes it really easy to get started with some useful features from Negroni.\n\n## Handlers\n\nNegroni provides a bidirectional middleware flow. This is done through the\n`negroni.Handler` interface:\n\n``` go\ntype Handler interface {\n  ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)\n}\n```\n\nIf a middleware hasn't already written to the `ResponseWriter`, it should call\nthe next `http.HandlerFunc` in the chain to yield to the next middleware\nhandler.  This can be used for great good:\n\n``` go\nfunc MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\n  // do some stuff before\n  next(rw, r)\n  // do some stuff after\n}\n```\n\nAnd you can map it to the handler chain with the `Use` function:\n\n``` go\nn := negroni.New()\nn.Use(negroni.HandlerFunc(MyMiddleware))\n```\n\nYou can also map plain old `http.Handler`s:\n\n``` go\nn := negroni.New()\n\nmux := http.NewServeMux()\n// map your routes\n\nn.UseHandler(mux)\n\nhttp.ListenAndServe(\":3000\", n)\n```\n\n## `With()`\n\nNegroni has a convenience function called `With`. `With` takes one or more\n`Handler` instances and returns a new `Negroni` with the combination of the\nreceiver's handlers and the new handlers.\n\n```go\n// middleware we want to reuse\ncommon := negroni.New()\ncommon.Use(MyMiddleware1)\ncommon.Use(MyMiddleware2)\n\n// `specific` is a new negroni with the handlers from `common` combined with the\n// the handlers passed in\nspecific := common.With(\n\tSpecificMiddleware1,\n\tSpecificMiddleware2\n)\n```\n\n## `Run()`\n\nNegroni has a convenience function called `Run`. `Run` takes an addr string\nidentical to [`http.ListenAndServe`](https://godoc.org/net/http#ListenAndServe).\n\n\u003c!-- { \"interrupt\": true } --\u003e\n``` go\npackage main\n\nimport (\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  n := negroni.Classic()\n  n.Run(\":8080\")\n}\n```\n\nIf no address is provided, the `PORT` environment variable is used instead.\nIf the `PORT` environment variable is not defined, the default address will be used. \nSee [Run](https://godoc.org/github.com/urfave/negroni/v3#Negroni.Run) for a complete description.\n\nIn general, you will want to use `net/http` methods and pass `negroni` as a\n`Handler`, as this is more flexible, e.g.:\n\n\u003c!-- { \"interrupt\": true } --\u003e\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"log\"\n  \"net/http\"\n  \"time\"\n\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  n := negroni.Classic() // Includes some default middlewares\n  n.UseHandler(mux)\n\n  s := \u0026http.Server{\n    Addr:           \":8080\",\n    Handler:        n,\n    ReadTimeout:    10 * time.Second,\n    WriteTimeout:   10 * time.Second,\n    MaxHeaderBytes: 1 \u003c\u003c 20,\n  }\n  log.Fatal(s.ListenAndServe())\n}\n```\n\n## Route Specific Middleware\n\nIf you have a route group of routes that need specific middleware to be\nexecuted, you can simply create a new Negroni instance and use it as your route\nhandler.\n\n``` go\nrouter := mux.NewRouter()\nadminRoutes := mux.NewRouter()\n// add admin routes here\n\n// Create a new negroni for the admin middleware\nrouter.PathPrefix(\"/admin\").Handler(negroni.New(\n  Middleware1,\n  Middleware2,\n  negroni.Wrap(adminRoutes),\n))\n```\n\nIf you are using [Gorilla Mux], here is an example using a subrouter:\n\n``` go\nrouter := mux.NewRouter()\nsubRouter := mux.NewRouter().PathPrefix(\"/subpath\").Subrouter().StrictSlash(true)\nsubRouter.HandleFunc(\"/\", someSubpathHandler) // \"/subpath/\"\nsubRouter.HandleFunc(\"/:id\", someSubpathHandler) // \"/subpath/:id\"\n\n// \"/subpath\" is necessary to ensure the subRouter and main router linkup\nrouter.PathPrefix(\"/subpath\").Handler(negroni.New(\n  Middleware1,\n  Middleware2,\n  negroni.Wrap(subRouter),\n))\n```\n\n`With()` can be used to eliminate redundancy for middlewares shared across\nroutes.\n\n``` go\nrouter := mux.NewRouter()\napiRoutes := mux.NewRouter()\n// add api routes here\nwebRoutes := mux.NewRouter()\n// add web routes here\n\n// create common middleware to be shared across routes\ncommon := negroni.New(\n\tMiddleware1,\n\tMiddleware2,\n)\n\n// create a new negroni for the api middleware\n// using the common middleware as a base\nrouter.PathPrefix(\"/api\").Handler(common.With(\n  APIMiddleware1,\n  negroni.Wrap(apiRoutes),\n))\n// create a new negroni for the web middleware\n// using the common middleware as a base\nrouter.PathPrefix(\"/web\").Handler(common.With(\n  WebMiddleware1,\n  negroni.Wrap(webRoutes),\n))\n```\n\n## Bundled Middleware\n\n### Static\n\nThis middleware will serve files on the filesystem. If the files do not exist,\nit proxies the request to the next middleware. If you want the requests for\nnon-existent files to return a `404 File Not Found` to the user you should look\nat using [http.FileServer](https://golang.org/pkg/net/http/#FileServer) as\na handler.\n\nExample:\n\n\u003c!-- { \"interrupt\": true } --\u003e\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  // Example of using a http.FileServer if you want \"server-like\" rather than \"middleware\" behavior\n  // mux.Handle(\"/public\", http.FileServer(http.Dir(\"/home/public\")))\n\n  n := negroni.New()\n  n.Use(negroni.NewStatic(http.Dir(\"/tmp\")))\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3002\", n)\n}\n```\n\nWill serve files from the `/tmp` directory first, but proxy calls to the next\nhandler if the request does not match a file on the filesystem.\n\n### Recovery\n\nThis middleware catches `panic`s and responds with a `500` response code. If\nany other middleware has written a response code or body, this middleware will\nfail to properly send a 500 to the client, as the client has already received\nthe HTTP response code. Additionally, an `PanicHandlerFunc` can be attached\nto report 500's to an error reporting service such as Sentry or Airbrake.\n\nExample:\n\n\u003c!-- { \"interrupt\": true } --\u003e\n``` go\npackage main\n\nimport (\n  \"net/http\"\n\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    panic(\"oh no\")\n  })\n\n  n := negroni.New()\n  n.Use(negroni.NewRecovery())\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3003\", n)\n}\n```\n\nWill return a `500 Internal Server Error` to each request. It will also log the\nstack traces as well as print the stack trace to the requester if `PrintStack`\nis set to `true` (the default).\n\nExample with error handler:\n\n``` go\npackage main\n\nimport (\n  \"net/http\"\n\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    panic(\"oh no\")\n  })\n\n  n := negroni.New()\n  recovery := negroni.NewRecovery()\n  recovery.PanicHandlerFunc = reportToSentry\n  n.Use(recovery)\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3003\", n)\n}\n\nfunc reportToSentry(info *negroni.PanicInformation) {\n    // write code here to report error to Sentry\n}\n```\n\nThe middleware simply output the informations on STDOUT by default.\nYou can customize the output process by using the `SetFormatter()` function.\n\nYou can use also the `HTMLPanicFormatter` to display a pretty HTML when a crash occurs.\n\n\u003c!-- { \"interrupt\": true } --\u003e\n``` go\npackage main\n\nimport (\n  \"net/http\"\n\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    panic(\"oh no\")\n  })\n\n  n := negroni.New()\n  recovery := negroni.NewRecovery()\n  recovery.Formatter = \u0026negroni.HTMLPanicFormatter{}\n  n.Use(recovery)\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3003\", n)\n}\n```\n\n## Logger\n\nThis middleware logs each incoming request and response.\n\nExample:\n\n\u003c!-- { \"interrupt\": true } --\u003e\n``` go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n\n  \"github.com/urfave/negroni/v3\"\n)\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n    fmt.Fprintf(w, \"Welcome to the home page!\")\n  })\n\n  n := negroni.New()\n  n.Use(negroni.NewLogger())\n  n.UseHandler(mux)\n\n  http.ListenAndServe(\":3004\", n)\n}\n```\n\nWill print a log similar to:\n\n```\n[negroni] 2017-10-04T14:56:25+02:00 | 200 |      378µs | localhost:3004 | GET /\n```\n\non each request.\n\nYou 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 -\n\n```go\nl.SetFormat(\"[{{.Status}} {{.Duration}}] - {{.Request.UserAgent}}\")\n```\n\nwill show something like - `[200 18.263µs] - Go-User-Agent/1.1 `\n\n## Third Party Middleware\n\nHere is a current list of Negroni compatible middlware. Feel free to put up a PR\nlinking your middleware if you have built one:\n\n| Middleware                                                                   | Author                                               | Description                                                                                                                     |\n| ---------------------------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| [authz](https://github.com/casbin/negroni-authz)                             | [Yang Luo](https://github.com/hsluoyz)               | ACL, RBAC, ABAC Authorization middlware based on [Casbin](https://github.com/casbin/casbin)                                     |\n| [binding](https://github.com/mholt/binding)                                  | [Matt Holt](https://github.com/mholt)                | Data binding from HTTP requests into structs                                                                                    |\n| [cloudwatch](https://github.com/cvillecsteele/negroni-cloudwatch)            | [Colin Steele](https://github.com/cvillecsteele)     | AWS cloudwatch metrics middleware                                                                                               |\n| [cors](https://github.com/rs/cors)                                           | [Olivier Poitrey](https://github.com/rs)             | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support                                                      |\n| [csp](https://github.com/awakenetworks/csp)                                  | [Awake Networks](https://github.com/awakenetworks)   | [Content Security Policy](https://www.w3.org/TR/CSP2/) (CSP) support                                                            |\n| [delay](https://github.com/jeffbmartinez/delay)                              | [Jeff Martinez](https://github.com/jeffbmartinez)    | Add delays/latency to endpoints. Useful when testing effects of high latency                                                    |\n| [New Relic Go Agent](https://github.com/yadvendar/negroni-newrelic-go-agent) | [Yadvendar Champawat](https://github.com/yadvendar)  | Official [New Relic Go Agent](https://github.com/newrelic/go-agent) (currently in beta)                                         |\n| [gorelic](https://github.com/jingweno/negroni-gorelic)                       | [Jingwen Owen Ou](https://github.com/jingweno)       | New Relic agent for Go runtime                                                                                                  |\n| [Graceful](https://github.com/tylerb/graceful)                               | [Tyler Bunnell](https://github.com/tylerb)           | Graceful HTTP Shutdown                                                                                                          |\n| [gzip](https://github.com/phyber/negroni-gzip)                               | [phyber](https://github.com/phyber)                  | GZIP response compression                                                                                                       |\n| [JWT Middleware](https://github.com/auth0/go-jwt-middleware)                 | [Auth0](https://github.com/auth0)                    | Middleware checks for a JWT on the `Authorization` header on incoming requests and decodes it                                   |\n| [JWT Middleware](https://github.com/mfuentesg/go-jwtmiddleware)              | [Marcelo Fuentes](https://github.com/mfuentesg)      | JWT middleware for golang                                                                                                       |\n| [logrus](https://github.com/meatballhat/negroni-logrus)                      | [Dan Buch](https://github.com/meatballhat)           | Logrus-based logger                                                                                                             |\n| [oauth2](https://github.com/goincremental/negroni-oauth2)                    | [David Bochenski](https://github.com/bochenski)      | oAuth2 middleware                                                                                                               |\n| [onthefly](https://github.com/xyproto/onthefly)                              | [Alexander Rødseth](https://github.com/xyproto)      | Generate TinySVG, HTML and CSS on the fly                                                                                       |\n| [permissions2](https://github.com/xyproto/permissions2)                      | [Alexander Rødseth](https://github.com/xyproto)      | Cookies, users and permissions                                                                                                  |\n| [prometheus](https://github.com/zbindenren/negroni-prometheus)               | [Rene Zbinden](https://github.com/zbindenren)        | Easily create metrics endpoint for the [prometheus](http://prometheus.io) instrumentation tool                                  |\n| [prometheus](https://github.com/slok/go-prometheus-middleware)               | [Xabier Larrakoetxea](https://github.com/slok)       | [Prometheus](http://prometheus.io) metrics with multiple options that follow standards and try to be measured in a efficient way |\n| [render](https://github.com/unrolled/render)                                 | [Cory Jacobsen](https://github.com/unrolled)         | Render JSON, XML and HTML templates                                                                                             |\n| [RestGate](https://github.com/pjebs/restgate)                                | [Prasanga Siripala](https://github.com/pjebs)        | Secure authentication for REST API endpoints                                                                                    |\n| [secure](https://github.com/unrolled/secure)                                 | [Cory Jacobsen](https://github.com/unrolled)         | Middleware that implements a few quick security wins                                                                            |\n| [sessions](https://github.com/goincremental/negroni-sessions)                | [David Bochenski](https://github.com/bochenski)      | Session Management                                                                                                              |\n| [stats](https://github.com/thoas/stats)                                      | [Florent Messa](https://github.com/thoas)            | Store information about your web application (response time, etc.)                                                              |\n| [VanGoH](https://github.com/auroratechnologies/vangoh)                       | [Taylor Wrobel](https://github.com/twrobel3)         | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware |\n| [xrequestid](https://github.com/pilu/xrequestid)                             | [Andrea Franz](https://github.com/pilu)              | Middleware that assigns a random X-Request-Id header to each request                                                            |\n| [mgo session](https://github.com/joeljames/nigroni-mgo-session)              | [Joel James](https://github.com/joeljames)           | Middleware that handles creating and closing mgo sessions per request                                                           |\n| [digits](https://github.com/bamarni/digits)                                  | [Bilal Amarni](https://github.com/bamarni)           | Middleware that handles [Twitter Digits](https://get.digits.com/) authentication                                                |\n| [stats](https://github.com/guptachirag/stats)                                | [Chirag Gupta](https://github.com/guptachirag/stats) | Middleware that manages qps and latency stats for your endpoints and asynchronously flushes them to influx db                   |\n| [Chaos](https://github.com/falzm/chaos)                                      | [Marc Falzon](https://github.com/falzm)              | Middleware for injecting chaotic behavior into application in a programmatic way                                                |\n\n## Examples\n\n[Alexander Rødseth](https://github.com/xyproto) created\n[mooseware](https://github.com/xyproto/mooseware), a skeleton for writing a\nNegroni middleware handler.\n\n[Prasanga Siripala](https://github.com/pjebs) created an effective skeleton structure for web-based Go/Negroni projects: [Go-Skeleton](https://github.com/pjebs/go-skeleton) \n\n## Live code reload?\n\n[gin](https://github.com/codegangsta/gin) and\n[fresh](https://github.com/pilu/fresh) both live reload negroni apps.\n\n## Essential Reading for Beginners of Go \u0026 Negroni\n\n* [Using a Context to pass information from middleware to end handler](http://elithrar.github.io/article/map-string-interface/)\n* [Understanding middleware](https://mattstauffer.co/blog/laravel-5.0-middleware-filter-style)\n\n## About\n\nNegroni is obsessively designed by none other than the [Code\nGangsta](https://codegangsta.io/)\n\n[Gorilla Mux]: https://github.com/gorilla/mux\n[`http.FileSystem`]: https://godoc.org/net/http#FileSystem\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furfave%2Fnegroni","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Furfave%2Fnegroni","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furfave%2Fnegroni/lists"}