custom error page support

This commit is contained in:
Naman Sood 2021-02-17 00:57:16 -05:00
parent 8afaaa10d2
commit 2cf6d91ff5
5 changed files with 139 additions and 0 deletions

74
errorCatcher.go Normal file
View file

@ -0,0 +1,74 @@
package main
import (
"net/http"
"strconv"
"github.com/aymerick/raymond"
)
// errorCatcher is a wrapper for http.ResponseWriter that
// captures 4xx and 5xx status codes and handles them in
// a custom manner
type errorCatcher struct {
req *http.Request
res http.ResponseWriter
errorTpl *raymond.Template
notFoundTpl *raymond.Template
handledError bool
}
func (ec *errorCatcher) Header() http.Header {
return ec.res.Header()
}
func (ec *errorCatcher) Write(buf []byte) (int, error) {
// if we have already sent a response, pretend that this was successful
if ec.handledError {
return len(buf), nil
}
return ec.res.Write(buf)
}
func (ec *errorCatcher) WriteHeader(statusCode int) {
if ec.handledError {
return
}
if statusCode == 404 {
ctx := map[string]string{
"path": ec.req.URL.Path,
}
page, err := ec.notFoundTpl.Exec(ctx)
// if we don't have a page to write, return before
// we toggle the flag so we fall back to the original
// error page
if err != nil {
return
}
ec.res.Header().Add("content-type", "text/html")
ec.res.WriteHeader(statusCode)
ec.res.Write([]byte(page))
ec.handledError = true
return
}
if statusCode >= 400 && statusCode < 600 {
ctx := map[string]string{
"code": strconv.Itoa(statusCode),
}
page, err := ec.errorTpl.Exec(ctx)
// if we don't have a page to write, return before
// we toggle the flag so we fall back to the original
// error page
if err != nil {
return
}
ec.res.Header().Add("content-type", "text/html")
ec.res.WriteHeader(statusCode)
ec.res.Write([]byte(page))
ec.handledError = true
return
}
ec.res.WriteHeader(statusCode)
}

View file

@ -19,6 +19,8 @@ type server struct {
pageTpl *raymond.Template pageTpl *raymond.Template
fullPostTpl *raymond.Template fullPostTpl *raymond.Template
summaryTpl *raymond.Template summaryTpl *raymond.Template
errorTpl *raymond.Template
notFoundTpl *raymond.Template
} }
func newServer() (*server, error) { func newServer() (*server, error) {
@ -81,6 +83,18 @@ func (s *server) refreshTemplates() error {
} }
log.Printf("Loaded full post template") log.Printf("Loaded full post template")
s.notFoundTpl, err = raymond.ParseFile("templates/notfound.html")
if err != nil {
return fmt.Errorf("could not parse 404 template")
}
log.Printf("Loaded 404 template")
s.errorTpl, err = raymond.ParseFile("templates/error.html")
if err != nil {
return fmt.Errorf("could not parse error template")
}
log.Printf("Loaded error template")
s.summaryTpl, err = raymond.ParseFile("templates/summary.html") s.summaryTpl, err = raymond.ParseFile("templates/summary.html")
if err != nil { if err != nil {
return fmt.Errorf("could not parse summary template") return fmt.Errorf("could not parse summary template")
@ -138,6 +152,13 @@ func (s *server) logRequest(req *http.Request) {
func (s *server) router(res http.ResponseWriter, req *http.Request) { func (s *server) router(res http.ResponseWriter, req *http.Request) {
s.logRequest(req) s.logRequest(req)
res = &errorCatcher{
res: res,
req: req,
errorTpl: s.errorTpl,
notFoundTpl: s.notFoundTpl,
handledError: false,
}
slug := req.URL.Path[1:] slug := req.URL.Path[1:]
if slug == "" { if slug == "" {

11
styles/error.css Normal file
View file

@ -0,0 +1,11 @@
body {
font-family: monospace;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin: 0;
min-height: 100vh;
font-size: 20px;
text-align: center;
}

16
templates/error.html Normal file
View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="/css/error.css">
<title>oh no &ndash; Naman Sood</title>
</head>
<body>
<h1>That was <em>not</em> supposed to happen.</h1>
<p>Calm down. Take a deep breath. Error {{code}}s can happen to anyone. Seriously. It's alright.</p>
<p>Try again in a while, or check out my <a href="https://nsood.in">website</a>, which should not have these issues. Probably.</p>
</body>
</html>

17
templates/notfound.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="/css/error.css">
<title>something something princess in other castle &ndash; Naman Sood</title>
</head>
<body>
<h1>Uncaught ReferenceError: {{path}} is not defined</h1>
<p>Haha, just kidding. No, but really, there's no page here. This is what the kids call an &ldquo;Error 404&rdquo; situation.</p>
<p>Consider visiting <a href='/'>my homepage</a>, which is guaranteed to exist.</p>
</body>
</html>