This repository has been archived by the owner on Jul 31, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathhandler.go
111 lines (97 loc) · 2.68 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2017 The Go Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd.
//
// This handler implementation is based on gddo.
// https://github.com/golang/gddo/tree/master/gddo-server
package wiki
import (
"bytes"
"errors"
"fmt"
"io"
"log"
"net/http"
"runtime/debug"
"github.com/suzuken/wiki/controller"
"github.com/suzuken/wiki/httputil"
)
var errUnauthrized = errors.New("unauthorized")
// Auth verify if session user is logged in.
func Auth(h handler) handler {
return func(w http.ResponseWriter, r *http.Request) error {
if !controller.LoggedIn(r) {
return &httputil.HTTPError{
Status: http.StatusUnauthorized,
Err: errUnauthrized,
}
}
h.ServeHTTP(w, r)
return nil
}
}
func m(method string, h handler) handler {
return func(w http.ResponseWriter, r *http.Request) error {
if r.Method != method {
return &httputil.HTTPError{Status: http.StatusMethodNotAllowed}
}
h.ServeHTTP(w, r)
return nil
}
}
func GET(h handler) handler { return m("GET", h) }
func POST(h handler) handler { return m("POST", h) }
type handler func(w http.ResponseWriter, r *http.Request) error
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
runHandler(w, r, h, handleError)
}
type errFn func(w http.ResponseWriter, r *http.Request, status int, err error)
func logError(req *http.Request, err error, rv interface{}) {
if err != nil {
var buf bytes.Buffer
fmt.Fprintf(&buf, "Error serving %s: %v\n", req.URL, err)
if rv != nil {
fmt.Fprintln(&buf, rv)
buf.Write(debug.Stack())
}
log.Print(buf.String())
}
}
func runHandler(w http.ResponseWriter, r *http.Request,
fn func(w http.ResponseWriter, r *http.Request) error, errfn errFn) {
defer func() {
if rv := recover(); rv != nil {
err := errors.New("handler panic")
logError(r, err, rv)
errfn(w, r, http.StatusInternalServerError, err)
}
}()
r.Body = http.MaxBytesReader(w, r.Body, 2048)
r.ParseForm()
var buf httputil.ResponseBuffer
err := fn(&buf, r)
if err == nil {
buf.WriteTo(w)
} else if e, ok := err.(*httputil.HTTPError); ok {
if e.Status >= 500 {
logError(r, err, nil)
}
errfn(w, r, e.Status, e.Err)
} else {
logError(r, err, nil)
errfn(w, r, http.StatusInternalServerError, err)
}
}
func errorText(err error) string {
if err == errUnauthrized {
return "You are unauthorized."
}
return "Internal Server error."
}
func handleError(w http.ResponseWriter, r *http.Request, status int, err error) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(status)
io.WriteString(w, errorText(err))
}