diff options
Diffstat (limited to 'page/render.go')
| -rw-r--r-- | page/render.go | 137 |
1 files changed, 108 insertions, 29 deletions
diff --git a/page/render.go b/page/render.go index 6cbabf9..d35ba38 100644 --- a/page/render.go +++ b/page/render.go @@ -1,20 +1,104 @@ package page import ( + "bytes" "net/http" "path/filepath" "strings" ) -// Render is a lower level option, allowing you to specify local -// variables and the status code in which to return. -func Render(w http.ResponseWriter, r *http.Request, - path string, vars map[string]interface{}, statusCode int) { +func getURLPath(r *http.Request) string { u := r.URL.Path if u == "/" { u = "/index" } + return u +} + +// Render5xx is automatically called if any render fails, +// additionally you can call it for your own uses. It will +// try to use the 5xx template but will fall back to a plain +// page if that fails. +func Render5xx(w http.ResponseWriter, r *http.Request, + vars map[string]interface{}, statusCode int) { + u := getURLPath(r) + + Logger.Printf("%s %s %d %s", + r.RemoteAddr, + r.Method, + statusCode, + u) + + p := NewPage(TemplateDirectory + "/5xx") + + buf := &bytes.Buffer{} + + err := p.Render(buf) + if err != nil { + Logger.Printf("%s %s path: %s while trying 5xx: %s", + r.RemoteAddr, + r.Method, + u, + err) + http.Error(w, "Internal server error", statusCode) + + return + } + + w.WriteHeader(statusCode) + + _, _ = w.Write(buf.Bytes()) + + Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u) +} + +// Render4xx is mostly used to render a 404 page, pulls from 404 template. +// automatically called by Render if a page is missing. +func Render4xx(w http.ResponseWriter, r *http.Request, + vars map[string]interface{}, statusCode int) { + u := getURLPath(r) + + Logger.Printf("%s %s %d %s", + r.RemoteAddr, + r.Method, + statusCode, + u) + + p := NewPage(TemplateDirectory + "/4xx") + + buf := &bytes.Buffer{} + + err := p.Render(buf) + if err != nil { + Logger.Printf("%s %s path: %s while trying 404: %s", + r.RemoteAddr, + r.Method, + u, + err) + Render5xx(w, r, vars, http.StatusInternalServerError) + + return + } + + w.WriteHeader(statusCode) + + _, err = w.Write(buf.Bytes()) + if err != nil { + Render5xx(w, r, nil, http.StatusInternalServerError) + + return + } + + Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u) +} + +// Render is a lower level option, allowing you to specify local +// variables and the status code in which to return. +func Render(w http.ResponseWriter, r *http.Request, + path string, vars map[string]interface{}, statusCode int) { + u := getURLPath(r) + u = filepath.Join(".", u) // Sepcifically use the specified path for the page @@ -24,42 +108,37 @@ func Render(w http.ResponseWriter, r *http.Request, p.Vars = vars } - err := p.Render(w) + buf := &bytes.Buffer{} + + err := p.Render(buf) if err != nil { if strings.HasSuffix(err.Error(), "no such file or directory") { - Logger.Printf("%s %s %d %s", - r.RemoteAddr, - r.Method, - http.StatusNotFound, - u) + Render4xx(w, r, vars, http.StatusNotFound) - p = NewPage("404") - - w.WriteHeader(http.StatusNotFound) + return + } - err := p.Render(w) - if err != nil { - Logger.Printf("%s %s path: %s while trying 404: %s", - r.RemoteAddr, - r.Method, - u, - err) - http.Error(w, "Internal server error", - http.StatusInternalServerError) + Logger.Printf("%s %s path: %s rendering encountered: %s", + r.RemoteAddr, + r.Method, + u, + err) + Render5xx(w, r, vars, http.StatusInternalServerError) - return - } + return + } - return - } + w.WriteHeader(statusCode) - Logger.Printf("%s %s path: %s encountered: %s", + _, err = w.Write(buf.Bytes()) + if err != nil { + Logger.Printf("%s %s %d %s: while writing buf: %s", r.RemoteAddr, r.Method, + statusCode, u, err) - http.Error(w, "Internal server error", - http.StatusInternalServerError) + Render5xx(w, r, nil, http.StatusInternalServerError) return } |
