Performance improvements when rendering

- Fast path for JSON, XML and plain text rendering
This commit is contained in:
Manu Mtz-Almeida
2015-05-07 12:44:52 +02:00
parent eb3e9293ed
commit 2d8f0a4801
10 changed files with 299 additions and 163 deletions

View File

@ -4,103 +4,24 @@
package render
import (
"encoding/json"
"encoding/xml"
"fmt"
"html/template"
"net/http"
)
import "net/http"
type (
Render interface {
Render(http.ResponseWriter, int, ...interface{}) error
}
jsonRender struct{}
indentedJSON struct{}
xmlRender struct{}
plainTextRender struct{}
htmlPlainRender struct{}
redirectRender struct{}
HTMLRender struct {
Template *template.Template
}
)
type Render interface {
Render(http.ResponseWriter, int, ...interface{}) error
}
var (
JSON = jsonRender{}
IndentedJSON = indentedJSON{}
XML = xmlRender{}
HTMLPlain = htmlPlainRender{}
Plain = plainTextRender{}
Redirect = redirectRender{}
JSON Render = jsonRender{}
IndentedJSON Render = indentedJSON{}
XML Render = xmlRender{}
HTMLPlain Render = htmlPlainRender{}
Plain Render = plainTextRender{}
Redirect Render = redirectRender{}
Data Render = dataRender{}
_ Render = HTMLRender{}
_ Render = &HTMLDebugRender{}
)
func (_ redirectRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
req := data[0].(*http.Request)
location := data[1].(string)
http.Redirect(w, req, location, 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 (_ indentedJSON) Render(w http.ResponseWriter, code int, data ...interface{}) error {
WriteHeader(w, code, "application/json")
jsonData, err := json.MarshalIndent(data[0], "", " ")
if err != nil {
return err
}
_, err = w.Write(jsonData)
return err
}
func (_ xmlRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
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")
format := data[0].(string)
args := data[1].([]interface{})
if len(args) > 0 {
_, err = fmt.Fprintf(w, format, args...)
} else {
_, err = w.Write([]byte(format))
}
return
}
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{})
if len(args) > 0 {
_, err = fmt.Fprintf(w, format, args...)
} else {
_, err = w.Write([]byte(format))
}
return
}
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 WriteHeader(w http.ResponseWriter, code int, contentType string) {
contentType = joinStrings(contentType, "; charset=utf-8")
w.Header().Set("Content-Type", contentType)