custom error page support
This commit is contained in:
parent
8afaaa10d2
commit
2cf6d91ff5
5 changed files with 139 additions and 0 deletions
74
errorCatcher.go
Normal file
74
errorCatcher.go
Normal 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)
|
||||||
|
}
|
21
server.go
21
server.go
|
@ -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
11
styles/error.css
Normal 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
16
templates/error.html
Normal 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 – 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
17
templates/notfound.html
Normal 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 – 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 “Error 404” situation.</p>
|
||||||
|
|
||||||
|
<p>Consider visiting <a href='/'>my homepage</a>, which is guaranteed to exist.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue