我正在try 开发一个使用围棋的API网关.我希望如果请求在查询中包含"_alway s200=true",我会将状态代码设置为200. 以下是我try 过的: custom_response_writer.go:

type CustomResponseWriter struct {
    http.ResponseWriter
    Buf         *bytes.Buffer
    StatusCode  int
    WroteHeader bool
}

func NewCustomResponseWriter(w http.ResponseWriter) *CustomResponseWriter {
    return &CustomResponseWriter{ResponseWriter: w, Buf: new(bytes.Buffer)}
}

func (c *CustomResponseWriter) WriteHeader(code int) {
    c.StatusCode = code
    c.ResponseWriter.WriteHeader(code)
}

func (c *CustomResponseWriter) Write(b []byte) (int, error) {
    return c.Buf.Write(b)
}

middleware:

func HeaderFilterMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        always200, _ := r.Context().Value(always200QueryKey).(bool)
        crw := NewCustomResponseWriter(w)
        next.ServeHTTP(crw, r)

        if always200 {
            crw.WriteHeader(http.StatusOK)
        }
    })
}

它总是返回404.有什么办法可以解决这个问题吗?

推荐答案

该代码中至少存在两个问题.

  1. always200, _ := r.Context().Value(always200QueryKey).(bool)不是获取查询参数的正确方法.我认为您应该用r.URL.Query().Get("_always200")来读取它,并将其值与字符串"true"进行比较.

  2. next.ServeHTTP(crw, r)后打crw.WriteHeader(http.StatusOK)已经太晚了.当我测试代码时,它打印了一条警告消息:

    http: superfluous response.WriteHeader call from main.(*CustomResponseWriter).WriteHeader
    

以下是更改响应状态代码的修改后的示例:

package main

import (
    "bytes"
    "net/http"
    "strings"

    "github.com/go-chi/chi/v5"
)

type CustomResponseWriter struct {
    http.ResponseWriter
    Buf                *bytes.Buffer
    OriginalStatusCode int
    WroteHeader        bool
    always200          bool
}

func NewCustomResponseWriter(w http.ResponseWriter, always200 bool) *CustomResponseWriter {
    return &CustomResponseWriter{
        ResponseWriter: w,
        Buf:            new(bytes.Buffer),
        always200:      always200,
    }
}

func (c *CustomResponseWriter) WriteHeader(code int) {
    c.OriginalStatusCode = code

    if c.always200 {
        code = http.StatusOK
    }
    c.ResponseWriter.WriteHeader(code)
}

func (c *CustomResponseWriter) Write(b []byte) (int, error) {
    return c.Buf.Write(b)
}

func HeaderFilterMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        always200 := r.URL.Query().Get("_always200")
        crw := NewCustomResponseWriter(w, strings.EqualFold(always200, "true"))
        next.ServeHTTP(crw, r)
    })
}

func main() {
    r := chi.NewRouter()

    r.Use(HeaderFilterMiddleware)

    r.Get("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("welcome"))
    })
    http.ListenAndServe(":3000", r)
}

Go相关问答推荐

try 用GitHub操作中的release标签更新version. go文件,但失败了

+在具有html/模板Golang的Base64中

GoLang:无法发送带有附件的邮箱

带有一个新变量的Go冒号等于运算符

go mod tidy会自动升级go.mod中的go版本吗?

如何绕过深层 xml,没有嵌套循环?

Golang telegram 机器人

无法在go中为docker容器写入有效的挂载路径

AWS Lambda 中的 Websocket URL 超时达到错误

是否可以从 golang 中的参数推断类型?

Go 切片容量增长率

如何匹配两次出现的相同但随机字符串之间的字符

拆分文本并按空格获取字符串数组,如果文本长度超过 500,则获取字符串数组

查找、解析和验证邮箱地址

Go 泛型:自引用接口约束

如何使用特定的 Go 版本运行 govulncheck?

在 Go 中读取数字行

将 Simple Go Web 应用程序部署到 Elastic Beanstalk

无法识别同步错误.使用一次

如何断言类型是指向golang中接口的指针