// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one. // While Martini is in development mode, Recovery will also output the panic as HTML. func Recovery() Handler { return func(c Context, log *log.Logger) { defer func() { if err := recover(); err != nil { stack := stack(3) log.Printf("PANIC: %s\n%s", err, stack) // Lookup the current responsewriter val := c.Get(inject.InterfaceOf((*http.ResponseWriter)(nil))) res := val.Interface().(http.ResponseWriter) // respond with panic message while in development mode var body []byte if Env == Dev { res.Header().Set("Content-Type", "text/html") body = []byte(fmt.Sprintf(panicHtml, err, err, stack)) } else { body = []byte("500 Internal Server Error") } res.WriteHeader(http.StatusInternalServerError) if nil != body { res.Write(body) } } }() c.Next() } }
func defaultReturnHandler() ReturnHandler { return func(ctx Context, vals []reflect.Value) { rv := ctx.Get(inject.InterfaceOf((*http.ResponseWriter)(nil))) res := rv.Interface().(http.ResponseWriter) var responseVal reflect.Value if len(vals) > 1 && vals[0].Kind() == reflect.Int { res.WriteHeader(int(vals[0].Int())) responseVal = vals[1] } else if len(vals) > 0 { responseVal = vals[0] } if canDeref(responseVal) { responseVal = responseVal.Elem() } if isByteSlice(responseVal) { res.Write(responseVal.Bytes()) } else { res.Write([]byte(responseVal.String())) } } }