重写ResponseWriter接口以捕获HTTP错误

时间:2016-02-20 20:01:42

标签: go

我在Go中编写了一个Web应用程序,虽然各种mux库提供了一种设置自定义404错误处理程序的方法,但其他4xx和5xx错误代码却没有。

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

这是为4xx和5xx错误提供自定义模板的正确方法吗?任何人都可以提供一个如何实现这个的例子吗?

更新

非常感谢David和elithrar的回复和代码。 David编码的Interceptor结构可以在服务器mux的包装器中使用,正如elithrar在注释中所示。对于那些希望进一步解释为什么以及如何工作的人,this section from astaxie's book提供了一些关于net / http包的工作原理的非常好的信息,以及从net / http包中查看server.go source code

1 个答案:

答案 0 :(得分:3)

mux库只能设置未找到的处理程序,以便为您提供一种拦截请求的方法,其中多路复用器可以解析其已知映射的URL。

例如,你这样做:

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

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

它们实际上并不拦截进入客户端的404,它们只是在遇到此问题时调用未找到的处理程序。

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

如果您想要从映射的URL中获取各种返回响应的自定义页面,只需让各种处理程序写出正确的响应即可。

如果你不控制那个逻辑(即:框架正在编写某些东西而无法覆盖),那么你可能想拦截所有请求并用响应代码检测逻辑覆盖http.ResposeWriter。 / p>

这是一个基本上做你想要的拦截器的示例。在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()
}
相关问题