@cryptotaxi247 / kubo / commits / 8ad114143

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":