瀏覽代碼

Adds flexible render system

Manu Mtz-Almeida 11 年之前
父節點
當前提交
5ea7a92267
共有 3 個文件被更改,包括 105 次插入42 次删除
  1. 5 0
      deprecated.go
  2. 31 42
      gin.go
  3. 69 0
      render/render.go

+ 5 - 0
deprecated.go

@@ -31,3 +31,8 @@ func (c *Context) ParseBody(item interface{}) error {
 func (engine *Engine) ServeFiles(path string, root http.FileSystem) {
 func (engine *Engine) ServeFiles(path string, root http.FileSystem) {
 	engine.router.ServeFiles(path, root)
 	engine.router.ServeFiles(path, root)
 }
 }
+
+// DEPRECATED use gin.LoadHTMLGlob() or gin.LoadHTMLFiles() instead
+func (engine *Engine) LoadHTMLTemplates(pattern string) {
+	engine.LoadHTMLGlob(pattern)
+}

+ 31 - 42
gin.go

@@ -2,11 +2,11 @@ package gin
 
 
 import (
 import (
 	"bytes"
 	"bytes"
-	"encoding/json"
 	"encoding/xml"
 	"encoding/xml"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"github.com/gin-gonic/gin/binding"
 	"github.com/gin-gonic/gin/binding"
+	"github.com/gin-gonic/gin/render"
 	"github.com/julienschmidt/httprouter"
 	"github.com/julienschmidt/httprouter"
 	"html/template"
 	"html/template"
 	"log"
 	"log"
@@ -71,10 +71,10 @@ type (
 	// Represents the web framework, it wraps the blazing fast httprouter multiplexer and a list of global middlewares.
 	// Represents the web framework, it wraps the blazing fast httprouter multiplexer and a list of global middlewares.
 	Engine struct {
 	Engine struct {
 		*RouterGroup
 		*RouterGroup
-		HTMLTemplates *template.Template
-		cache         sync.Pool
-		handlers404   []HandlerFunc
-		router        *httprouter.Router
+		HTMLRender  render.Render
+		cache       sync.Pool
+		handlers404 []HandlerFunc
+		router      *httprouter.Router
 	}
 	}
 )
 )
 
 
@@ -147,8 +147,20 @@ func Default() *Engine {
 	return engine
 	return engine
 }
 }
 
 
-func (engine *Engine) LoadHTMLTemplates(pattern string) {
-	engine.HTMLTemplates = template.Must(template.ParseGlob(pattern))
+func (engine *Engine) LoadHTMLGlob(pattern string) {
+	templ := template.Must(template.ParseGlob(pattern))
+	engine.SetHTTPTemplate(templ)
+}
+
+func (engine *Engine) LoadHTMLFiles(files ...string) {
+	templ := template.Must(template.ParseFiles(files...))
+	engine.SetHTTPTemplate(templ)
+}
+
+func (engine *Engine) SetHTTPTemplate(templ *template.Template) {
+	engine.HTMLRender = render.HTMLRender{
+		Template: templ,
+	}
 }
 }
 
 
 // Adds handlers for NotFound. It return a 404 code by default.
 // Adds handlers for NotFound. It return a 404 code by default.
@@ -441,58 +453,35 @@ func (c *Context) BindWith(obj interface{}, b binding.Binding) bool {
 	return true
 	return true
 }
 }
 
 
-// Serializes the given struct as JSON into the response body in a fast and efficient way.
-// It also sets the Content-Type as "application/json".
-func (c *Context) JSON(code int, obj interface{}) {
-	c.Writer.Header().Set("Content-Type", MIMEJSON)
-	if code >= 0 {
-		c.Writer.WriteHeader(code)
-	}
-	encoder := json.NewEncoder(c.Writer)
-	if err := encoder.Encode(obj); err != nil {
+func (c *Context) Render(code int, render render.Render, obj ...interface{}) {
+	if err := render.Render(c.Writer, code, obj); err != nil {
 		c.ErrorTyped(err, ErrorTypeInternal, obj)
 		c.ErrorTyped(err, ErrorTypeInternal, obj)
 		c.Abort(500)
 		c.Abort(500)
 	}
 	}
 }
 }
 
 
+// Serializes the given struct as JSON into the response body in a fast and efficient way.
+// It also sets the Content-Type as "application/json".
+func (c *Context) JSON(code int, obj interface{}) {
+	c.Render(code, render.JSON, obj)
+}
+
 // Serializes the given struct as XML into the response body in a fast and efficient way.
 // Serializes the given struct as XML into the response body in a fast and efficient way.
 // It also sets the Content-Type as "application/xml".
 // It also sets the Content-Type as "application/xml".
 func (c *Context) XML(code int, obj interface{}) {
 func (c *Context) XML(code int, obj interface{}) {
-	c.Writer.Header().Set("Content-Type", MIMEXML)
-	if code >= 0 {
-		c.Writer.WriteHeader(code)
-	}
-	encoder := xml.NewEncoder(c.Writer)
-	if err := encoder.Encode(obj); err != nil {
-		c.ErrorTyped(err, ErrorTypeInternal, obj)
-		c.Abort(500)
-	}
+	c.Render(code, render.XML, obj)
 }
 }
 
 
 // Renders the HTTP template specified by its file name.
 // Renders the HTTP template specified by its file name.
 // It also updates the HTTP code and sets the Content-Type as "text/html".
 // It also updates the HTTP code and sets the Content-Type as "text/html".
 // See http://golang.org/doc/articles/wiki/
 // See http://golang.org/doc/articles/wiki/
-func (c *Context) HTML(code int, name string, data interface{}) {
-	c.Writer.Header().Set("Content-Type", MIMEHTML)
-	if code >= 0 {
-		c.Writer.WriteHeader(code)
-	}
-	if err := c.Engine.HTMLTemplates.ExecuteTemplate(c.Writer, name, data); err != nil {
-		c.ErrorTyped(err, ErrorTypeInternal, H{
-			"name": name,
-			"data": data,
-		})
-		c.Abort(500)
-	}
+func (c *Context) HTML(code int, name string, obj interface{}) {
+	c.Render(code, c.Engine.HTMLRender, name, obj)
 }
 }
 
 
 // Writes the given string into the response body and sets the Content-Type to "text/plain".
 // Writes the given string into the response body and sets the Content-Type to "text/plain".
 func (c *Context) String(code int, format string, values ...interface{}) {
 func (c *Context) String(code int, format string, values ...interface{}) {
-	c.Writer.Header().Set("Content-Type", MIMEPlain)
-	if code >= 0 {
-		c.Writer.WriteHeader(code)
-	}
-	c.Writer.Write([]byte(fmt.Sprintf(format, values...)))
+	c.Render(code, render.Plain, format, values)
 }
 }
 
 
 // Writes some data into the body stream and updates the HTTP code.
 // Writes some data into the body stream and updates the HTTP code.

+ 69 - 0
render/render.go

@@ -0,0 +1,69 @@
+package render
+
+import (
+	"encoding/json"
+	"encoding/xml"
+	"fmt"
+	"html/template"
+	"net/http"
+)
+
+type (
+	Render interface {
+		Render(http.ResponseWriter, int, ...interface{}) error
+	}
+
+	// JSON binding
+	jsonRender struct{}
+
+	// XML binding
+	xmlRender struct{}
+
+	// Plain text
+	plainRender struct{}
+
+	// form binding
+	HTMLRender struct {
+		Template *template.Template
+	}
+)
+
+var (
+	JSON  = jsonRender{}
+	XML   = xmlRender{}
+	Plain = plainRender{}
+)
+
+func writeHeader(w http.ResponseWriter, code int, contentType string) {
+	if code >= 0 {
+		w.Header().Set("Content-Type", contentType)
+		w.WriteHeader(code)
+	}
+}
+
+func (_ jsonRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
+	writeHeader(w, code, "application/xml")
+	encoder := json.NewEncoder(w)
+	return encoder.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])
+}
+
+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)
+}
+
+func (_ plainRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
+	writeHeader(w, code, "text/plain")
+	format := data[0].(string)
+	args := data[1].([]interface{})
+	_, err := w.Write([]byte(fmt.Sprintf(format, args)))
+	return err
+}