覆盖ResponseWriter接口以捕获HTTP错误 [英] Overriding ResponseWriter interface to catch HTTP errors

查看:70
本文介绍了覆盖ResponseWriter接口以捕获HTTP错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Go编写一个Web应用程序,尽管各种mux库提供了一种设置自定义404错误处理程序的方法,但其他4xx和5xx错误代码却一无所获.

一个建议是在ResponseWriter接口中重写WriteHeader方法并检查状态代码,但是我对如何实际编写感到困惑(在输出之前重写ResponseWriter方法).可以从 negroni包中找到一个示例..>

这是为4xx和5xx错误提供自定义模板的正确方法吗?谁能提供一个示例说明如何实现?

更新

非常感谢David和elithrar的回答和代码.David编码的 Interceptor 结构可以在服务器多路复用器的包装器中使用,如elithrar在注释中所示.对于那些希望进一步解释其原因和方式的人,解决方案

mux库只能设置未找到的处理程序,从而为您提供了一种方法来拦截mux无法解析URL的请求到它的已知映射.

例如,您这样做:

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

但是客户端访问的多路复用器没有映射的/baz .

他们实际上并没有截取到404的客户端,而是在遇到此问题时调用未找到的处理程序.

此外,如果您的/foo处理程序发送404响应,则不会调用未找到的内容.

如果您想为自定义页面提供来自映射URL的各种返回响应的信息,只需使各种处理程序编写正确的响应即可.

如果您不控制该逻辑(例如,框架正在写东西并且没有覆盖方法),那么您可能希望拦截所有请求并使用响应代码检测逻辑覆盖http.ResposeWriter.

这是一个示例拦截器,基本上可以完成您想要的操作.在播放

 程序包主要进口 ("fmt"日志")导入"net/http"类型拦截器struct {origWriter http.ResponseWriter覆盖的布尔}func(i * Interceptor)WriteHeader(rc int){切换rc {案例500:http.Error(i.origWriter,自定义500条消息/内容",500)案例404:http.Error(i.origWriter,自定义404消息",404)案例403:i.origWriter.WriteHeader(403)fmt.Fprintln(i.origWriter,自定义403消息")默认:i.origWriter.WriteHeader(rc)返回}//如果默认情况不执行(并返回),则必须覆盖输出i.overridden = truelog.Println(i.overridden)}func(i * Interceptor)Write(b [] byte)(int,error){如果!i.overridden {返回i.origWriter.Write(b)}//如果我们已覆盖响应,则不返回任何内容.返回0,无}func(i * Interceptor)Header()http.Header {返回i.origWriter.Header()} 

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.

解决方案

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()
}

这篇关于覆盖ResponseWriter接口以捕获HTTP错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆