Bläddra i källkod

Fixes debug HTML rendering:

- Stateless algorithm
Manu Mtz-Almeida 10 år sedan
förälder
incheckning
df3ed787e1
3 ändrade filer med 89 tillägg och 57 borttagningar
  1. 4 4
      gin.go
  2. 50 0
      render/html_debug.go
  3. 35 53
      render/render.go

+ 4 - 4
gin.go

@@ -76,8 +76,8 @@ func (engine *Engine) allocateContext() (c *Context) {
 
 func (engine *Engine) LoadHTMLGlob(pattern string) {
 	if IsDebugging() {
-		render.HTMLDebug.AddGlob(pattern)
-		engine.HTMLRender = render.HTMLDebug
+		r := &render.HTMLDebugRender{Glob: pattern}
+		engine.HTMLRender = r
 	} else {
 		templ := template.Must(template.ParseGlob(pattern))
 		engine.SetHTMLTemplate(templ)
@@ -86,8 +86,8 @@ func (engine *Engine) LoadHTMLGlob(pattern string) {
 
 func (engine *Engine) LoadHTMLFiles(files ...string) {
 	if IsDebugging() {
-		render.HTMLDebug.AddFiles(files...)
-		engine.HTMLRender = render.HTMLDebug
+		r := &render.HTMLDebugRender{Files: files}
+		engine.HTMLRender = r
 	} else {
 		templ := template.Must(template.ParseFiles(files...))
 		engine.SetHTMLTemplate(templ)

+ 50 - 0
render/html_debug.go

@@ -0,0 +1,50 @@
+// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
+// Use of this source code is governed by a MIT style
+// license that can be found in the LICENSE file.
+
+package render
+
+import (
+	"html/template"
+	"net/http"
+)
+
+type HTMLDebugRender struct {
+	files []string
+	globs []string
+}
+
+func (r *HTMLDebugRender) AddGlob(pattern string) {
+	r.globs = append(r.globs, pattern)
+}
+
+func (r *HTMLDebugRender) AddFiles(files ...string) {
+	r.files = append(r.files, files...)
+}
+
+func (r *HTMLDebugRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
+	WriteHeader(w, code, "text/html")
+	file := data[0].(string)
+	obj := data[1]
+
+	if t, err := r.newTemplate(); err == nil {
+		return t.ExecuteTemplate(w, file, obj)
+	} else {
+		return err
+	}
+}
+
+func (r *HTMLDebugRender) newTemplate() (*template.Template, error) {
+	t := template.New("")
+	if len(r.files) > 0 {
+		if _, err := t.ParseFiles(r.files...); err != nil {
+			return nil, err
+		}
+	}
+	for _, glob := range r.globs {
+		if _, err := t.ParseGlob(glob); err != nil {
+			return nil, err
+		}
+	}
+	return t, nil
+}

+ 35 - 53
render/render.go

@@ -27,11 +27,6 @@ type (
 
 	redirectRender struct{}
 
-	htmlDebugRender struct {
-		files []string
-		globs []string
-	}
-
 	HTMLRender struct {
 		Template *template.Template
 	}
@@ -43,34 +38,26 @@ var (
 	HTMLPlain = htmlPlainRender{}
 	Plain     = plainTextRender{}
 	Redirect  = redirectRender{}
-	HTMLDebug = &htmlDebugRender{}
 )
 
-func writeHeader(w http.ResponseWriter, code int, contentType string) {
-	w.Header().Set("Content-Type", contentType+"; charset=utf-8")
-	w.WriteHeader(code)
-}
-
-func (_ jsonRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
-	writeHeader(w, code, "application/json")
-	encoder := json.NewEncoder(w)
-	return encoder.Encode(data[0])
-}
-
 func (_ redirectRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
 	w.Header().Set("Location", data[0].(string))
 	w.WriteHeader(code)
 	return nil
 }
 
+func (_ jsonRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
+	WriteHeader(w, code, "application/json")
+	return json.NewEncoder(w).Encode(data[0])
+}
+
 func (_ xmlRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
-	writeHeader(w, code, "application/xml")
-	encoder := xml.NewEncoder(w)
-	return encoder.Encode(data[0])
+	WriteHeader(w, code, "application/xml")
+	return xml.NewEncoder(w).Encode(data[0])
 }
 
 func (_ plainTextRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
-	writeHeader(w, code, "text/plain")
+	WriteHeader(w, code, "text/plain")
 	format := data[0].(string)
 	args := data[1].([]interface{})
 	if len(args) > 0 {
@@ -81,52 +68,47 @@ func (_ plainTextRender) Render(w http.ResponseWriter, code int, data ...interfa
 	return
 }
 
-func (_ htmlPlainRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
-	writeHeader(w, code, "text/html")
+func (_ htmlPlainRender) Render(w http.ResponseWriter, code int, data ...interface{}) (err error) {
+	WriteHeader(w, code, "text/html")
 	format := data[0].(string)
 	args := data[1].([]interface{})
-	var err error
 	if len(args) > 0 {
 		_, err = w.Write([]byte(fmt.Sprintf(format, args...)))
 	} else {
 		_, err = w.Write([]byte(format))
 	}
-	return err
+	return
 }
 
-func (r *htmlDebugRender) AddGlob(pattern string) {
-	r.globs = append(r.globs, pattern)
+func (html HTMLRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
+	WriteHeader(w, code, "text/html")
+	file := data[0].(string)
+	args := data[1]
+	return html.Template.ExecuteTemplate(w, file, args)
 }
 
-func (r *htmlDebugRender) AddFiles(files ...string) {
-	r.files = append(r.files, files...)
+func WriteHeader(w http.ResponseWriter, code int, contentType string) {
+	contentType = joinStrings(contentType, "; charset=utf-8")
+	w.Header().Set("Content-Type", contentType)
+	w.WriteHeader(code)
 }
 
-func (r *htmlDebugRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
-	writeHeader(w, code, "text/html")
-	file := data[0].(string)
-	obj := data[1]
-
-	t := template.New("")
-
-	if len(r.files) > 0 {
-		if _, err := t.ParseFiles(r.files...); err != nil {
-			return err
-		}
+func joinStrings(a ...string) string {
+	if len(a) == 0 {
+		return ""
 	}
-
-	for _, glob := range r.globs {
-		if _, err := t.ParseGlob(glob); err != nil {
-			return err
-		}
+	if len(a) == 1 {
+		return a[0]
+	}
+	n := 0
+	for i := 0; i < len(a); i++ {
+		n += len(a[i])
 	}
 
-	return t.ExecuteTemplate(w, file, obj)
-}
-
-func (html HTMLRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
-	writeHeader(w, code, "text/html")
-	file := data[0].(string)
-	obj := data[1]
-	return html.Template.ExecuteTemplate(w, file, obj)
+	b := make([]byte, n)
+	n = 0
+	for _, s := range a {
+		n += copy(b[n:], s)
+	}
+	return string(b)
 }