Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow passing custom header values to recovery #246

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions recovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ type Recovery struct {
StackAll bool
StackSize int
Formatter PanicFormatter
HeaderValues map[string]string

// Deprecated: Use PanicHandlerFunc instead to receive panic
// error with additional information (see PanicInformation)
Expand All @@ -158,6 +159,12 @@ func NewRecovery() *Recovery {
func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
defer func() {
if err := recover(); err != nil {
// set any custom header values before writing the status
if rec.HeaderValues != nil {
for k, v := range rec.HeaderValues {
rw.Header().Set(k, v)
}
}
rw.WriteHeader(http.StatusInternalServerError)

stack := make([]byte, rec.StackSize)
Expand Down
34 changes: 34 additions & 0 deletions recovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package negroni
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -172,3 +173,36 @@ func TestRecovery_HTMLFormatter(t *testing.T) {
expect(t, recorder.Header().Get("Content-Type"), "text/html; charset=utf-8")
refute(t, recorder.Body.Len(), 0)
}

type jSONFormatter struct{}

func (t *jSONFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) {
fmt.Fprintf(rw, `{"error":"%s"}`, infos.RecoveredPanic)
}

// test custom Content type case, an httptest.Server is required as httptest.ResponseRecorder
// does not replicate the header flushing behaviour of http.Server
func TestRecovery_JSONFormatter(t *testing.T) {
rec := NewRecovery()

rec.Formatter = &jSONFormatter{}
rec.HeaderValues = map[string]string{"Content-Type": "application/json"}
n := New()
n.Use(rec)
n.UseHandler(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
panic("some panic")
}))
server := httptest.NewServer(n)
defer server.Close()

res, err := http.Get(server.URL + "/somePath")
expect(t, err, nil)
defer res.Body.Close()

body, err := ioutil.ReadAll(res.Body)
expect(t, err, nil)
expect(t, string(body), `{"error":"some panic"}`)

expect(t, res.Header.Get("Content-Type"), "application/json")
expect(t, res.StatusCode, http.StatusInternalServerError)
}