http在golang中覆盖http标头代码,而json编码有错误

Jag*_*ata 3 error-handling http go net-http

考虑这种情况!

成功执行http请求后,如果执行json编码出错怎么办,如何覆盖头代码

func writeResp(w http.ResponseWriter, code int, data interface{}) {
    w.Header().Set("Content-Type", "application/json")

    //Here I set the status to 201 StatusCreated
    w.WriteHeader(code) 
    s := success{Data: data}

    //what if there is an error here and want to override the status to 5xx error
    //how to handle error here, panic?, http.Error() is not an option because as we already wrote header to 201, it just prints `http: multiple response.WriteHeader calls`
    if err := json.NewEncoder(w).Encode(s); err != nil {
        w.Header().Set("Content-Type", "application/json")

        //it throws http: multiple response.WriteHeader calls here as we already wrote header above to 201
        w.WriteHeader(code)
        e := errorResponse{
            Code:        code,
            Error:       error,
            Description: msg,
        }
        if err := json.NewEncoder(w).Encode(e); err != nil {
         //same how to handle here
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我这里有多个选项,如果我们只进行致命日志记录,用户将无法确切知道发生了什么,即使我w.Write([]byte(msg))仍然使用状态显示201已创建的字符串编写字符串,如何以错误代码 5xx 进行响应

任何帮助是极大的赞赏

eug*_*ioy 5

首先,编码时出现错误的可能性似乎不大。

Marshal请参阅此问题了解失败的原因:

什么输入会导致golang的json.Marshal返回错误?

错误的另一个潜在原因可能是实际将数据写入响应流时出现一些问题,但在这种情况下,您也无法编写自定义错误。

回到你的问题,如果你担心编码你的对象可能会失败,你可以首先封送你的数据(检查错误),然后如果封送成功,则只写入 201 状态代码(和编码数据)。

稍微修改一下你的例子:

s := success{Data: data}
jsonData, err := json.Marshal(s)
if err != nil {
    // write your error to w, then return
}
w.Header().Set("Content-Type", "application/json") 
w.WriteHeader(code)
w.Write(jsonData)
Run Code Online (Sandbox Code Playgroud)

现在,最后一个write也可能会引发错误。

但如果发生这种情况,写入自定义错误时也会失败,因此在这种情况下,您最好在服务器端记录该错误(或将该错误发送到跟踪器,例如 New Relic 等)。

  • @JagadeeshVenkata:对,好吧,如果您在那里收到错误,我认为您无法使用http响应通知用户(因为编写自定义错误响应也可能会失败)。您需要诉诸服务器端日志记录并监视这些日志..更新了我的答案以添加最后一部分。 (2认同)