~samwhited/tmpl

564939b25e0a23edddcb8cfd0bcfad77e781cc6e — Sam Whited 1 year, 5 months ago ff4dc1b v0.0.3
Return errors from renderer

Now that this is public let the application handle errors from the
renderer instead of logging them.
2 files changed, 10 insertions(+), 17 deletions(-)

M tmpl.go
M tmpl_test.go
M tmpl.go => tmpl.go +3 -8
@@ 4,7 4,6 @@ package tmpl // import "code.soquee.net/tmpl"
import (
	"html/template"
	"io"
	"log"
	"net/http"
	"net/url"
	"path"


@@ 158,7 157,7 @@ func defaultData(p Page) interface{} {

// RenderFunc is the type used to render templates into pages.
// For more information see Renderer.
type RenderFunc func(uid int, flash Flash, w http.ResponseWriter, r *http.Request, extraData interface{})
type RenderFunc func(uid int, flash Flash, w http.ResponseWriter, r *http.Request, extraData interface{}) error

// Renderer returns a function that can be used to render pages using the
// provided templates.


@@ 178,7 177,6 @@ func Renderer(
	tmplName,
	title string,
	tmpls Template,
	logger *log.Logger,
	data func(Page) interface{},
) RenderFunc {
	if data == nil {


@@ 186,7 184,7 @@ func Renderer(
	}
	matcher := tmpls.catalog.Matcher()

	return func(uid int, flash Flash, w http.ResponseWriter, r *http.Request, extraData interface{}) {
	return func(uid int, flash Flash, w http.ResponseWriter, r *http.Request, extraData interface{}) error {
		var xsrfToken string
		if xsrfKey != "" {
			xsrfToken = xsrftoken.Generate(xsrfKey, strconv.Itoa(uid), r.URL.Path)


@@ 226,7 224,7 @@ func Renderer(
		acceptLangs, _, _ := language.ParseAcceptLanguage(r.Header.Get("Accept-Language"))
		tag, _, _ := matcher.Match(acceptLangs...)

		err := tmpls.ExecuteTemplate(w, tmplName, data(Page{
		return tmpls.ExecuteTemplate(w, tmplName, data(Page{
			Title:   title,
			Path:    r.URL.Path,
			URL:     r.URL,


@@ 239,8 237,5 @@ func Renderer(
			Lang:    tag,
			Printer: message.NewPrinter(tag, message.Catalog(tmpls.catalog)),
		}))
		if err != nil {
			logger.Printf("Error rendering template %q: %q", tmplName, err)
		}
	}
}

M tmpl_test.go => tmpl_test.go +7 -9
@@ 3,7 3,6 @@ package tmpl_test
import (
	"bytes"
	"errors"
	"log"
	"net/http"
	"net/http/httptest"
	"os"


@@ 255,9 254,8 @@ func TestRenderer(t *testing.T) {
			if err != nil {
				t.Fatalf("Unexpected error creating templates: %q", err)
			}
			errBuf := &bytes.Buffer{}
			render := tmpl.Renderer(
				"example.org", tc.xsrfKey, tc.tmplName, t.Name(), tmpls, log.New(errBuf, "", 0), tc.data)
				"example.org", tc.xsrfKey, tc.tmplName, t.Name(), tmpls, tc.data)

			w := httptest.NewRecorder()



@@ 281,7 279,7 @@ func TestRenderer(t *testing.T) {
				}
			}

			render(uid, tc.flash, w, r, tc.data)
			err = render(uid, tc.flash, w, r, tc.data)

			// If no flash message was set, the cookie one should have been cleared
			// (otherwise it should still exist).


@@ 296,11 294,11 @@ func TestRenderer(t *testing.T) {
				}
			}

			switch s := errBuf.String(); {
			case tc.wantErr && s == "":
				t.Errorf("Expected an error to be logged, but did not get any log output")
			case !tc.wantErr && s != "":
				t.Errorf("Unexpected error logged: %q", s)
			switch {
			case tc.wantErr && err == nil:
				t.Errorf("Expected an error but got none")
			case !tc.wantErr && err != nil:
				t.Errorf("Unexpected error logged: %q", err)
			}
			// We know net/http will always return 200 if no code is set, so just make
			// that the default.