douba1617 2018-12-20 00:55
浏览 13
已采纳

错误处理中间件引发运行时错误

I have this piece of error handling middleware:

func Error(next http.HandlerFunc) http.Handler {

    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        defer func() {
            if err := recover(); err != nil {

                log.Error("Caught error in defer/recover middleware: ", err)
                originalError := err.(struct{ OriginalError error }).OriginalError

                if originalError != nil {
                    log.Error("Original error in defer/recover middleware: ", originalError)
                }

                statusCode := err.(struct{ StatusCode int }).StatusCode

                if statusCode != 0 {
                    w.WriteHeader(statusCode)
                } else {
                    w.WriteHeader(http.StatusInternalServerError)
                }

                message := err.(struct{ Message string }).Message

                if message == "" {
                    message = "Unknown error message."
                }

                json.NewEncoder(w).Encode(struct {
                    ID string
                }{
                    message,
                })
            }
        }()
        next.ServeHTTP(w, r)
    })

}

it will run at least once per request since it's deferred, and I get this error:

ERRO[0009] Caught error in defer/recover middleware: runtime error: index out of range 
2018/12/19 16:53:47 http: panic serving 127.0.0.1:50394: interface conversion: interface {} is runtime.errorString, not struct { OriginalError error }
goroutine 34 [running]:
net/http.(*conn).serve.func1(0xc420224000)
        /usr/lib/go-1.10/src/net/http/server.go:1726 +0xd0
panic(0x700300, 0xc420232340)
        /usr/lib/go-1.10/src/runtime/panic.go:502 +0x229
huru/mw.Error.func1.1(0x7a5b60, 0xc420244000)
        /home/oleg/codes/huru/api/src/huru/mw/middleware.go:113 +0x309
panic(0x6fd380, 0x919c10)
        /usr/lib/go-1.10/src/runtime/panic.go:502 +0x229
huru/mw.Auth.func1(0x7a5b60, 0xc420244000, 0xc42023a200)
        /home/oleg/codes/huru/api/src/huru/mw/middleware.go:53 +0x4ae
net/http.HandlerFunc.ServeHTTP(0xc4201133c0, 0x7a5b60, 0xc420244000, 0xc42023a200)
        /usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
huru/mw.Logging.func1(0x7a5b60, 0xc420244000, 0xc42023a200)
        /home/oleg/codes/huru/api/src/huru/mw/middleware.go:21 +0xcb
net/http.HandlerFunc.ServeHTTP(0xc4200117c0, 0x7a5b60, 0xc420244000, 0xc42023a200)
        /usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
huru/mw.Error.func1(0x7a5b60, 0xc420244000, 0xc42023a200)
        /home/oleg/codes/huru/api/src/huru/mw/middleware.go:140 +0x86
net/http.HandlerFunc.ServeHTTP(0xc4200117d0, 0x7a5b60, 0xc420244000, 0xc42023a200)
        /usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc42013e000, 0x7a5b60, 0xc420244000, 0xc42023a200)
        /home/oleg/codes/huru/api/src/github.com/gorilla/mux/mux.go:162 +0xed
net/http.serverHandler.ServeHTTP(0xc4200a5110, 0x7a5b60, 0xc420244000, 0xc42023a000)
        /usr/lib/go-1.10/src/net/http/server.go:2697 +0xbc

I can't figure out how to fix it.

  • 写回答

1条回答 默认 最新

  • doushi1900 2018-12-20 01:14
    关注

    From the error message, the err object type is runtime.errorString not struct { OriginalError error }. Forcing the type assertion will generates a panic.

    I think better to use second return value during type assertion, to check whether the casting process is success or not.

    if err := recover(); err != nil {
    
        if temp, ok := err.(struct{ OriginalError error }); ok {
            log.Error("Caught error in defer/recover middleware: ", err)
            originalError := temp.OriginalError
    
            if originalError != nil {
                log.Error("Original error in defer/recover middleware: ", originalError)
            }
        }
    
        if temp, ok := err.(struct{ StatusCode int }); ok {
            statusCode := temp.StatusCode
    
            if statusCode != 0 {
                w.WriteHeader(statusCode)
            } else {
                w.WriteHeader(http.StatusInternalServerError)
            }
        }
    
        if temp, ok := err.(struct{ Message string }); ok {
            message := temp.Message
    
            if message == "" {
                message = "Unknown error message."
            }
    
            json.NewEncoder(w).Encode(struct {
                ID string
            }{
                message,
            })
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?