http: 多余的 response.WriteHeader 调用 StatusOK

huangapple go评论74阅读模式
英文:

http: superfluous response.WriteHeader call StatusOK

问题

在我的代码中,我有一个循环来处理一组文件(基于预先指定的文件夹中的内容),根据每个处理文件的输出,将一些信息发送给客户端,所以我写了以下代码:

for i, file := range files {
    uniqueSlice := unique(matches)
    output = Output{MSG: "ok", File: file, Skills: uniqueSlice}
    data, err := json.Marshal(output)
    if err != nil {
        panic(err)
    }
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK) // -< Error from here
    w.Write(data)
}

如果文件夹中只有一个文件,上述代码可以正常工作,但如果文件夹中有多个文件,我会得到错误:http: superfluous response.WriteHeader call

我理解这个错误是由于使用了w.WriteHeader(http.StatusOK),它不能被多次设置,但我需要它被设置为了让客户端处理返回的数据。

我该如何修改这段代码,以便在处理每个文件后直接将数据返回给客户端。

更新
如果我按照下面的评论建议删除http.StatusOK,那么返回的将是纯文本而不是JSON!

英文:

In my code, I've a loop that processing set of files (based on what available at pre-specified folder), and based on the output of each processed file, some info is sent to the client, so I wrote the below:

	for i, file := range files {
		uniqueSlice := unique(matches)
		output = Output{MSG: "ok", File: file, Skills: uniqueSlice}
		data, err := json.Marshal(output)
		if err != nil {
			panic(err)
		}
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK) // -< Error from here
		w.Write(data)
	}

Above working correctly if the folder has a single file, but if has more than one, I got the error: http: superfluous response.WriteHeader call
I understood the error is due to using w.WriteHeader(http.StatusOK) which can not be used more than once to be set, but I need it to be set for the client to process the returned data.

How can I fix this code, so that I can return data directly to the client upon processing each file.

UPDATE
If I remove http.StatusOK as recommended in the comments below, then I get the returned as plain text not as JSON!

答案1

得分: 1

你不能简单地将JSON文档连接在一起,然后期望结果是有效的JSON编码。你需要将你的output对象放入一个数组中,然后在最后一次输出该数组,否则响应将不是有效的JSON。

如果你像你的代码一样逐个输出对象,最终的数据将会是这样的:

{"MSG": "ok", "File": "...", "Skills": [...]}{"MSG": "ok", "File": "...", "Skills": [...]}{"MSG": "ok", "File": "...", "Skills": [...]}

每个输出本身都是有效的,但是将对象简单地连接在一起的整个输出是无效的

理想情况下,当将JSON输出到像HTTP响应这样的流时,不要将其存储在一个中间缓冲区(data)中,而是使用json.NewEncoder(w),其中w是HTTP响应写入器。流式传输通常比渲染到变量更好。

var outputs = make([]Output, 0, len(files))
for i, file := range files {
    uniqueSlice := unique(matches)
    outputs = append(outputs, Output{MSG: "ok", File: file, Skills: uniqueSlice})
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(outputs); err != nil {
   panic(err)
}
英文:

You can't just concatenate JSON documents together and expect the result to be valid json encoded. You'll have to put your output objects in an array and then output that array once at the end, otherwise the response won't be valid json.

If you output objects individually like your code did, the final data will look like

{"MSG": "ok", "File": "...", "Skills": [...]}{"MSG": "ok", "File": "...", "Skills": [...]}{"MSG": "ok", "File": "...", "Skills": [...]}

Each one of those outputs is valid by itself, but the entire output with the objects just concatenated together, is not.

Ideally, when outputting json to a stream like an HTTP response, instead of storing it in an intermediate buffer (data) for you, use json.NewEncoder(w) where w is the http response writer. Streaming is almost always better than rendering to a variable.

    var outputs = make([]Output,0,len(files)
    for i, file := range files {
        uniqueSlice := unique(matches)
        outputs = append(outputs, Output{MSG: "ok", File: file, Skills: uniqueSlice})
    }
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    if err := json.NewEncoder(w).Encode(outputs); err != nil {
       panic(err)
    }

huangapple
  • 本文由 发表于 2021年8月3日 01:59:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/68626078.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定