Adds recovery middleware
This commit is contained in:
69
recovery.go
Normal file
69
recovery.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package narco
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/codemodus/chain"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type StackResponseFormatter func(w io.Writer, err interface{}, stack []byte)
|
||||
|
||||
func GoFormatStack(w io.Writer, err interface{}, stack []byte) {
|
||||
fmt.Fprintf(w, "Server internal error: %s\n%s", err, stack)
|
||||
}
|
||||
|
||||
func HtmlFormatStack(w io.Writer, err interface{}, stack []byte) {
|
||||
fmt.Fprintf(w, `<html>
|
||||
<body>
|
||||
<h1>Server internal error: %s</h1>
|
||||
<pre>%s</pre>
|
||||
</body>
|
||||
</html>`, err, stack)
|
||||
}
|
||||
|
||||
type Recoverer struct {
|
||||
Logger *log.Logger
|
||||
ShowStackInResponse StackResponseFormatter
|
||||
StackOtherGoroutine bool
|
||||
}
|
||||
|
||||
func NewRecoverer() *Recoverer {
|
||||
return &Recoverer{
|
||||
Logger: log.New(os.Stdout, "[narco] ", log.LstdFlags),
|
||||
ShowStackInResponse: nil,
|
||||
StackOtherGoroutine: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (rec *Recoverer) Wrap() func(chain.Handler) chain.Handler {
|
||||
return func(other chain.Handler) chain.Handler {
|
||||
return chain.HandlerFunc(func(ctx context.Context, h http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
// h.Header()["Content-Type"] = []string{"text/html; charset=utf-8"}
|
||||
h.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
stack := make([]byte, 8*1024)
|
||||
stack = stack[:runtime.Stack(stack, rec.StackOtherGoroutine)]
|
||||
rec.Logger.Printf("PANIC: %s\n%s", err, stack)
|
||||
|
||||
if rec.ShowStackInResponse != nil {
|
||||
rec.ShowStackInResponse(h, err, stack)
|
||||
} else {
|
||||
fmt.Fprintf(h, "%s\n", http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
}()
|
||||
|
||||
other.ServeHTTPContext(ctx, h, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user