github.com/wanliu/go-oauth2-server@v0.0.0-20180817021415-f928fa1580df/web/render.go (about) 1 package web 2 3 import ( 4 "fmt" 5 // "html/template" 6 "net/http" 7 "path/filepath" 8 9 "github.com/arschles/go-bindata-html-template" 10 11 "github.com/oxtoacart/bpool" 12 ) 13 14 //go:generate go-bindata -pkg web includes layouts 15 16 var ( 17 templates map[string]*template.Template 18 bufpool *bpool.BufferPool 19 loaded = false 20 ) 21 22 func raw(x string) interface{} { return template.HTML(x) } 23 24 // renderTemplate is a wrapper around template.ExecuteTemplate. 25 // It writes into a bytes.Buffer before writing to the http.ResponseWriter to catch 26 // any errors resulting from populating the template. 27 func renderTemplate(w http.ResponseWriter, name string, data map[string]interface{}) error { 28 loadTemplates() 29 30 // Ensure the template exists in the map. 31 tmpl, ok := templates[name] 32 if !ok { 33 return fmt.Errorf("The template %s does not exist", name) 34 } 35 36 // Create a buffer to temporarily write to and check if any errors were encountered. 37 buf := bufpool.Get() 38 defer bufpool.Put(buf) 39 40 err := tmpl.ExecuteTemplate(buf, "base", data) 41 if err != nil { 42 return err 43 } 44 45 // The X-Frame-Options HTTP response header can be used to indicate whether 46 // or not a browser should be allowed to render a page in a <frame>, 47 // <iframe> or <object> . Sites can use this to avoid clickjacking attacks, 48 // by ensuring that their content is not embedded into other sites. 49 w.Header().Set("X-Frame-Options", "deny") 50 // Set the header and write the buffer to the http.ResponseWriter 51 w.Header().Set("Content-Type", "text/html; charset=utf-8") 52 buf.WriteTo(w) 53 return nil 54 } 55 56 func loadTemplates() { 57 if loaded { 58 return 59 } 60 61 templates = make(map[string]*template.Template) 62 63 bufpool = bpool.NewBufferPool(64) 64 65 layoutTemplates := map[string][]string{ 66 "layouts/index.html": { 67 "includes/index.html", 68 }, 69 "layouts/outside.html": { 70 "includes/register.html", 71 "includes/login.html", 72 }, 73 "layouts/inside.html": { 74 "includes/authorize.html", 75 "includes/account.html", 76 }, 77 "layouts/profile.html": { 78 "includes/clients.html", 79 "includes/new_client.html", 80 "includes/client_detail.html", 81 }, 82 } 83 84 funcMap := template.FuncMap{ 85 "raw": raw, 86 } 87 88 for layout, includes := range layoutTemplates { 89 for _, include := range includes { 90 files := []string{include, layout} 91 92 templates[filepath.Base(include)] = template.Must(template.New("", Asset).Funcs(funcMap).ParseFiles(files...)) 93 } 94 } 95 96 loaded = true 97 }