diff --git a/README.md b/README.md index f0dff626..488dd6be 100644 --- a/README.md +++ b/README.md @@ -30,28 +30,40 @@ Echo is a fast HTTP router (zero memory allocation) + micro web framework in Go. package main import ( + "io" "net/http" + "html/template" + "github.com/labstack/echo" mw "github.com/labstack/echo/middleware" "github.com/rs/cors" "github.com/thoas/stats" ) -type user struct { - ID string `json:"id"` - Name string `json:"name"` +type ( + // Template provides HTML template rendering + Template struct { + templates *template.Template + } + + user struct { + ID string `json:"id"` + Name string `json:"name"` + } +) + +var ( + users map[string]user +) + +// Render HTML +func (t *Template) Render(w io.Writer, name string, data interface{}) error { + return t.templates.ExecuteTemplate(w, name, data) } -var users map[string]user - -func init() { - users = map[string]user{ - "1": user{ - ID: "1", - Name: "Wreck-It Ralph", - }, - } +func welcome(c *echo.Context) { + c.Render("welcome", "Joe") } func createUser(c *echo.Context) { @@ -109,6 +121,16 @@ func main() { e.Get("/users", getUsers) e.Get("/users/:id", getUser) + //***************// + // Templates // + //***************// + t := &Template{ + // Cached templates + templates: template.Must(template.ParseFiles("public/tpl/welcome.tpl")), + } + e.Renderer(t) + e.Get("/welcome", welcome) + //***********// // Group // //***********// @@ -132,6 +154,15 @@ func main() { // Start server e.Run(":8080") } + +func init() { + users = map[string]user{ + "1": user{ + ID: "1", + Name: "Wreck-It Ralph", + }, + } +} ``` ### Benchmark diff --git a/context.go b/context.go index c15f1b45..f8c23e08 100644 --- a/context.go +++ b/context.go @@ -45,9 +45,14 @@ func (c *Context) Bind(v interface{}) error { return ErrUnsupportedMediaType } -func (c *Context) Render(code int, name string, data interface{}) error { +// Render calls the registered HTML template renderer and sends a text/html +// response. +func (c *Context) Render(name string, data interface{}) error { + if c.echo.renderer == nil { + return ErrNoRenderer + } c.Response.Header().Set(HeaderContentType, MIMEHTML+"; charset=utf-8") - c.Response.WriteHeader(code) + c.Response.WriteHeader(http.StatusOK) return c.echo.renderer.Render(c.Response, name, data) } diff --git a/context_test.go b/context_test.go index 7144a3d1..6bae4da3 100644 --- a/context_test.go +++ b/context_test.go @@ -3,11 +3,23 @@ package echo import ( "bytes" "encoding/json" + "io" "net/http" "net/http/httptest" "testing" + "text/template" ) +type ( + Template struct { + templates *template.Template + } +) + +func (t *Template) Render(w io.Writer, name string, data interface{}) error { + return t.templates.ExecuteTemplate(w, name, data) +} + func TestContext(t *testing.T) { b, _ := json.Marshal(u1) r, _ := http.NewRequest(POST, "/users/1", bytes.NewReader(b)) @@ -16,6 +28,7 @@ func TestContext(t *testing.T) { Request: r, params: make(Params, 5), store: make(store), + echo: &Echo{}, } //**********// @@ -66,24 +79,38 @@ func TestContext(t *testing.T) { t.Error("user name should be Joe") } + // Render + tpl := &Template{ + templates: template.Must(template.New("hello").Parse("{{.}}")), + } + c.echo.renderer = tpl + if err := c.Render("hello", "Joe"); err != nil { + t.Errorf("render %v", err) + } + c.echo.renderer = nil + if err := c.Render("hello", "Joe"); err == nil { + t.Error("render should error out") + } + // JSON r.Header.Set(HeaderAccept, MIMEJSON) + c.Response.committed = false if err := c.JSON(http.StatusOK, u1); err != nil { - t.Errorf("render json %v", err) + t.Errorf("json %v", err) } // String r.Header.Set(HeaderAccept, MIMEText) c.Response.committed = false if err := c.String(http.StatusOK, "Hello, World!"); err != nil { - t.Errorf("render string %v", err) + t.Errorf("string %v", err) } // HTML r.Header.Set(HeaderAccept, MIMEHTML) c.Response.committed = false if err := c.HTML(http.StatusOK, "Hello, World!"); err != nil { - t.Errorf("render html %v", err) + t.Errorf("html %v", err) } // Redirect diff --git a/echo.go b/echo.go index 5615bfa4..fb8457cf 100644 --- a/echo.go +++ b/echo.go @@ -65,6 +65,7 @@ var ( // Errors ErrUnsupportedMediaType = errors.New("echo: unsupported media type") + ErrNoRenderer = errors.New("echo: renderer not registered") ) // New creates an Echo instance. @@ -109,12 +110,13 @@ func (e *Echo) MaxParam(n uint8) { e.maxParam = n } -// NotFoundHandler sets a custom NotFound handler. +// NotFoundHandler registers a custom NotFound handler. func (e *Echo) NotFoundHandler(h Handler) { e.notFoundHandler = wrapH(h) } -// Renderer sets an HTML Renderer. +// Renderer registers an HTML template renderer, it is used by +// echo.Context.Render API. func (e *Echo) Renderer(r Renderer) { e.renderer = r } diff --git a/example/main.go b/example/main.go index 8efc7aff..58e7f991 100644 --- a/example/main.go +++ b/example/main.go @@ -1,28 +1,40 @@ package main import ( + "io" "net/http" + "html/template" + "github.com/labstack/echo" mw "github.com/labstack/echo/middleware" "github.com/rs/cors" "github.com/thoas/stats" ) -type user struct { - ID string `json:"id"` - Name string `json:"name"` +type ( + // Template provides HTML template rendering + Template struct { + templates *template.Template + } + + user struct { + ID string `json:"id"` + Name string `json:"name"` + } +) + +var ( + users map[string]user +) + +// Render HTML +func (t *Template) Render(w io.Writer, name string, data interface{}) error { + return t.templates.ExecuteTemplate(w, name, data) } -var users map[string]user - -func init() { - users = map[string]user{ - "1": user{ - ID: "1", - Name: "Wreck-It Ralph", - }, - } +func welcome(c *echo.Context) { + c.Render("welcome", "Joe") } func createUser(c *echo.Context) { @@ -80,6 +92,16 @@ func main() { e.Get("/users", getUsers) e.Get("/users/:id", getUser) + //***************// + // Templates // + //***************// + t := &Template{ + // Cached templates + templates: template.Must(template.ParseFiles("public/tpl/welcome.tpl")), + } + e.Renderer(t) + e.Get("/welcome", welcome) + //***********// // Group // //***********// @@ -103,3 +125,12 @@ func main() { // Start server e.Run(":8080") } + +func init() { + users = map[string]user{ + "1": user{ + ID: "1", + Name: "Wreck-It Ralph", + }, + } +}