重写 ResponseWriter 接口以捕获 HTTP 错误

2024-04-29

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

一个建议是重写 ResponseWriter 接口中的 WriteHeader 方法并检查状态代码,但我对实际如何编写它感到困惑(在输出之前重写 ResponseWriter 方法)。一个可能的例子可以从内格罗尼包 https://github.com/codegangsta/negroni/blob/c7477ad8e330bef55bf1ebe300cf8aa67c492d1b/negroni.go#L73.

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

Update

非常感谢 David 和 elithrar 的回复和代码。这InterceptorDavid 编码的结构体可以在服务器复用器的包装器中使用,如 elithrar 在评论中所示。对于那些寻求进一步解释其工作原理和原因的人,这一部分来自 astaxie 的书 https://astaxie.gitbooks.io/build-web-application-with-golang/content/en/03.3.html提供了有关 net/http 包的工作原理的一些非常好的信息,以及查看server.go 源代码 https://golang.org/src/net/http/server.go来自 net/http 包。


mux 库只有一种设置未找到处理程序的方法,作为一种方法来拦截 mux 无法将 URL 解析为其已知映射的请求。

例如,您这样做:

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

但客户端访问/baz多路复用器没有映射到该位置。

他们实际上并没有拦截发送给客户端的 404 错误,只是在遇到此问题时调用未找到的处理程序。

另外,如果您的 /foo 处理程序发送 404 响应,则不会调用 not find 。

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

如果您不控制该逻辑(即:框架正在编写某些内容并且无法覆盖),那么您可能希望拦截所有请求并使用响应代码检测逻辑覆盖 http.ResposeWriter 。

这是一个示例拦截器,基本上可以完成您想要的操作。在Play http://play.golang.org/p/kKmMBDjMq8

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()
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重写 ResponseWriter 接口以捕获 HTTP 错误 的相关文章

  • 在 Go 中将 float 转换为 int 时如何舍入到最近的 int

    将 float 转换为 int 时 小数点将被丢弃 有什么干净的方法可以将其四舍五入到最接近的整数 x int 3 6 应等于 4 而不是 3 int f 0 5 如果 gt 5 将导致向上舍入
  • Golang 中的“相互”包导入

    是否可以在 Golang 中执行 相互 包导入之类的操作 举例来说 我有两个包 A 和 B 分别具有 AFunc 和 BFunc BFunc2 函数 package A import B func AFunc do stuff but al
  • 地图中的最大元素数

    GO 中的 Map 最多可以存储多少个元素 如果我需要经常从 Map 访问数据 那么在长时间运行的程序中不断向 Map 添加项目并从中检索项目是一个好主意吗 除了map length类型的最大值之外 map中的元素数量没有理论上的限制 in
  • mysql 查询中的 golang 切片,带有 where in 子句

    我正在运行以下查询 但只获取第一个 id 值 select from table where table id in 1 2 3 4 5 6 7 9 11 13 14 15 17 and table deleted at is null 我
  • Go中funcappend的实现在哪里?

    我对 go 非常感兴趣 并尝试阅读 go 函数的实现 我发现其中一些函数没有实现 如追加或调用 The append built in function appends elements to the end of a slice If i
  • 使用 Golang 通道处理 HTTP 请求

    我正在尝试构建一个简单的 Golang Appengine 应用程序 它使用通道来处理每个 http 请求 原因是我希望每个请求执行合理的大型内存计算 并且每个请求都以线程安全的方式执行 即来自并发请求的计算不会混合 这一点很重要 本质上
  • 如何使用json传递opentracing数据

    我的 API 网关启动一个跟踪器和一个用于验证电子邮件的范围 然后它传递给user service用于验证 我想通过这个span详情至user service作为 json 对象并启动另一个span as a tracer start sp
  • Ajax 将文件上传到内容类型为 Multipart 的 GoLang 服务器

    我正在尝试使用多部分表单将音频文件上传到 Golang 服务器 然而 Go 返回错误 multipart NextPart bufio buffer full 我相信这表明我的 Javascript 请求中存在不属于多部分格式的内容 这是我
  • Golang 网络爬虫 NTLM 身份验证

    Golang 网络抓取工具需要从经过 NTLM 验证的网页中提取信息 有了有效的用户名和密码 网络抓取工具如何与服务器进行 NTLM 4 次握手 以获得对后面受保护网页的访问权限 url username password http www
  • 使用 google.protobuf.Timestamp 在 Go 中解析带有时区偏移的日期时间戳

    我正在创建一个将使用 GRPC 和 protobuf 的 Go 应用程序 我的 RPC 服务应获取包含类型的消息google protobuf Timestamp 解析它并最终将其保存在数据库中或对其执行更多操作 我对什么被认为是该类型的有
  • 有没有一种方法可以在不停机的情况下更新 net/http 服务器中的 TLS 证书?

    我有一个简单的 https 服务器 提供一个简单的页面 如下所示 为简洁起见 没有错误处理 package main import crypto tls fmt net http func main mux http NewServeMux
  • 如何在 Visual Studio Code 中使用 Delve 调试器进行远程调试

    我已经问过了 得到了很好的答复answer https stackoverflow com questions 39058823 how to use delve debugger in visual studio code用于使用 del
  • 当涉及多个渠道时,select 如何工作?

    我发现在多个非缓冲通道上使用 select 时 例如 select case lt chana case lt chanb 即使两个通道都有数据 但在处理此选择时 case chana 和 case chanb 的跟注不平衡 package
  • GOPATH值设置

    我用go1 3 1 windows amd64 msi安装go 安装后GOROOT是默认设置 我发现 D Programs Go bin 在 PATH 中 然后我创建一个 GOPATH 环境变量 使用 go get 命令时 出现错误 软件包
  • 我怎么知道我的所有 goroutine 确实正在使用 golang 的同步包等待一个条件

    我有一个应用程序 我正在创建多个 goroutine 来同时执行某个任务 所有工作协程都会等待条件 事件发生 一旦事件被触发 它们就会开始执行 创建完所有goroutines后 主线程在发送广播信号之前应该知道所有goroutines确实处
  • 鸭子在 Go 中打字

    我想写一个Join函数接受任意对象String 方法 package main import fmt strings type myint int func i myint String string return fmt Sprintf
  • 匿名结构和空结构

    http play golang org p vhaKi5uVmm http play golang org p vhaKi5uVmm package main import fmt var battle make chan string
  • Golang 正则表达式命名组和子匹配

    我正在尝试匹配正则表达式并获取匹配的捕获组名称 当正则表达式仅与字符串匹配一次时 这是有效的 但如果它与字符串匹配多次 SubexpNames不返回重复的名称 这是一个例子 package main import fmt regexp fu
  • 解组转义 XML

    在 Go 中 我将如何解码此 XML 响应 我尝试过建立一个自定义UnMarshal方法在我的Answerstruct 但我运气不太好
  • 在 Go 中初始化嵌入结构

    我有以下内容struct其中包含一个net http Request type MyRequest struct http Request PathParams map string string 现在我想初始化匿名内部结构http Req

随机推荐