douwu8524 2016-02-20 20:01
浏览 57
已采纳

覆盖ResponseWriter接口以捕获HTTP错误

I'm coding a web application in Go, and while various mux libraries provide a way to set a custom 404 error handler, there's nothing for other 4xx and 5xx error codes.

One suggestion is to override the WriteHeader method in the ResponseWriter interface and check the status code, but I'm confused as to how this would actually be written (the overriding of ResponseWriter methods, before outputting). One possible example can be found from the negroni package.

Would this be the correct way to serve a custom template for 4xx and 5xx errors? Could anyone provide an example of how this could be implemented?

Update

Big thanks to David and elithrar for their responses and code. The Interceptor struct that David coded can be used in a wrapper for the server mux, as elithrar shows in the comments. For those looking for further explanation as to why and how this works, this section from astaxie's book gives some very good info on the workings of the net/http package, along with viewing the server.go source code from the net/http package.

  • 写回答

1条回答 默认 最新

  • doushi5024 2016-02-20 20:52
    关注

    The mux libraries only have a means of setting the not found handler as a means of giving you a way to intercept requests where the mux can't resolve the URL to it's known mappings.

    For example, you do:

    mux.Handle("/foo",fooFunc)
    mux.Handle("/bar",barFunc)
    

    But the client accesses /baz to which the mux has no mapping.

    They do not actually intercept a 404 going to the client, they just invoke the not found handler when it runs in to this problem.

    Also, if your /foo handler sends a 404 response, the not found does not get invoked.

    If you want custom pages for various return responses from your mapped URLs, simply make the various handlers write the correct response.

    If you don't control that logic (ie: the framwork is writing something and has no means to override), then you may want to intercept all requests and override the http.ResposeWriter with response code detection logic.

    Here's an example interceptor that basically does what you want. On Play

    package main
    
    import (
        "fmt"
        "log"
    )
    import "net/http"
    
    type Interceptor struct {
        origWriter http.ResponseWriter
        overridden bool
    }
    
    func (i *Interceptor) WriteHeader(rc int) {
        switch rc {
        case 500:
            http.Error(i.origWriter, "Custom 500 message / content", 500)
        case 404:
            http.Error(i.origWriter, "Custom 404 message", 404)
        case 403:
            i.origWriter.WriteHeader(403)
            fmt.Fprintln(i.origWriter, "Custom 403 message")
        default:
            i.origWriter.WriteHeader(rc)
            return
        }
        // if the default case didn't execute (and return) we must have overridden the output
        i.overridden = true
        log.Println(i.overridden)
    }
    
    func (i *Interceptor) Write(b []byte) (int, error) {
        if !i.overridden {
            return i.origWriter.Write(b)
        }
    
        // Return nothing if we've overriden the response.
        return 0, nil
    }
    
    func (i *Interceptor) Header() http.Header {
        return i.origWriter.Header()
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大
  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端