Skip to content

Commit

Permalink
middleware: panic handler for crashes
Browse files Browse the repository at this point in the history
  • Loading branch information
donutloop committed Nov 13, 2018
1 parent 75afce2 commit 0903775
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 3 deletions.
7 changes: 5 additions & 2 deletions cmd/httpcache/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"github.com/donutloop/httpcache/internal/cache"
"github.com/donutloop/httpcache/internal/handler"
"github.com/donutloop/httpcache/internal/middleware"
"github.com/donutloop/httpcache/internal/xhttp"
"log"
"net"
Expand Down Expand Up @@ -47,14 +48,16 @@ func main() {
mux.Handle("/stats", stats)
mux.Handle("/", proxy)

stack := middleware.NewPanic(mux, logger.Println)

if *httpAddr != "" {
listener, err := net.Listen("tcp", *httpAddr)
if err != nil {
log.Fatal(err)
}

xserver := xhttp.Server{
Server: &http.Server{Addr: *httpAddr, Handler: mux},
Server: &http.Server{Addr: *httpAddr, Handler: stack},
Logger: logger,
Listener: listener,
ShutdownTimeout: 3 * time.Second,
Expand All @@ -74,7 +77,7 @@ func main() {
}

xserver := xhttp.Server{
Server: &http.Server{Addr: *tlsAddr, Handler: mux},
Server: &http.Server{Addr: *tlsAddr, Handler: stack},
Logger: logger,
Listener: listener,
ShutdownTimeout: 3 * time.Second,
Expand Down
36 changes: 36 additions & 0 deletions internal/middleware/panic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package middleware

import (
"fmt"
"net/http"
"runtime/debug"
)

func NewPanic(next http.Handler, loggerFunc func(v ...interface{})) *Panic {
return &Panic{
Next: next,
loggerFunc: loggerFunc,
}
}

// Panic recovers from API panics and logs encountered panics
type Panic struct {
Next http.Handler
loggerFunc func(v ...interface{})
}

// It recovers from panics of all next handlers and logs them
func (h *Panic) ServeHTTP(r http.ResponseWriter, req *http.Request) {
defer func() {
if r := recover(); r != nil {
h.loggerFunc("begin: recovered from panic")
h.loggerFunc(fmt.Sprintf("unkown value of recover (%v)", r))
h.loggerFunc(fmt.Sprintf("url %v", req.URL.String()))
h.loggerFunc(fmt.Sprintf("method %v", req.Method))
h.loggerFunc(fmt.Sprintf("remote address %v", req.RemoteAddr))
h.loggerFunc(fmt.Sprintf("stack strace of cause \n %v", string(debug.Stack())))
h.loggerFunc("end: recovered from panic")
}
}()
h.Next.ServeHTTP(r, req)
}
20 changes: 20 additions & 0 deletions internal/middleware/panic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package middleware

import (
"net/http"
"net/http/httptest"
"testing"
)

func TestPanic(t *testing.T) {
crashedHandler := http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
panic("hello world")
})

middleware := NewPanic(crashedHandler, t.Log)

resp := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/panic", nil)

middleware.ServeHTTP(resp, req)
}
5 changes: 4 additions & 1 deletion tests/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"github.com/donutloop/httpcache/internal/cache"
"github.com/donutloop/httpcache/internal/handler"
"github.com/donutloop/httpcache/internal/middleware"
"github.com/donutloop/httpcache/internal/xhttp"
"log"
"math/rand"
Expand All @@ -30,7 +31,9 @@ func TestMain(m *testing.M) {
mux.Handle("/stats", stats)
mux.Handle("/", proxy)

proxyServer := httptest.NewServer(mux)
stack := middleware.NewPanic(mux, log.Println)

proxyServer := httptest.NewServer(stack)

transport := &http.Transport{
Proxy: SetProxyURL(proxyServer.URL),
Expand Down

0 comments on commit 0903775

Please sign in to comment.