Skip to content
This repository has been archived by the owner on Dec 23, 2023. It is now read-only.

Commit

Permalink
Add Context.Render
Browse files Browse the repository at this point in the history
  • Loading branch information
razonyang committed Apr 4, 2020
1 parent 7d66c9c commit 73d0886
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ under development
- Add `Context.QueryString`.
- Add `Context.QueryParams` and `Context.QueryParam`.
- Add `Context.JSONP` and `Context.JSONPCallback`.
- Add `Context.Render` to render a template.

v1.8.1 April 2, 2020
--------------------
Expand Down
3 changes: 2 additions & 1 deletion CREDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ Creadit

- Thanks to all [contributors](https://github.com/clevergo/clevergo/graphs/contributors).
- [Razon Yang](https://github.com/razonyang): author and maintainer of [CleverGo](https://github.com/clevergo).
- [Julien Schmidt](https://github.com/julienschmidt): the author of [julienschmidt/httprouter](https://github.com/julienschmidt/httprouter).
- [Julien Schmidt](https://github.com/julienschmidt): the author of [julienschmidt/httprouter](https://github.com/julienschmidt/httprouter).
- [Echo](https://github.com/labstack/echo): Renderer is inspired by Echo framework.
19 changes: 19 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package clevergo

import (
"bytes"
"context"
"encoding/json"
"encoding/xml"
Expand All @@ -16,6 +17,7 @@ import (

// Context contains incoming request, route, params and manages outgoing response.
type Context struct {
router *Router
Params Params
Route *Route
Request *http.Request
Expand All @@ -31,6 +33,7 @@ func newContext(w http.ResponseWriter, r *http.Request) *Context {
}

func (ctx *Context) reset() {
ctx.router = nil
ctx.Params = nil
ctx.Route = nil
ctx.Response = nil
Expand Down Expand Up @@ -234,6 +237,22 @@ func (ctx *Context) HTML(code int, html string) error {
return err
}

// Render renders a template with data, and sends HTML response with status code.
func (ctx *Context) Render(code int, name string, data interface{}) (err error) {
if ctx.router.Renderer == nil {
return ErrRendererNotRegister
}

buf := new(bytes.Buffer)
if err = ctx.router.Renderer.Render(buf, name, data, ctx); err != nil {
return err
}
ctx.SetContentTypeHTML()
ctx.Response.WriteHeader(code)
_, err = buf.WriteTo(ctx.Response)
return
}

// FormValue is a shortcut of http.Request.FormValue.
func (ctx *Context) FormValue(key string) string {
return ctx.Request.FormValue(key)
Expand Down
33 changes: 33 additions & 0 deletions context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ package clevergo

import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"net/http/httptest"
"reflect"
Expand Down Expand Up @@ -472,3 +474,34 @@ func TestContext_QueryString(t *testing.T) {
assert.Equal(t, ctx.QueryString(), req.URL.RawQuery)
}
}

type fakeRenderer struct {
}

func (r *fakeRenderer) Render(w io.Writer, name string, data interface{}, ctx *Context) error {
if name == "" {
return errors.New("empty template name")
}
w.Write([]byte(name))
return nil
}

func TestContext_Render(t *testing.T) {
w := httptest.NewRecorder()
router := NewRouter()
ctx := newContext(w, nil)
ctx.router = router

err := ctx.Render(http.StatusOK, "foo", nil)
assert.Equal(t, err, ErrRendererNotRegister)

router.Renderer = new(fakeRenderer)

err = ctx.Render(http.StatusOK, "", nil)
assert.EqualError(t, err, "empty template name")

ctx.Render(http.StatusForbidden, "foo", nil)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.Equal(t, w.Header().Get("Content-Type"), "text/html; charset=utf-8")
assert.Equal(t, w.Body.String(), "foo")
}
15 changes: 15 additions & 0 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@
package clevergo

import (
"errors"
"fmt"
"io"
"log"
"net/http"
"net/url"
"strings"
"sync"
)

// errors
var (
ErrRendererNotRegister = errors.New("renderer not registered")
)

// Handle is a function which handle incoming request and manage outgoing response.
type Handle func(ctx *Context) error

Expand All @@ -32,6 +39,11 @@ func HandleHandlerFunc(f http.HandlerFunc) Handle {
}
}

// Renderer is an interface for template engine.
type Renderer interface {
Render(w io.Writer, name string, data interface{}, ctx *Context) error
}

// Router is a http.Handler which can be used to dispatch requests to different
// handler functions via configurable routes
type Router struct {
Expand Down Expand Up @@ -103,6 +115,8 @@ type Router struct {

middlewares []MiddlewareFunc
handle Handle

Renderer Renderer
}

// Make sure the Router conforms with the http.Handler interface
Expand Down Expand Up @@ -354,6 +368,7 @@ func (r *Router) allowed(path, reqMethod string) (allow string) {
// ServeHTTP makes the router implement the http.Handler interface.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctx := r.getContext()
ctx.router = r
ctx.Request = req
ctx.Response = w
defer r.putContext(ctx)
Expand Down

0 comments on commit 73d0886

Please sign in to comment.