Skip to content

Instantly share code, notes, and snippets.

@campoy
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save campoy/f8fe6cf2cee366da9e8b to your computer and use it in GitHub Desktop.
Save campoy/f8fe6cf2cee366da9e8b to your computer and use it in GitHub Desktop.
A small web server with a customized 404 page showed in two different ways, wrapping the ResponseWriter or wrapping the Handler
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>404 - not found</title>
<style>
* {
padding: 0;
margin: 0;
}
html {
-webkit-font-smoothing: antialiased;
background-color: #fafafa;
}
body {
font-family:'Helvetica Neue', Helvetica, Arial, 'lucida grande', tahoma, verdana, arial, sans-serif;
color: #222222;
margin: 0;
line-height: 1.5em;
}
</style>
</head>
<body>
<div style="padding:40px;">
<h2>404 - not found</h2>
<hr size="1" width="30%" />
<br/><a href="/">go back</a>
</div>
</body>
</html>
package main
import (
"flag"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
)
var (
address = flag.String("address", ":3000", "tcp4 host and port to listen")
root = flag.String("root", ".", "root directory")
)
type fileServer struct {
root http.Dir
fs http.Handler
page []byte
}
func newFileServer(root http.Dir, page []byte) http.Handler {
return fileServer{root, http.FileServer(root), page}
}
func (s fileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
_, err := s.root.Open(r.URL.Path)
if err != nil {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusNotFound)
w.Write(s.page)
return
}
s.fs.ServeHTTP(w, r)
}
func main() {
flag.Parse()
// Parse the not found page.
f, err := os.Open(filepath.Join(*root, "notfound.html"))
if err != nil {
log.Fatal(err)
}
page, err := ioutil.ReadAll(f)
if err != nil {
log.Fatal(err)
}
fs := newFileServer(http.Dir(*root), page)
log.Fatal(http.ListenAndServe(*address, fs))
}
package main
import (
"bytes"
"flag"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
)
var (
address = flag.String("address", ":3000", "tcp4 host and port to listen")
root = flag.String("root", ".", "root directory")
)
type NotFoundHandler struct {
h http.Handler
page []byte
}
func (h NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
wr := &response{header: w.Header()}
h.h.ServeHTTP(wr, r)
if wr.status == http.StatusNotFound {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusNotFound)
w.Write(h.page)
return
}
w.WriteHeader(wr.status)
io.Copy(w, &wr.buf)
}
type response struct {
buf bytes.Buffer
status int
header http.Header
}
func (w *response) Write(p []byte) (int, error) { return w.buf.Write(p) }
func (w *response) WriteHeader(status int) { w.status = status }
func (w *response) Header() http.Header { return w.header }
func main() {
flag.Parse()
// Parse the not found page.
f, err := os.Open(filepath.Join(*root, "notfound.html"))
if err != nil {
log.Fatal(err)
}
page, err := ioutil.ReadAll(f)
if err != nil {
log.Fatal(err)
}
// Start the server.
h := NotFoundHandler{http.FileServer(http.Dir(*root)), page}
log.Fatal(http.ListenAndServe(*address, h))
}
@genesem
Copy link

genesem commented Jul 1, 2014

awesome, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment