马提尼酒适用于任何恐慌情况的恢复。

huangapple go评论96阅读模式
英文:

martini recover for any panics

问题

我想将RecoverWrap连接到martini路由的所有处理程序,以便通过RecoverWrap内部的代码完成任何panic

我尝试像这样做m.Use(RecoverWrap),但不知道如何确切地做,它在编译时失败。

package main

import (
	"errors"
	"github.com/go-martini/martini"
	"net/http"
)

func main() {
	m := martini.Classic()
    //m.Use(RecoverWrap)
	m.Get("/", func() {
		panic("some panic")
	})

	m.Run()
}

func RecoverWrap(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *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")
				}

				http.Error(w, "Something goes wrong", http.StatusInternalServerError)
			}
		}()
		h.ServeHTTP(w, req)
	})
}
英文:

I want to wire RecoverWrap to all handlers of martini routes to make any panic be finished by code inside RecoverWrap.

I tried to do it like m.Use(RecoverWrap) but do not know how to do it exactly, it fails on compile.

package main

import (
	"errors"
	"github.com/go-martini/martini"
	"net/http"
)

func main() {
	m := martini.Classic()
    //m.Use(RecoverWrap)
	m.Get("/", func() {
		panic("some panic")
	})

	m.Run()
}

func RecoverWrap(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *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")
				}

				http.Error(w, "Something goes wrong", http.StatusInternalServerError)
			}
		}()
		h.ServeHTTP(w, req)
	})
}

答案1

得分: 1

Martini中的中间件处理程序无法“包装”其他处理程序调用,因此无法通过注入器找到http.Handler。

你可以使用context.Next()来实现:

package main

import (
    "errors"
    "github.com/go-martini/martini"
    "net/http"
)

func main() {
    m := martini.Classic()
    m.Use(RecoverWrap)
    m.Get("/", func() {
        panic("some panic")
    })

    m.Run()
}

func RecoverWrap(c martini.Context, w http.ResponseWriter) {
    var err error
    defer func(w http.ResponseWriter) {
        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")
            }
            http.Error(w, "Something goes wrong", http.StatusInternalServerError)
        }
    }(w)
    c.Next()
}

你需要确保你的错误处理程序是第一个注册的中间件,否则在它之前运行的处理程序将无法被捕获。

实际上,相同的方法在martini.Recovery中实现:

https://github.com/go-martini/martini/blob/6241001738f6e1b1ea7c4a4089195e1b0681609a/recovery.go#L115

英文:

Middleware handlers in Martini do not get to "wrap" other handler calls, so http.Handler is not found by the injector.

What you can do is use context.Next():

package main

import (
"errors"
"github.com/go-martini/martini"
"net/http"
)

func main() {
    m := martini.Classic()
    m.Use(RecoverWrap)
    m.Get("/", func() {
        panic("some panic")
        })

    m.Run()
}

func RecoverWrap(c martini.Context, w http.ResponseWriter) {
    var err error
    defer func(w http.ResponseWriter) {
        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")
            }
            http.Error(w, "Something goes wrong", http.StatusInternalServerError)
        }
        }(w)
    c.Next()
}

You will have to make sure that your error handler is the first middleware registered, or those handlers running before will not be caught.

Actually, the same method is implemented in martini.Recovery:

https://github.com/go-martini/martini/blob/6241001738f6e1b1ea7c4a4089195e1b0681609a/recovery.go#L115

huangapple
  • 本文由 发表于 2015年2月28日 18:15:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/28780565.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定