Documentation
¶
Overview ¶
Package ehtml provides ways of rendering an error html page, using Go templates. It supports status code specific templates, with fallback to a generic error template. If no templates are defined, it uses a simple placeholder template.
Define some templates:
{{- define "head" -}}
<head>
<meta charset="utf-8">
<title>{{ .String }}</title>
</head>
{{- end -}}
{{- define "error" -}}
<!DOCTYPE html>
<html lang="en">
{{ template "head" }}
<body>
<h1>{{ .StatusCode }} {{ .StatusText }}</h1>
<p>
{{ .Message }} while serving {{ .Request.URL.Path }}.
Request ID: {{ .Data.RequestID }}
</p>
<p><i>This is a generic error page</i><p>
</body>
</html>
{{- end -}}
{{- define "500" -}}
<!DOCTYPE html>
<html lang="en">
{{ template "head" }}
<body>
<h1>Snap!</h1>
<h2>{{ .StatusCode }} {{ .StatusText }}</h2>
<p>
Something went really wrong and we've been notified!
Please try again later.
</p>
<p><i>
Error: {{ .Message }} while serving {{ .Request.URL.Path }}.
Request ID: {{ .Data.RequestID }}
</i></p>
</body>
</html>
{{- end -}}
{{- define "404" -}}
<!DOCTYPE html>
<html lang="en">
<head>
{{ template "head" }}
</head>
<body>
<h1>{{ .StatusCode }} {{ .StatusText }}</h1>
<p>
{{ .Request.URL.Path }} could not be found.
</body>
</html>
{{- end -}}
Parse them into a globale variable (or part of your Handler object):
var errorPages = &Pages{template.Must(template.New("error").Parse(templates))}
If you are using Gorilla mux, set the `NotFoundHandler`
r := mux.NewRouter()
r.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := p.Render(w, r, http.StatusNotFound, "", nil); err != nil {
log.Println(err)
}
})
And whenever something goes wrong in your handlers, call `Render()`:
err := p.Render(w, req, http.StatusInternalServerError, "DB connection", struct{ RequestID int }{666})
if err != nil {
log.Println(err)
}
Example ¶
p := &Pages{template.Must(template.New("error").Parse(exampleTemplates))}
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
w := httptest.NewRecorder()
// Serves the client with the "500" template
err := p.Render(w, req, http.StatusInternalServerError, "DB connection", struct{ RequestID int }{666})
if err != nil {
log.Println(err)
}
resp := w.Result()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(resp.StatusCode)
fmt.Println(string(body))
w = httptest.NewRecorder()
// 400 is not defined, so the generic "error" template is used instead.
err = p.Render(w, req, http.StatusBadRequest, "Missing token in URL", struct{ RequestID int }{667})
if err != nil {
log.Println(err)
}
resp = w.Result()
body, _ = ioutil.ReadAll(resp.Body)
fmt.Println(resp.StatusCode)
fmt.Println(string(body))
Example (NotFoundHandler) ¶
p := &Pages{template.Must(template.New("error").Parse(exampleTemplates))}
r := mux.NewRouter()
r.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := p.Render(w, r, http.StatusNotFound, "", nil); err != nil {
log.Println(err)
}
})
Index ¶
Examples ¶
Constants ¶
const DefaultTmpl = `` /* 228-byte string literal not displayed */
DefaultTmpl is a placeholder template for `Pages.Render()`
const RenderError = "500 Internal server error. While handling:\n%s"
RenderError is returned to the client if the template failed to render. This doesn't look nice, but it prevents partial responses.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Data ¶
type Data struct {
Request *http.Request // Request object as passed to `Render()`
StatusCode int
Message string
Data interface{} // Optional, additional Data
}
Data available in templates.
func (*Data) StatusText ¶
StatusText returns a text for the HTTP status code. It returns the empty string if the code is unknown.
type Pages ¶
Pages allows setting of status page templates. Whenever such page needs to be served, a Lookup is done for a template named by the code. Eg: "404". A generic template named "error" can be provided and will be used if there is no status-specific template defined.
If Tmpl is `nil` or no templates are found using above Lookup scheme, `DefaultErrTmpl` will be used.
func (*Pages) Render ¶
func (p *Pages) Render(w http.ResponseWriter, r *http.Request, statusCode int, msg string, data interface{}) error
Render a page for passed status code. Data and Request are optional and can be nil, if the template doesn't need them. They are passed to the template as-is.
In case of template execution errors, RenderError including the original status and message is sent to the client.