44
Building Your First Web App in Go Andy Watson Ionic Security #ATOWebGo #ATO2015 All Things Open 2015

How to Build Your First Web App in Go

Embed Size (px)

Citation preview

Using Cryptography Properly in Applications

Building Your First Web App in GoAndy WatsonIonic Security#ATOWebGo #ATO2015All Things Open2015

Hello everyone, thank you for coming. Im Andy Watson and Im here to talk to you about ways to use cryptography correctly in your applications

About MeWho:Andy WatsonWhat:Code FlingerWhere:Ionic Security

http://ionic.com/@andrewwatson

Im currently a senior engineer at Ionic Security which is a data protection security company based out of Atlanta, GA

Ive been a software developer professionally since 1996 when I got my first job developing large scale, distributed systems for processing streams of data collected out of particle accelerators with some Physics professors at FSU. This was cloud computing before it had a name.

Since then Ive built mobile, desktop and web applications for companies like The Walt Disney World Resort, Maersk Sealand, Cox Communications, CoffeeCup Software and many many others.

I used to write PHPLots of PHP.

Tons.

Im a Gopher Now

Take the Tour at golang.org

Web Apps in GoNo need for a wrapper like Apache or NginxCreate a self-contained, statically compiled binaryCross Compile from your laptop to your server architecture

Simple Web Apppackage main

import ("fmt""net/http")

func main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprint(w, "Hello, world\n")})fmt.Print("Listening on :8080\n")http.ListenAndServe(":8080", nil)}

TemplatesEasily render well formed HTML using data from your application

Nest templates inside each other (partials) for easy re-use

Simple Template Example

func handleRoot(w http.ResponseWriter, req *http.Request) {var templateStr = "{{.}}\n"var templ = template.Must(template.New("qr").Parse(templateStr))templ.Execute(w, "Hello!")}

func main() {http.HandleFunc("/", handleRoot)fmt.Print("Listening on :8080\n")http.ListenAndServe(":8080", nil)}

Simple Logic{{if .}} Something!{{else}} None{{end}}

Iterationstype Book struct { Author, Title string}

func handler(w http.ResponseWriter, r *http.Request) { // var bookList Book[] bookList, err := lookupBooksForSale() templ.Execute(w, bookList)

}

Template with range OperatorBooks For Sale{{range .}} {{.Title}} by {{.Author}} {{else}} Sorry.{{end}}

OutputsSorry.

The Thing by Stephen KingMoby Dick by Herman Melville

With Empty List

With Data

Its the Methods, man!func uploadHandler() {if r.Method != "POST" {err := doPostThings()handleErrors(err)return}}

RoutingUse a routing library like httprouter or mux to match requests to handlers

Routes defined using paths and HTTP verbs

r := httprouter.New() r.POST(/login", LoginHandler) r.GET("/", HomeHandler)

MiddleWareGets executed with every request

Used for logging, instrumentation, error handling and more

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

n := negroni.Classic() n.UseHandler(mux) n.Run(":3000")}

https://github.com/codegangsta/negroni

Negroni ClassicCommon set of middlewareLoggingRecovery (from panics)Static Content Handling

RenderCleans Up boilerplate template rendering codeHandles ErrorsTakes care of headers for HTML, JSON, XML etc

https://github.com/unrolled/render

ContextStores values shared during a request lifetimeUseful for easily passing the full context of a request to multiple handlers

http://www.gorillatoolkit.org/pkg/context

SessionsKeep data between requests to maintain stateUser informationShopping CartETC

http://www.gorillatoolkit.org/pkg/sessions

Setting up Session Handlingvar sessionstore = sessions.NewCookieStore([]byte(secret))

func init() {sessionstore.Options = &sessions.Options{Path: "/",MaxAge: 3600,HttpOnly: true,}}

Using Sessionssession, _ := sessionstore.Get(req, "OthrNumbr-session")

session.Values["loggedin"] = truesession.Values["cust_id"] = cust.CustomerIdsession.Values["description"] = cust.Description

session.Save(req, w)http.Redirect(w, req, "/home/", 302)

Rapid DevelopmentGin wraps your processRecompiles and Restarts Automaticallyhttps://github.com/codegangsta/gin

Deploy to ProductionCross Compile for LinuxSCP to productionWrap in upstart script etc

Get up and Go

Contain Yourself

The GoLang library Docker images make it easy to build and run your Go app in a container

https://hub.docker.com/_/golang/

DockerfileFROM golang:1.5-onbuild

Docker Commands$ docker build -t hello-world .$ docker run --rm -it --name fred hello-world

Google App EngineGAE supports Go runtimeAutomatically scales up instancesProvides highly available datastoreSupports Go 1.4 at this timeSoon: Migrate GAE to Managed VMs

https://cloud.google.com/appengine/

GAE DataStoretype Greeting struct { Author string Content string Date time.Time}

Fetch from DataStorefunc root(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) q := datastore.NewQuery("Greeting"). Ancestor(guestbookKey(c)).Order("-Date").Limit(10)

greetings := make([]Greeting, 0, 10) if _, err := q.GetAll(c, &greetings); err != nil { http.Error(w, err.Error(),500) return }}

GAE Examplehttps://github.com/GoogleCloudPlatform/appengine-guestbook-go

Shows session handling, data storage, authentication and more

Other ResourcesBuilding Web Apps with Go by codegangtsahttp://bit.ly/WebAppsWithGo

Google Cloud Platform - Gohttp://bit.ly/GoGoogleCloud

Deployed To GAESMS Voting Application for CSS Dev ConfTakes votes via SMS (Twilio) and stores them in GAE DatastoreOutputs them as CSV

Deployed to GAEOthrNumbrBurner Numbers for texting with strangersWritten in Go, Deployed on App EngineUsers Datastore, memcache, Twilio, Stripe

http://othrnumbr.com/

@andrewwatsonhttp://about.me/andrewwatsonThank You

Kitty wants to learn concurrency

Concurrency in GoIn Go, concurrency is accomplished by passing shared values around on channelsNot by sharing memory between threads

Repeat After MeDo not communicate by sharing memory; instead, share memory by communicating.

Concurrent RoutinesCreated by putting go in front of function calls

func Announce(message string, delay time.Duration) { go func() { time.Sleep(delay) fmt.Println(message) }() // Note the parentheses - must call the function.}

https://golang.org/doc/effective_go.html#concurrency

ChannelsGo has a built in primitive types for communicating between goroutines

c := make(chan int) // Allocate a channel.

// Start the sort in a goroutine; when it completes, signal on the channel.go func() { list.Sort() c