卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章35281本站已运行394

如何解决杜松子酒中的“标头已写入。想要用 400 覆盖状态代码 200”

如何解决杜松子酒中的“标头已写入。想要用 400 覆盖状态代码 200”

php小编子墨为您介绍解决杜松子酒中的“标头已写入。想要用 400 覆盖状态代码 200”问题的方法。这个问题通常发生在使用PHP进行网页开发时,可能会导致网页无法正常加载。解决方法包括检查代码中的重复输出、清空缓冲区、检查服务器配置等。通过采取适当的措施,您可以轻松解决这个问题,确保您的网页能够正常运行。

问题内容

我正在尝试使用 Gin 框架独立于 HTTP 请求来计算报告,但如果尚未关闭,我也想将其返回到请求。以下代码片段有时可以正常工作,但有时会抛出错误“标头已写入。想要用 400 覆盖状态代码 200”。我找不到解决方案。

// router.go
reportRoute.POST("/query", func(c *gin.Context) {
        reporter.ReportInChan <- c
    }) // Unpublish report by id
//reporter
package reporter

import (
    "fmt"
    "github.com/gin-gonic/gin"
)

var (
    ReportInChan = make(chan *gin.Context)
)

func Listener() {
    for {
        select {
        case req := <-ReportInChan:
            queryReports(req)
        }
    }
}

func queryReports(req *gin.Context) {
    type ReqQuery struct {
        QueryID    uint           `json:"query_id"`
        Parameters map[string]any `json:"parameters"`
    }
    type Req struct {
        ReportID uint       `json:"report_id"`
        Queries  []ReqQuery `json:"queries"`
    }

    var reqBody Req
    err := req.BindJSON(&reqBody)
    if err != nil {
        fmt.Println("hata var")
        if ctx := req.Request.Context(); ctx.Done() == nil {
            req.JSON(400, gin.H{"error": "Veriler Yanlış Gönderiliyor. Lütfen Bilgi İşlem Birimiyle İletişime Geçin ", "data": nil})
        }
        return
    }
}

解决方法

下面的处理程序会将上下文发送到通道,然后返回。一旦处理程序返回,请求将被取消。此时,接收 Goroutine 可能根本没有机会产生任何输出,但有时可能会产生任何输出。如果接收 Goroutine 在 Gin 框架写入响应之后但在取消上下文之前开始生成输出,您将收到上述错误。

reportRoute.POST("/query", func(c *gin.Context) {
        reporter.ReportInChan <- c
})

您真正需要做的是实现一个超时方案,因此如果请求处理程序可以在该超时之前响应,则将其写入输出并返回。否则,您让请求处理程序运行,并找到另一种方法将结果返回给调用者,可能是通过另一个 API 调用:

type reportRequest struct {
    ReportParams
    result chan ReportResult
}

reportRoute.POST("/query", func(c *gin.Context) {
        req:=reportRequest {
              ReportParams: {...},
              result: make(chan ReportResult),
        }
        reporter.ReportInChan <- req
        select {
           case time.After(100*time.Millisecond): 
               // Wait 100 msecs 
           case result<-req.result:
               // Write the result
        }
})

上面的代码将从请求上下文创建一个报告请求,创建一个返回通道,然后将其发送到报告处理器。如果报表处理器在 100 毫秒内响应,则可以写入结果。否则,结果应存储在可以由另一个 API 检索的其他位置。

报表处理器应如下所示:

func (r Reporter) reportProcessor() {
   for request:=range r.ReportInChan {
       result:=processReport(request)
       select {
          case request.result <- result:
              // Wrote the result
          default:
               // Cannot write the result, handler returned
             storeResult(result)
   }
}
卓越飞翔博客
上一篇: 将值插入“type abc interface{}”
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏