fixup panic catching in http handler funcs
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
Jeromy committed
Dec 2, 2015 at 20:48 UTC
8ad1141436dbb795e2b545378527e6f7ad96685e
2 files changed
+33
-26
commands/http/handler.go
+24
-26
@@ -6,8 +6,7 @@ import (
6
"io"
7
"net/http"
8
"net/url"
9
- "os"
10
- "runtime"
9
+ "runtime/debug"
10
"strconv"
11
"strings"
12
"sync"
@@ -92,7 +91,7 @@ func skipAPIHeader(h string) bool {
91
}
92
}
93
95
-func NewHandler(ctx cmds.Context, root *cmds.Command, cfg *ServerConfig) *Handler {
94
+func NewHandler(ctx cmds.Context, root *cmds.Command, cfg *ServerConfig) http.Handler {
95
if cfg == nil {
96
panic("must provide a valid ServerConfig")
97
}
@@ -114,14 +113,33 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
113
114
defer func() {
115
if r := recover(); r != nil {
116
+ log.Error("A panic has occurred in the commands handler!")
117
log.Error(r)
118
119
- buf := make([]byte, 4096)
120
- n := runtime.Stack(buf, false)
121
- fmt.Fprintln(os.Stderr, string(buf[:n]))
119
+ debug.PrintStack()
120
}
121
}()
122
123
+ // get the node's context to pass into the commands.
124
+ node, err := i.ctx.GetNode()
125
+ if err != nil {
126
+ s := fmt.Sprintf("cmds/http: couldn't GetNode(): %s", err)
127
+ http.Error(w, s, http.StatusInternalServerError)
128
+ return
129
+ }
130
+
131
+ ctx, cancel := context.WithCancel(node.Context())
132
+ defer cancel()
133
+ if cn, ok := w.(http.CloseNotifier); ok {
134
+ go func() {
135
+ select {
136
+ case <-cn.CloseNotify():
137
+ case <-ctx.Done():
138
+ }
139
+ cancel()
140
+ }()
141
+ }
142
+
143
if !allowOrigin(r, i.cfg) || !allowReferer(r, i.cfg) {
144
w.WriteHeader(http.StatusForbidden)
145
w.Write([]byte("403 - Forbidden"))
@@ -140,29 +158,9 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
158
return
159
}
160
143
- // get the node's context to pass into the commands.
144
- node, err := i.ctx.GetNode()
145
- if err != nil {
146
- s := fmt.Sprintf("cmds/http: couldn't GetNode(): %s", err)
147
- http.Error(w, s, http.StatusInternalServerError)
148
- return
149
- }
150
-
161
//ps: take note of the name clash - commands.Context != context.Context
162
req.SetInvocContext(i.ctx)
163
154
- ctx, cancel := context.WithCancel(node.Context())
155
- defer cancel()
156
- if cn, ok := w.(http.CloseNotifier); ok {
157
- go func() {
158
- select {
159
- case <-cn.CloseNotify():
160
- case <-ctx.Done():
161
- }
162
- cancel()
163
- }()
164
- }
165
-
164
err = req.SetRootContext(ctx)
165
if err != nil {
166
http.Error(w, err.Error(), http.StatusInternalServerError)
core/corehttp/gateway_handler.go
+9
@@ -6,6 +6,7 @@ import (
6
"io"
7
"net/http"
8
gopath "path"
9
+ "runtime/debug"
10
"strings"
11
"time"
12
@@ -55,6 +56,14 @@ func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.Node, error) {
56
57
// TODO(btc): break this apart into separate handlers using a more expressive muxer
58
func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
59
+ defer func() {
60
+ if r := recover(); r != nil {
61
+ log.Error("A panic occurred in the gateway handler!")
62
+ log.Error(r)
63
+ debug.PrintStack()
64
+ }
65
+ }()
66
+
67
if i.config.Writable {
68
switch r.Method {
69
case "POST":