{"id":2975,"date":"2017-09-07T07:38:35","date_gmt":"2017-09-07T07:38:35","guid":{"rendered":"https:\/\/intelligentbee.com\/blog\/?p=2975"},"modified":"2025-03-06T07:25:38","modified_gmt":"2025-03-06T07:25:38","slug":"negroni-middleware-golang-httprouter","status":"publish","type":"post","link":"https:\/\/intelligentbee.com\/blog\/negroni-middleware-golang-httprouter\/","title":{"rendered":"Using Negroni middleware in Golang for specific routes with httprouter"},"content":{"rendered":"<p>In the last days I\u2019ve played a little bit with <code>negroni<\/code> middleware and <code>httprouter<\/code> router. I found that the documentation about how can we use negroni middlewares for specific routes with httprouter is pretty poor. So I decided to write this article to share with you what I\u2019ve found.<\/p>\n<p>Negroni is an idiomatic approach to web middleware in Golang which will help you build and stack middleware very easily. It comes with some default middlewares like:<\/p>\n<ul>\n<li>negroni.Recovery &#8211; Panic Recovery Middleware.<\/li>\n<li>negroni.Logger &#8211; Request\/Response Logger Middleware.<\/li>\n<li>negroni.Static &#8211; Static File serving under the &#8220;public&#8221; directory.<\/li>\n<\/ul>\n<p>But it also letting you create your own middlewares very easily:<\/p>\n<pre class=\"lang:go decode:true\">func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\r\n    \/\/ do some stuff before\r\n    next(rw, r)\r\n    \/\/ do some stuff after\r\n}\r\n\r\n\u2026\r\nn := negroni.New()\r\nn.Use(negroni.HandlerFunc(MyMiddleware))\r\n<\/pre>\n<p>Negroni is BYOR (Bring your own Router) so we can use it with httprouter.<\/p>\n<p>Httprouter is a Golang lightweight and high performance HTTP request router which is fast and has low memory consumption. TLDR: it is one of the fastest routers.<\/p>\n<p>Here you have an example on how a simple route can be added when using httprouter:<\/p>\n<pre class=\"lang:default decode:true\">router := httprouter.New()\r\nrouter.POST(\"\/login\", loginHandler)<\/pre>\n<p>Where loginHandler will look like:<\/p>\n<pre class=\"lang:go decode:true\">func loginHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {\r\n    \/\/ login controller logic\r\n}<\/pre>\n<p>Now lets suppose you want to access <code>GET profile<\/code> endpoint but you need to be authenticated.<br \/>\nWe will start by creating an authentication middleware:<\/p>\n<pre class=\"lang:go decode:true\">\/\/ auth middleware\r\nfunc auth(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {\r\n    \/\/ do some stuff before\r\n    log.Println(\"auth middleware -&gt; before executing controller\")\r\n\r\n    \/\/ call endpoint handler\r\n    next(rw, r)\r\n\r\n    \/\/ do some stuff after\r\n    log.Println(\"auth middleware -&gt; after the controller was executed\")\r\n}\r\n<\/pre>\n<p>Then we will create a handler which will return profile information after the authentication will be done. This handler will be sent to the auth middleware as a callback using &#8220;next&#8221; parameter:<\/p>\n<pre class=\"lang:go decode:true\">func profileHandler(w http.ResponseWriter, r *http.Request) {\r\n    fmt.Fprintf(w, \"This is the content of the profile controller\\n\")\r\n    log.Println(\"executing profile controller\")\r\n}\r\n<\/pre>\n<p>Now let\u2019s send everything to the router:<\/p>\n<pre class=\"lang:go decode:true\">nProfile := negroni.New()\r\n\/\/ set the middleware\r\nnProfile.Use(negroni.HandlerFunc(auth))\r\n\/\/ set the handler\r\nnProfile.UseHandlerFunc(profileHandler)\r\n\/\/ attach negroni middleware and handler to our route\r\nrouter.Handler(\"GET\", \"\/profile\", nProfile)\r\n<\/pre>\n<p>That was simple, but now if we have a route which contains parameters inside it (like\u00a0<code>\/hello\/<span style=\"color: #ff0000;\">:name<\/span><\/code>) we cannot access it from our handler function. To solve that, I\u2019ve written the following functions which will help us call the handler with the parameters:<\/p>\n<pre class=\"lang:go decode:true\">\/\/ callwithParams function is helping us to call controller from middleware having access to URL params\r\nfunc callWithParams(router *httprouter.Router, handler func(w http.ResponseWriter, r *http.Request, ps httprouter.Params)) func(w http.ResponseWriter, r *http.Request) {\r\n    return func(w http.ResponseWriter, r *http.Request) {\r\n        params := getUrlParams(router, r)\r\n        handler(w, r, params)\r\n    }\r\n}\r\n\r\n\/\/ getUrlParams function is extracting URL parameters\r\nfunc getUrlParams(router *httprouter.Router, req *http.Request) httprouter.Params {\r\n    _, params, _ := router.Lookup(req.Method, req.URL.Path)\r\n\r\n    return params\r\n}<\/pre>\n<p>And will be used like this:<\/p>\n<pre class=\"lang:go decode:true\">router := httprouter.New()\r\nnHello := negroni.New()\r\n\/\/ add auth middleware\r\nnHello.Use(negroni.HandlerFunc(auth))\r\n\/\/ add handler using callWithParams function so we can access the URL parameters in handler\r\nnHello.UseHandlerFunc(callWithParams(router, helloHandler))\r\nrouter.Handler(\"GET\", \"\/hello\/:name\", nHello)\r\n\r\nn.UseHandler(router)\r\n\r\nlog.Fatal(http.ListenAndServe(\":8080\", n))<\/pre>\n<h2>Using Negroni middleware in Golang for specific routes with httprouter<\/h2>\n<p>The full working example can be found <a href=\"https:\/\/github.com\/intelligentbee\/negroni_middleware\/blob\/master\/example.go\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last days I\u2019ve played a little bit with negroni middleware and httprouter router. I found that the documentation [&hellip;]<\/p>\n","protected":false},"author":20,"featured_media":2993,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[73,78],"tags":[147,155,169,178],"yst_prominent_words":[281,461,798,902,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/2975"}],"collection":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/comments?post=2975"}],"version-history":[{"count":4,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/2975\/revisions"}],"predecessor-version":[{"id":133372,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/2975\/revisions\/133372"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/media\/2993"}],"wp:attachment":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/media?parent=2975"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/categories?post=2975"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/tags?post=2975"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/yst_prominent_words?post=2975"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}