@@ -10,9 +10,12 @@ import (
10
10
"io"
11
11
"io/ioutil"
12
12
"log"
13
+ "net"
13
14
"net/http"
14
15
"net/http/httputil"
16
+ "os"
15
17
"runtime"
18
+ "syscall"
16
19
"time"
17
20
)
18
21
@@ -37,16 +40,37 @@ func RecoveryWithWriter(out io.Writer) HandlerFunc {
37
40
return func (c * Context ) {
38
41
defer func () {
39
42
if err := recover (); err != nil {
43
+ // Check for a broken connection, as it is not really a
44
+ // condition that warrants a panic stack trace.
45
+ var brokenPipe bool
46
+ if ne , ok := err .(* net.OpError ); ok {
47
+ if se , ok := ne .Err .(* os.SyscallError ); ok {
48
+ if se .Err == syscall .EPIPE || se .Err == syscall .ECONNRESET {
49
+ brokenPipe = true
50
+ }
51
+ }
52
+ }
40
53
if logger != nil {
41
54
stack := stack (3 )
42
- if IsDebugging () {
43
- httprequest , _ := httputil .DumpRequest (c .Request , false )
44
- logger .Printf ("[Recovery] %s panic recovered:\n %s\n %s\n %s%s" , timeFormat (time .Now ()), string (httprequest ), err , stack , reset )
55
+ httprequest , _ := httputil .DumpRequest (c .Request , false )
56
+ if brokenPipe {
57
+ logger .Printf ("%s\n %s%s" , err , string (httprequest ), reset )
58
+ } else if IsDebugging () {
59
+ logger .Printf ("[Recovery] %s panic recovered:\n %s\n %s\n %s%s" ,
60
+ timeFormat (time .Now ()), string (httprequest ), err , stack , reset )
45
61
} else {
46
- logger .Printf ("[Recovery] %s panic recovered:\n %s\n %s%s" , timeFormat (time .Now ()), err , stack , reset )
62
+ logger .Printf ("[Recovery] %s panic recovered:\n %s\n %s%s" ,
63
+ timeFormat (time .Now ()), err , stack , reset )
47
64
}
48
65
}
49
- c .AbortWithStatus (http .StatusInternalServerError )
66
+
67
+ // If the connection is dead, we can't write a status to it.
68
+ if brokenPipe {
69
+ c .Error (err .(error ))
70
+ c .Abort ()
71
+ } else {
72
+ c .AbortWithStatus (http .StatusInternalServerError )
73
+ }
50
74
}
51
75
}()
52
76
c .Next ()
0 commit comments