SlideShare ist ein Scribd-Unternehmen logo
1 von 25
Downloaden Sie, um offline zu lesen
Customising Your Own Web
Framework in Go
20 January 2015
Jonathan Gomez
Engineer, Zumata
This Talk
Overview
- Intro to serving requests with http/net
- Customising Handlers
- Writing Middleware
- Ecosystem
Key takeaways
- Compared with Ruby/Node.js, mainly using the standard library is considered normal
- Interfaces and first-class functions make it easy to extend functionality
- Ecosystem of libraries that work alongside http/netis growing
Intro to Serving Requests with http/net
Serving Requests via Standard Lib (1/4)
packagemain
import"net/http"
funchandlerFn(whttp.ResponseWriter,r*http.Request){
w.Write([]byte(`Helloworld!`))
}
funcmain(){
http.HandleFunc("/",handlerFn)
http.ListenAndServe("localhost:4000",nil)
}
ListenAndServe - creates server that will listen for requests
Each request spawns a go routine: goc.serve()
Serving Requests via Standard Lib (2/4)
ServeMux matches incoming request against a list of patterns (method/host/url)
ServeMux is a special kind of Handlerwhich calls another Handler
Handler interface
typeHandlerinterface{
ServeHTTP(ResponseWriter,*Request)
}
Serving Requests via Standard Lib (3/4)
Request handling logic in ordinary function func(ResponseWriter,*Request)
funcfinal(whttp.ResponseWriter,r*http.Request){
w.Write([]byte("OK"))
}
Register the function as a Handler on DefaultServeMux
http.Handle("/",http.HandlerFunc(final))
Also can:
http.HandleFunc("/",final)
Serving Requests via Standard Lib (4/4)
func(ResponseWriter,*Request)
ResponseWriter interface
typeResponseWriterinterface{
Header()Header
Write([]byte)(int,error)
WriteHeader(int)
}
Request struct
typeRequeststruct{
Methodstring
URL*url.URL
HeaderHeader
Bodyio.ReadCloser
ContentLengthint64
Hoststring
RemoteAddrstring
...
}
Customising Handlers
Demo: Customising Handlers - DRY Response Handling (1/3)
typeappHandlerstruct{
hfunc(http.ResponseWriter,*http.Request)(error)
}
func(ahappHandler)ServeHTTP(whttp.ResponseWriter,r*http.Request){
err:=ah.h(w,r)
iferr!=nil{
switcherr:=err.(type){
caseErrorDetails:
ErrorJSON(w,err)
default:
ErrorJSON(w,ErrorDetails{"InternalServerError","",500})
}
}
}
In app code we might extend this further:
Add error types and respond differently.
e.g. warn vs error-level log, send alerts, increment error metrics
Demo: Customising Handlers - DRY Response Handling (2/3)
typeErrorDetailsstruct{
Messagestring`json:"error"`
Detailsstring`json:"details,omitempty"`
Statusint`json:"-"`
}
func(eErrorDetails)Error()string{
returnfmt.Sprintf("Error:%s,Details:%s",e.Message,e.Details)
}
funcErrorJSON(whttp.ResponseWriter,detailsErrorDetails){
jsonB,err:=json.Marshal(details)
iferr!=nil{
http.Error(w,err.Error(),500)
return
}
w.Header().Set("Content-Type","application/json")
w.WriteHeader(details.Status)
w.Write(jsonB)
}
Demo: Customising Handlers - DRY Response Handling (3/3)
Use of special struct and special handler function to satisfy Handlerinterface
http.Handle("/",appHandler{unstableEndpoint})
Reduce repetition, extend functionality.
funcunstableEndpoint(whttp.ResponseWriter,r*http.Request)(error){
ifrand.Intn(100)>60{
returnErrorDetails{"Strangerequest","Pleasetryagain.",422}
}
ifrand.Intn(100)>80{
returnErrorDetails{"Seriousfailure","Weareinvestigating.",500}
}
w.Write([]byte(`{"ok":true}`))
returnnil
} Run
Demo: Customising Handlers - Avoiding Globals
Allows injecting dependencies rather than relying on global variables.
typeApistruct{
importantThingstring
//db*gorp.DbMap
//redis*redis.Pool
//logger...
}
typeappHandlerstruct{
*Api
hfunc(*Api,http.ResponseWriter,*http.Request)
}
func(ahappHandler)ServeHTTP(whttp.ResponseWriter,r*http.Request){
ah.h(ah.Api,w,r)
}
funcmyHandler(a*Api,whttp.ResponseWriter,r*http.Request){
w.Write([]byte("2015:Yearofthe"+a.importantThing))
} Run
Writing Middleware
Middleware: Why?
Abstract common functionality across a set of handlers
Bare minimum in Go:
func(nexthttp.Handler)http.Handler
Typical uses of middleware across languages/frameworks:
- logging
- authentication
- handling panic / exceptions
- gzipping
- request parsing
Demo: Middleware Example (Panic Recovery)
funcrecoveryMiddleware(nexthttp.Handler)http.Handler{
returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){
deferfunc(){
iferr:=recover();err!=nil{
log.Println("Recoverfromerror:",err)
http.Error(w,http.StatusText(500),500)
}
}()
log.Println("ExecutingrecoveryMiddleware")
next.ServeHTTP(w,r)
})
}
funcfinal(whttp.ResponseWriter,r*http.Request){
log.Println("ExecutingfinalHandler")
panic("walau!")
w.Write([]byte("OK"))
} Run
Demo: Chaining Middleware
funcmiddlewareOne(nexthttp.Handler)http.Handler{
returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){
log.Println("->ExecutingmiddlewareOne")
next.ServeHTTP(w,r)
log.Println("->ExecutingmiddlewareOneagain")
})
}
Calling chain of middleware
http.Handle("/",middlewareOne(middlewareTwo(http.HandlerFunc(final))))
funcmiddlewareTwo(nexthttp.Handler)http.Handler{
returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){
log.Println("--->ExecutingmiddlewareTwo")
next.ServeHTTP(w,r)
log.Println("--->ExecutingmiddlewareTwoagain")
})
} Run
Chaining Middleware - Alternate Syntax
3rd Party Library: Alice
Manages middleware with the standard function signature
Nice syntax for setting up chains used in different endpoints
chain:=alice.New(middlewareOne,middlewareTwo)
http.Handle("/",chain.Then(finalHandler))
Our example
noAuthChain:=alice.New(contextMiddleware,loggerMiddleware)
authChain:=alice.New(contextMiddleware,loggerMiddleware,apiKeyAuthMiddleware)
adminChain:=alice.New(contextMiddleware,loggerMiddleware,adminAuthMiddleware)
Demo: Creating Configurable Middleware
e.g. Pass the dependency on *AppLogger
varlogger*AppLogger=NewLogger()
loggerMiddleware:=simpleLoggerMiddlewareWrapper(logger)
http.Handle("/",loggerMiddleware(http.HandlerFunc(final)))
funcsimpleLoggerMiddlewareWrapper(logger*AppLogger)func(http.Handler)http.Handler{
returnfunc(nexthttp.Handler)http.Handler{
returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){
startTime:=time.Now()
next.ServeHTTP(w,r)
endTime:=time.Since(startTime)
logger.Info(r.Method+""+r.URL.String()+""+endTime.String())
})
}
} Run
Demo: Customising ResponseWriter (1/3)
typeResponseWriterinterface{
Header()http.Header
Write([]byte)(int,error)
WriteHeader(int)
}
ResponseWriter as an interface allows us to extend functionality easily
Example:
Step 1: Create a struct that wraps ResponseWriter
typeresponseWriterLoggerstruct{
w http.ResponseWriter
datastruct{
statusint
size int
}
}
Record data that would be otherwise be untracked.
Demo: Customising ResponseWriter (2/3)
Step 2: Define methods required for implicit satisfaction
func(l*responseWriterLogger)Header()http.Header{
returnl.w.Header()
}
func(l*responseWriterLogger)Write(b[]byte)(int,error){
//scenariowhereWriteHeaderhasnotbeencalled
ifl.data.status==0{
l.data.status=http.StatusOK
}
size,err:=l.w.Write(b)
l.data.size+=size
returnsize,err
}
func(l*responseWriterLogger)WriteHeader(codeint){
l.w.WriteHeader(code)
l.data.status=code
}
Demo: Customising ResponseWriter (3/3)
funcspecialLoggerMiddlewareWrapper(logger*AppLogger)func(http.Handler)http.Handler{
returnfunc(nexthttp.Handler)http.Handler{
returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){
startTime:=time.Now()
w2:=&responseWriterLogger{w:w}
next.ServeHTTP(w2,r)
logger.Info(r.Method+""+r.URL.String()+""+
time.Since(startTime).String()+
"status:"+strconv.Itoa(w2.data.status)+
"size:"+strconv.Itoa(w2.data.size))
})
}
} Run
Growing Middleware Ecosystem
Excerpt from Negroni Github page
graceful:(https://github.com/stretchr/graceful)graceful HTTP Shutdown
oauth2:(https://github.com/goincremental/negroni-oauth2)oAuth2 middleware
binding:(https://github.com/mholt/binding)data binding from HTTP requests into structs
xrequestid:(https://github.com/pilu/xrequestid)Assign a random X-Request-Id: header to each request
gorelic:(https://github.com/jingweno/negroni-gorelic)New Relic agent for Go runtime
Mailgun's Oxy
stream:(http://godoc.org/github.com/mailgun/oxy/stream)retries and buffers requests and responses
connlimit:(http://godoc.org/github.com/mailgun/oxy/connlimit)Simultaneous connections limiter
ratelimit:(http://godoc.org/github.com/mailgun/oxy/ratelimit)Rate limiter
Other Web Framework Components
Routing & Extracting URL Params
- standard library can be inflexible
- regex for extracting url params can feel too low level
- plenty of third party routers, e.g. Gorilla mux
funcShowWidget(whttp.ResponseWriter,r*http.Request){
vars:=mux.Vars(r)
teamIdStr:=vars["team_id"]
widgetIdStr:=vars["widget_id"]
...
}
Request-specific context
- sharing data between items in middleware chain and final handler
- solutions involve either global map, or per-request map/structs using custom
handlers/middleware
Web frameworks vs Build on top of standard library?
Time/expertise to build what you need? Too much re-inventing?
Your optimisation vs framework optimisation?
Performance? Does performance order of magnitude matter?
How much magic do you want?
Compatibility with net/http/ ecosystem? Framework interchangeability?
Martini -- 6.1k(https://github.com/go-martini/martini)
Revel -- 4.7k(https://github.com/revel/revel)
beego -- 3.7k(https://github.com/astaxie/beego)
goji -- 1.9k(https://github.com/zenazn/goji)
gin -- 1.9k(https://github.com/gin-gonic/gin)
negroni -- 1.8k(https://github.com/codegangsta/negroni)
go-json-rest -- 1.1k(https://github.com/ant0ine/go-json-rest)
Gorilla/mux -- 1.1k(https://github.com/gorilla/mux)
Tiger Tonic -- 0.8k(https://github.com/rcrowley/go-tigertonic)
Gocraft/web -- 0.6k(https://github.com/gocraft/web)
Thank you
Jonathan Gomez
Engineer, Zumata
jonathanbgomez@gmail.com(mailto:jonathanbgomez@gmail.com)
@jonog(http://twitter.com/jonog)

Weitere ähnliche Inhalte

Was ist angesagt?

服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
Qiangning Hong
 

Was ist angesagt? (20)

Non blocking io with netty
Non blocking io with nettyNon blocking io with netty
Non blocking io with netty
 
The basics of fluentd
The basics of fluentdThe basics of fluentd
The basics of fluentd
 
Like loggly using open source
Like loggly using open sourceLike loggly using open source
Like loggly using open source
 
Dive into Fluentd plugin v0.12
Dive into Fluentd plugin v0.12Dive into Fluentd plugin v0.12
Dive into Fluentd plugin v0.12
 
JRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing WorldJRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing World
 
Fluentd meetup
Fluentd meetupFluentd meetup
Fluentd meetup
 
Centralized + Unified Logging
Centralized + Unified LoggingCentralized + Unified Logging
Centralized + Unified Logging
 
Introduction tomcat7 servlet3
Introduction tomcat7 servlet3Introduction tomcat7 servlet3
Introduction tomcat7 servlet3
 
Fluentd meetup #2
Fluentd meetup #2Fluentd meetup #2
Fluentd meetup #2
 
The basics of fluentd
The basics of fluentdThe basics of fluentd
The basics of fluentd
 
Elk with Openstack
Elk with OpenstackElk with Openstack
Elk with Openstack
 
Netty: asynchronous data transfer
Netty: asynchronous data transferNetty: asynchronous data transfer
Netty: asynchronous data transfer
 
WebTalk - Implementing Web Services with a dedicated Java daemon
WebTalk - Implementing Web Services with a dedicated Java daemonWebTalk - Implementing Web Services with a dedicated Java daemon
WebTalk - Implementing Web Services with a dedicated Java daemon
 
Fluentd v1.0 in a nutshell
Fluentd v1.0 in a nutshellFluentd v1.0 in a nutshell
Fluentd v1.0 in a nutshell
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
Fluentd unified logging layer
Fluentd   unified logging layerFluentd   unified logging layer
Fluentd unified logging layer
 
Fluentd v0.12 master guide
Fluentd v0.12 master guideFluentd v0.12 master guide
Fluentd v0.12 master guide
 
Troubleshooting RabbitMQ and services that use it
Troubleshooting RabbitMQ and services that use itTroubleshooting RabbitMQ and services that use it
Troubleshooting RabbitMQ and services that use it
 
Fluentd meetup dive into fluent plugin (outdated)
Fluentd meetup dive into fluent plugin (outdated)Fluentd meetup dive into fluent plugin (outdated)
Fluentd meetup dive into fluent plugin (outdated)
 
Fluentd - Set Up Once, Collect More
Fluentd - Set Up Once, Collect MoreFluentd - Set Up Once, Collect More
Fluentd - Set Up Once, Collect More
 

Andere mochten auch (7)

Cleanppp
CleanpppCleanppp
Cleanppp
 
Fronteers: UX in een Agile omgeving
Fronteers: UX in een Agile omgevingFronteers: UX in een Agile omgeving
Fronteers: UX in een Agile omgeving
 
IdentityPR Social Media 101 Presentation
IdentityPR Social Media 101 PresentationIdentityPR Social Media 101 Presentation
IdentityPR Social Media 101 Presentation
 
Portfolio
PortfolioPortfolio
Portfolio
 
Social Media Hr Advantage Preso V2
Social Media Hr Advantage Preso V2Social Media Hr Advantage Preso V2
Social Media Hr Advantage Preso V2
 
How to Think Like a Social Media Cowboy
How to Think Like a Social Media CowboyHow to Think Like a Social Media Cowboy
How to Think Like a Social Media Cowboy
 
Networking Presentation
Networking PresentationNetworking Presentation
Networking Presentation
 

Ähnlich wie Customising Your Own Web Framework In Go

nodejs_at_a_glance.ppt
nodejs_at_a_glance.pptnodejs_at_a_glance.ppt
nodejs_at_a_glance.ppt
WalaSidhom1
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Tom Croucher
 

Ähnlich wie Customising Your Own Web Framework In Go (20)

Knot.x: when Vert.x and RxJava meet
Knot.x: when Vert.x and RxJava meetKnot.x: when Vert.x and RxJava meet
Knot.x: when Vert.x and RxJava meet
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java
 
Native REST Web Services with Oracle 11g
Native REST Web Services with Oracle 11gNative REST Web Services with Oracle 11g
Native REST Web Services with Oracle 11g
 
Intro to Node
Intro to NodeIntro to Node
Intro to Node
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interface
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interface
 
Java 8 Feature Preview
Java 8 Feature PreviewJava 8 Feature Preview
Java 8 Feature Preview
 
Advancedservletsjsp
AdvancedservletsjspAdvancedservletsjsp
Advancedservletsjsp
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
nodejs_at_a_glance.ppt
nodejs_at_a_glance.pptnodejs_at_a_glance.ppt
nodejs_at_a_glance.ppt
 
Woo: Writing a fast web server @ ELS2015
Woo: Writing a fast web server @ ELS2015Woo: Writing a fast web server @ ELS2015
Woo: Writing a fast web server @ ELS2015
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
 
L11 Process Design
L11 Process DesignL11 Process Design
L11 Process Design
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Extending Retrofit for fun and profit
Extending Retrofit for fun and profitExtending Retrofit for fun and profit
Extending Retrofit for fun and profit
 
Networked APIs with swift
Networked APIs with swiftNetworked APIs with swift
Networked APIs with swift
 
Web Server and how we can design app in C#
Web Server and how we can design app  in C#Web Server and how we can design app  in C#
Web Server and how we can design app in C#
 
Nodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredevNodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredev
 
Frameworks
FrameworksFrameworks
Frameworks
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 

Kürzlich hochgeladen

result management system report for college project
result management system report for college projectresult management system report for college project
result management system report for college project
Tonystark477637
 

Kürzlich hochgeladen (20)

MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
Extrusion Processes and Their Limitations
Extrusion Processes and Their LimitationsExtrusion Processes and Their Limitations
Extrusion Processes and Their Limitations
 
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdfONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
 
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
UNIT-III FMM. DIMENSIONAL ANALYSIS
UNIT-III FMM.        DIMENSIONAL ANALYSISUNIT-III FMM.        DIMENSIONAL ANALYSIS
UNIT-III FMM. DIMENSIONAL ANALYSIS
 
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
 
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINEDJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
 
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
 
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
 
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...Top Rated  Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
Top Rated Pune Call Girls Budhwar Peth ⟟ 6297143586 ⟟ Call Me For Genuine Se...
 
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
 
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
 
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSMANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
 
result management system report for college project
result management system report for college projectresult management system report for college project
result management system report for college project
 
Introduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxIntroduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptx
 
UNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its PerformanceUNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its Performance
 
UNIT-II FMM-Flow Through Circular Conduits
UNIT-II FMM-Flow Through Circular ConduitsUNIT-II FMM-Flow Through Circular Conduits
UNIT-II FMM-Flow Through Circular Conduits
 

Customising Your Own Web Framework In Go

  • 1. Customising Your Own Web Framework in Go 20 January 2015 Jonathan Gomez Engineer, Zumata
  • 2. This Talk Overview - Intro to serving requests with http/net - Customising Handlers - Writing Middleware - Ecosystem Key takeaways - Compared with Ruby/Node.js, mainly using the standard library is considered normal - Interfaces and first-class functions make it easy to extend functionality - Ecosystem of libraries that work alongside http/netis growing
  • 3. Intro to Serving Requests with http/net
  • 4. Serving Requests via Standard Lib (1/4) packagemain import"net/http" funchandlerFn(whttp.ResponseWriter,r*http.Request){ w.Write([]byte(`Helloworld!`)) } funcmain(){ http.HandleFunc("/",handlerFn) http.ListenAndServe("localhost:4000",nil) } ListenAndServe - creates server that will listen for requests Each request spawns a go routine: goc.serve()
  • 5. Serving Requests via Standard Lib (2/4) ServeMux matches incoming request against a list of patterns (method/host/url) ServeMux is a special kind of Handlerwhich calls another Handler Handler interface typeHandlerinterface{ ServeHTTP(ResponseWriter,*Request) }
  • 6. Serving Requests via Standard Lib (3/4) Request handling logic in ordinary function func(ResponseWriter,*Request) funcfinal(whttp.ResponseWriter,r*http.Request){ w.Write([]byte("OK")) } Register the function as a Handler on DefaultServeMux http.Handle("/",http.HandlerFunc(final)) Also can: http.HandleFunc("/",final)
  • 7. Serving Requests via Standard Lib (4/4) func(ResponseWriter,*Request) ResponseWriter interface typeResponseWriterinterface{ Header()Header Write([]byte)(int,error) WriteHeader(int) } Request struct typeRequeststruct{ Methodstring URL*url.URL HeaderHeader Bodyio.ReadCloser ContentLengthint64 Hoststring RemoteAddrstring ... }
  • 9. Demo: Customising Handlers - DRY Response Handling (1/3) typeappHandlerstruct{ hfunc(http.ResponseWriter,*http.Request)(error) } func(ahappHandler)ServeHTTP(whttp.ResponseWriter,r*http.Request){ err:=ah.h(w,r) iferr!=nil{ switcherr:=err.(type){ caseErrorDetails: ErrorJSON(w,err) default: ErrorJSON(w,ErrorDetails{"InternalServerError","",500}) } } } In app code we might extend this further: Add error types and respond differently. e.g. warn vs error-level log, send alerts, increment error metrics
  • 10. Demo: Customising Handlers - DRY Response Handling (2/3) typeErrorDetailsstruct{ Messagestring`json:"error"` Detailsstring`json:"details,omitempty"` Statusint`json:"-"` } func(eErrorDetails)Error()string{ returnfmt.Sprintf("Error:%s,Details:%s",e.Message,e.Details) } funcErrorJSON(whttp.ResponseWriter,detailsErrorDetails){ jsonB,err:=json.Marshal(details) iferr!=nil{ http.Error(w,err.Error(),500) return } w.Header().Set("Content-Type","application/json") w.WriteHeader(details.Status) w.Write(jsonB) }
  • 11. Demo: Customising Handlers - DRY Response Handling (3/3) Use of special struct and special handler function to satisfy Handlerinterface http.Handle("/",appHandler{unstableEndpoint}) Reduce repetition, extend functionality. funcunstableEndpoint(whttp.ResponseWriter,r*http.Request)(error){ ifrand.Intn(100)>60{ returnErrorDetails{"Strangerequest","Pleasetryagain.",422} } ifrand.Intn(100)>80{ returnErrorDetails{"Seriousfailure","Weareinvestigating.",500} } w.Write([]byte(`{"ok":true}`)) returnnil } Run
  • 12. Demo: Customising Handlers - Avoiding Globals Allows injecting dependencies rather than relying on global variables. typeApistruct{ importantThingstring //db*gorp.DbMap //redis*redis.Pool //logger... } typeappHandlerstruct{ *Api hfunc(*Api,http.ResponseWriter,*http.Request) } func(ahappHandler)ServeHTTP(whttp.ResponseWriter,r*http.Request){ ah.h(ah.Api,w,r) } funcmyHandler(a*Api,whttp.ResponseWriter,r*http.Request){ w.Write([]byte("2015:Yearofthe"+a.importantThing)) } Run
  • 14. Middleware: Why? Abstract common functionality across a set of handlers Bare minimum in Go: func(nexthttp.Handler)http.Handler Typical uses of middleware across languages/frameworks: - logging - authentication - handling panic / exceptions - gzipping - request parsing
  • 15. Demo: Middleware Example (Panic Recovery) funcrecoveryMiddleware(nexthttp.Handler)http.Handler{ returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){ deferfunc(){ iferr:=recover();err!=nil{ log.Println("Recoverfromerror:",err) http.Error(w,http.StatusText(500),500) } }() log.Println("ExecutingrecoveryMiddleware") next.ServeHTTP(w,r) }) } funcfinal(whttp.ResponseWriter,r*http.Request){ log.Println("ExecutingfinalHandler") panic("walau!") w.Write([]byte("OK")) } Run
  • 16. Demo: Chaining Middleware funcmiddlewareOne(nexthttp.Handler)http.Handler{ returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){ log.Println("->ExecutingmiddlewareOne") next.ServeHTTP(w,r) log.Println("->ExecutingmiddlewareOneagain") }) } Calling chain of middleware http.Handle("/",middlewareOne(middlewareTwo(http.HandlerFunc(final)))) funcmiddlewareTwo(nexthttp.Handler)http.Handler{ returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){ log.Println("--->ExecutingmiddlewareTwo") next.ServeHTTP(w,r) log.Println("--->ExecutingmiddlewareTwoagain") }) } Run
  • 17. Chaining Middleware - Alternate Syntax 3rd Party Library: Alice Manages middleware with the standard function signature Nice syntax for setting up chains used in different endpoints chain:=alice.New(middlewareOne,middlewareTwo) http.Handle("/",chain.Then(finalHandler)) Our example noAuthChain:=alice.New(contextMiddleware,loggerMiddleware) authChain:=alice.New(contextMiddleware,loggerMiddleware,apiKeyAuthMiddleware) adminChain:=alice.New(contextMiddleware,loggerMiddleware,adminAuthMiddleware)
  • 18. Demo: Creating Configurable Middleware e.g. Pass the dependency on *AppLogger varlogger*AppLogger=NewLogger() loggerMiddleware:=simpleLoggerMiddlewareWrapper(logger) http.Handle("/",loggerMiddleware(http.HandlerFunc(final))) funcsimpleLoggerMiddlewareWrapper(logger*AppLogger)func(http.Handler)http.Handler{ returnfunc(nexthttp.Handler)http.Handler{ returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){ startTime:=time.Now() next.ServeHTTP(w,r) endTime:=time.Since(startTime) logger.Info(r.Method+""+r.URL.String()+""+endTime.String()) }) } } Run
  • 19. Demo: Customising ResponseWriter (1/3) typeResponseWriterinterface{ Header()http.Header Write([]byte)(int,error) WriteHeader(int) } ResponseWriter as an interface allows us to extend functionality easily Example: Step 1: Create a struct that wraps ResponseWriter typeresponseWriterLoggerstruct{ w http.ResponseWriter datastruct{ statusint size int } } Record data that would be otherwise be untracked.
  • 20. Demo: Customising ResponseWriter (2/3) Step 2: Define methods required for implicit satisfaction func(l*responseWriterLogger)Header()http.Header{ returnl.w.Header() } func(l*responseWriterLogger)Write(b[]byte)(int,error){ //scenariowhereWriteHeaderhasnotbeencalled ifl.data.status==0{ l.data.status=http.StatusOK } size,err:=l.w.Write(b) l.data.size+=size returnsize,err } func(l*responseWriterLogger)WriteHeader(codeint){ l.w.WriteHeader(code) l.data.status=code }
  • 21. Demo: Customising ResponseWriter (3/3) funcspecialLoggerMiddlewareWrapper(logger*AppLogger)func(http.Handler)http.Handler{ returnfunc(nexthttp.Handler)http.Handler{ returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){ startTime:=time.Now() w2:=&responseWriterLogger{w:w} next.ServeHTTP(w2,r) logger.Info(r.Method+""+r.URL.String()+""+ time.Since(startTime).String()+ "status:"+strconv.Itoa(w2.data.status)+ "size:"+strconv.Itoa(w2.data.size)) }) } } Run
  • 22. Growing Middleware Ecosystem Excerpt from Negroni Github page graceful:(https://github.com/stretchr/graceful)graceful HTTP Shutdown oauth2:(https://github.com/goincremental/negroni-oauth2)oAuth2 middleware binding:(https://github.com/mholt/binding)data binding from HTTP requests into structs xrequestid:(https://github.com/pilu/xrequestid)Assign a random X-Request-Id: header to each request gorelic:(https://github.com/jingweno/negroni-gorelic)New Relic agent for Go runtime Mailgun's Oxy stream:(http://godoc.org/github.com/mailgun/oxy/stream)retries and buffers requests and responses connlimit:(http://godoc.org/github.com/mailgun/oxy/connlimit)Simultaneous connections limiter ratelimit:(http://godoc.org/github.com/mailgun/oxy/ratelimit)Rate limiter
  • 23. Other Web Framework Components Routing & Extracting URL Params - standard library can be inflexible - regex for extracting url params can feel too low level - plenty of third party routers, e.g. Gorilla mux funcShowWidget(whttp.ResponseWriter,r*http.Request){ vars:=mux.Vars(r) teamIdStr:=vars["team_id"] widgetIdStr:=vars["widget_id"] ... } Request-specific context - sharing data between items in middleware chain and final handler - solutions involve either global map, or per-request map/structs using custom handlers/middleware
  • 24. Web frameworks vs Build on top of standard library? Time/expertise to build what you need? Too much re-inventing? Your optimisation vs framework optimisation? Performance? Does performance order of magnitude matter? How much magic do you want? Compatibility with net/http/ ecosystem? Framework interchangeability? Martini -- 6.1k(https://github.com/go-martini/martini) Revel -- 4.7k(https://github.com/revel/revel) beego -- 3.7k(https://github.com/astaxie/beego) goji -- 1.9k(https://github.com/zenazn/goji) gin -- 1.9k(https://github.com/gin-gonic/gin) negroni -- 1.8k(https://github.com/codegangsta/negroni) go-json-rest -- 1.1k(https://github.com/ant0ine/go-json-rest) Gorilla/mux -- 1.1k(https://github.com/gorilla/mux) Tiger Tonic -- 0.8k(https://github.com/rcrowley/go-tigertonic) Gocraft/web -- 0.6k(https://github.com/gocraft/web)
  • 25. Thank you Jonathan Gomez Engineer, Zumata jonathanbgomez@gmail.com(mailto:jonathanbgomez@gmail.com) @jonog(http://twitter.com/jonog)