メールで送信するグローバルエラーハンドラーを作成したいと思います。
package main
import (
"github.com/gorilla/mux"
"log"
"net/http"
)
func main() {
rtr := mux.NewRouter()
rtr.HandleFunc("/", withPanic).Methods("GET")
http.Handle("/", rtr)
log.Println("Listening...")
http.ListenAndServe(":3001", http.DefaultServeMux)
}
func withPanic(w http.ResponseWriter, r *http.Request) {
panic("somewhere here will be panic, but I don't know where exactly")
}
それをグローバルにする方法。エラーが発生する場所がわかれば簡単です
if err != nil {
sendMeMail(err)
}
しかし、エラーが発生する場所が正確にわからない場合はどうすればよいですか?したがって、グローバルrecover
ishハンドラーを追加する必要があります。しかし、それを正確に行う方法はわかりません。
main
の先頭にdefer recover
を追加しましたが、http://localhost:3001
を要求しても実行されません。したがって、パニックは電子メールで送信されません。
package main
import (
"errors"
"fmt"
"github.com/gorilla/mux"
"log"
"net/http"
)
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
// find out exactly what the error was and set err
var err error
switch x := r.(type) {
case string:
err = errors.New(x)
case error:
err = x
default:
err = errors.New("Unknown panic")
}
if err != nil {
// sendMeMail(err)
fmt.Println("sendMeMail")
}
}
}()
rtr := mux.NewRouter()
rtr.HandleFunc("/", withPanic).Methods("GET")
http.Handle("/", rtr)
log.Println("Listening...")
http.ListenAndServe(":3001", http.DefaultServeMux)
}
func withPanic(w http.ResponseWriter, r *http.Request) {
panic("somewhere here will be panic, but I don't know where exactly")
}
ハンドラーをリカバリミドルウェアでラップできます
package main
import (
"errors"
"github.com/gorilla/mux"
"log"
"net/http"
)
func main() {
m := mux.NewRouter()
m.Handle("/", RecoverWrap(http.HandlerFunc(handler))).Methods("GET")
http.Handle("/", m)
log.Println("Listening...")
http.ListenAndServe(":3001", nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
panic(errors.New("panicing from error"))
}
func RecoverWrap(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var err error
defer func() {
r := recover()
if r != nil {
switch t := r.(type) {
case string:
err = errors.New(t)
case error:
err = t
default:
err = errors.New("Unknown error")
}
sendMeMail(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}()
h.ServeHTTP(w, r)
})
}
func sendMeMail(err error) {
// send mail
}
詳細については、 codahaleリカバリハンドラー または negroniミドルウェア を参照してください。
それが ゴリラ回復ハンドラー の目的だと思います