writing http middleware in go

20
Writing HTTP Middleware In Go Shiju Varghese GopherCon India 2016

Upload: shiju-varghese

Post on 15-Jan-2017

1.092 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Writing HTTP Middleware In Go

Writing HTTP Middleware In Go

Shiju Varghese

GopherCon India 2016

Page 2: Writing HTTP Middleware In Go

Agenda

• Introduction to HTTP Middleware

• Writing HTTP Middleware with Negroni

Page 3: Writing HTTP Middleware In Go

HTTP Handlers

! !!!! !

Handlers are responsible for writing headers and bodies !into HTTP responses. !!//ServeHTTPshouldwritereplyheadersanddata//totheResponseWriterandthenreturn.!typeHandlerinterface{ServeHTTP(ResponseWriter,*Request)}

Page 4: Writing HTTP Middleware In Go

HTTP Middleware• Pluggable and self-contained piece of code that

wraps web application handlers.!

• Components that work as another layer in the request handling cycle, which can execute some logic before or after executing your HTTP application handlers.!

• Great for implementing cross-cutting concerns: Authentication, authorization, caching, logging, etc.

!

Page 5: Writing HTTP Middleware In Go

Using StripPrefix to Wraps http.FileServer handler

packagemain!import("net/http")!funcmain(){//ToserveadirectoryondiskunderanalternateURL//path(/public/),useStripPrefixtomodifytherequest//URL'spathbeforetheFileServerseesit:!fs:=http.FileServer(http.Dir("public"))http.Handle("/public/",http.StripPrefix("/public/",fs)) }

Page 6: Writing HTTP Middleware In Go

funcStripPrefix(prefixstring,hHandler)Handler{ifprefix==""{returnh}returnHandlerFunc(func(wResponseWriter,r*Request){ifp:=strings.TrimPrefix(r.URL.Path,prefix);len(p)<len(r.URL.Path){r.URL.Path=ph.ServeHTTP(w,r)}else{NotFound(w,r)}})}

StripPrefix Function

Page 7: Writing HTTP Middleware In Go

Pattern for Writing HTTP Middleware

.

funcmiddlewareHandler(nexthttp.Handler)http.Handler{returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){//Ourmiddlewarelogicgoesherebefore //executingapplicationhandlernext.ServeHTTP(w,r)//Ourmiddlewarelogicgoeshereafter //executingapplicationhandler})}

Page 8: Writing HTTP Middleware In Go

Writing a Logging MiddlewarefuncloggingHandler(nexthttp.Handler)http.Handler{returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){! //Beforeexecutingthehandler!start:=time.Now()log.Printf("Started%s%s",r.Method,r.URL.Path)next.ServeHTTP(w,r)! //Afterexecutingthehandler!log.Printf("Completed%sin%v",r.URL.Path,time.Since(start))})}

• Parameter of type http.Handler!• Returns http.Handler type

Page 9: Writing HTTP Middleware In Go

!!funcindex(whttp.ResponseWriter,r*http.Request){fmt.Fprintf(w,"Welcome!")}funcabout(whttp.ResponseWriter,r*http.Request){fmt.Fprintf(w,"About")}funcmain(){http.Handle("/",loggingHandler(http.HandlerFunc(index)))http.Handle("/about",loggingHandler(http.HandlerFunc(about)))!server:=&http.Server{Addr:":3000",}server.ListenAndServe()}

Using the Logging Middleware

Page 10: Writing HTTP Middleware In Go

Middleware Chaining

http.Handle("/",middlewareFirst(middlewareSecond(loggingHandler(http.HandlerFunc(index)))))

Page 11: Writing HTTP Middleware In Go

Using HTTP Middleware with Negroni Package

Page 12: Writing HTTP Middleware In Go

Install Negroni:!

$ go get github.com/codegangsta/negroni!

Import Negroni package:!

import "github.com/codegangsta/negroni"

Page 13: Writing HTTP Middleware In Go

//Handlerhandlerisaninterfacethatobjects//canimplementtoberegisteredtoserveasmiddleware//intheNegronimiddlewarestack.//ServeHTTPshouldyieldtothenextmiddleware//inthechainbyinvokingthenexthttp.HandlerFunc//passedin.////IftheHandlerwritestotheResponseWriter,thenexthttp.HandlerFuncshouldnotbeinvoked.typeHandlerinterface{ServeHTTP(rwhttp.ResponseWriter,r*http.Request,nexthttp.HandlerFunc)}!//HandlerFuncisanadaptertoallowtheuseof//ordinaryfunctionsasNegronihandlers.typeHandlerFuncfunc(rwhttp.ResponseWriter,r*http.Request,nexthttp.HandlerFunc)!func(hHandlerFunc)ServeHTTP(rwhttp.ResponseWriter,r*http.Request,nexthttp.HandlerFunc){h(rw,r,next)}

Page 14: Writing HTTP Middleware In Go

Writing HTTP Middleware with Negroni

funcMyMiddleware(rwhttp.ResponseWriter,r*http.Request,nexthttp.HandlerFunc){//logicbeforeexecutingthenexthandlernext(rw,r)//logicafterexecutingthenexthandler}

Page 15: Writing HTTP Middleware In Go

Mapping Middleware Chaining with Negroni

funcmain(){mux:=http.NewServeMux()//mapyourroutesheren:=negroni.New()//YoucanmapittothehandlerchainwiththeUsefunction:n.Use(negroni.HandlerFunc(MyMiddleware))n.UseHandler(mux)server:=&http.Server{Addr:":8080",Handler:n,}server.ListenAndServe()}

Page 16: Writing HTTP Middleware In Go

Register Middleware Handlers for Specific Routes

router:=mux.NewRouter()adminRoutes:=mux.NewRouter()!//addadminrouteshere...!//AddroutespecificMiddlewareto“/admin”routerouter.Handle("/admin",negroni.New(Middleware1,Middleware2,negroni.Wrap(adminRoutes),))

Page 17: Writing HTTP Middleware In Go

Applying an Authentication Middleware into Specific Routes

Page 18: Writing HTTP Middleware In Go

//MiddlewareforvalidatingJWTtokensfuncAuthorize(whttp.ResponseWriter,r*http.Request,nexthttp.HandlerFunc){//validatethetokentoken,err:=jwt.ParseFromRequest(r,func(token*jwt.Token)(interface{},error){!//Verifythetokenwithpublickey,whichisthecounterpartofprivatekeyreturnverifyKey,nil})!iferr!=nil{switcherr.(type){!case*jwt.ValidationError://JWTvalidationerrorvErr:=err.(*jwt.ValidationError)!switchvErr.Errors{casejwt.ValidationErrorExpired://JWTexpiredDisplayAppError(w,err,"AccessTokenisexpired,getanewToken",401)return!default:DisplayAppError(w,err,"ErrorwhileparsingtheAccessToken!",500)return}!default:DisplayAppError(w,err,"ErrorwhileparsingAccessToken!",500)return}!}iftoken.Valid{next(w,r)}else{DisplayAppError(w,err,"InvalidAccessToken",401)!}}

Page 19: Writing HTTP Middleware In Go

//Routesfor“/users”pathfuncSetUserRoutes(router*mux.Router)*mux.Router{router.HandleFunc("/users/register",controllers.Register).Methods("POST")router.HandleFunc("/users/login",controllers.Login).Methods("POST")returnrouter}!//Routesfor“/tasks”pathfuncSetTaskRoutes(router*mux.Router)*mux.Router{taskRouter:=mux.NewRouter()taskRouter.HandleFunc("/tasks",controllers.CreateTask).Methods("POST")taskRouter.HandleFunc("/tasks/{id}",controllers.UpdateTask).Methods(“PUT”)...!//ApplyAuthorizemiddlewareinto“/tasks”path!router.PathPrefix("/tasks").Handler(negroni.New(negroni.HandlerFunc(Authorize),negroni.Wrap(taskRouter),))returnrouter}

Page 20: Writing HTTP Middleware In Go

THANKS

Shiju [email protected]

https://medium.com/@shijuvar https://github.com/shijuvar