Skip to content

Commit

Permalink
recoverer: don't recover http.ErrAbortHandler (#624)
Browse files Browse the repository at this point in the history
This error is generally used to abort a request while streaming a response
so it should not be recovered otherwise the request is not aborted and
the client does not detect the error

Fixes #588
  • Loading branch information
drakkan committed Jan 3, 2022
1 parent b750c80 commit 7dbe9a0
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
7 changes: 6 additions & 1 deletion middleware/recoverer.go
Expand Up @@ -22,7 +22,12 @@ import (
func Recoverer(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rvr := recover(); rvr != nil && rvr != http.ErrAbortHandler {
if rvr := recover(); rvr != nil {
if rvr == http.ErrAbortHandler {
// we don't recover http.ErrAbortHandler so the response
// to the client is aborted, this should not be logged
panic(rvr)
}

logEntry := GetLogEntry(r)
if logEntry != nil {
Expand Down
25 changes: 25 additions & 0 deletions middleware/recoverer_test.go
Expand Up @@ -40,3 +40,28 @@ func TestRecoverer(t *testing.T) {
}
t.Fatal("First func call line should start with ->.")
}

func TestRecovererAbortHandler(t *testing.T) {
defer func() {
rcv := recover()
if rcv != http.ErrAbortHandler {
t.Fatalf("http.ErrAbortHandler should not be recovered")
}
}()

w := httptest.NewRecorder()

r := chi.NewRouter()
r.Use(Recoverer)

r.Get("/", func(w http.ResponseWriter, r *http.Request) {
panic(http.ErrAbortHandler)
})

req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Fatal(err)
}

r.ServeHTTP(w, req)
}

0 comments on commit 7dbe9a0

Please sign in to comment.