提问人:LukeAtmi 提问时间:11/17/2023 更新时间:11/17/2023 访问量:68
Go HTTP服务器重置带有文件和文本的多部分表单上的连接
Go HTTP server resets connection on multipart form with file and text
问:
我一直在尝试在 Go 中设置一个 HTTP 服务器,允许用户通过 HTML 表单上传文件。出于其他原因,此表单还将具有文本输入。但是,在提交表单时,我的浏览器报告连接已重置(我尝试过使用 Firefox 和 Chromium),检查显示服务器在重置之前甚至没有到达上传端点的处理程序功能,尽管它没有崩溃。奇怪的是,当表单中的唯一输入是文件和提交时,这不会发生。
这是最小的复制品:
package main
import (
"fmt"
"net/http"
)
func showPage(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w,
`<!DOCTYPE html>
<html>
<body>
<form enctype="multipart/form-data" action="/upload">
<input type="file" name="file" />
<input type="text" name="lol" />
<input type="submit" value="upload" />
</form>
</body>
</html>`)
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("yay!")
fmt.Fprint(w, "yay!")
}
func main() {
http.HandleFunc("/", showPage)
http.HandleFunc("/upload/", uploadHandler)
http.ListenAndServe(":8080", nil)
}
运行上述代码并在表单 at 中提交文件应显示“yay!”页面,并在服务器控制台上打印“yay!”。相反,在提交足够大的文件(非常小的文件不会导致问题)时,连接将重置,并且控制台上不会打印任何内容。这个 5MB 的音频样本足够大,足以让我出现问题。http://localhost:8080/
如果表单中的唯一输入是文件,则出于某种原因,一切运行正常。
答:
1赞
Maristela Vasco
11/17/2023
#1
处理程序不读取任何请求正文。
从处理程序返回时,当未读请求正文的大小大于 262,144 字节时,net/http 服务器将关闭连接。
客户端在尝试写入请求正文时收到连接重置。客户端在读取响应之前出错。
通过读取请求正文进行修复。鉴于您需要多部分表单,因此调用 ParseMultipartForm 是读取请求正文的最简单方法。
func uploadHandler(w http.ResponseWriter, r *http.Request) {
if err := r.ParseMultipartForm(65535); err != nil {
http.Error(w, "bad request", 400)
return
}
fmt.Println("yay!")
fmt.Fprint(w, "yay!")
}
评论
0赞
LukeAtmi
11/17/2023
明白了。这解释了这个问题,但如何修复/规避它呢?我认为有一种正确的方法可以做到这一点。
1赞
erik258
11/17/2023
HTTP 规范要求服务器先读取请求正文,然后才能发送响应正文。继续在请求中实现对 MultiPartForm 上传的处理。
0赞
LukeAtmi
11/17/2023
当我发现这个问题时,我实际上正在这样做。但是,由于在重置之前甚至从未调用过 uploadHandler,因此我没有机会解析表单。
上一个:在文件输入中跟踪文件选择
评论
log.Fatal(http.ListenAndServe(":8080", nil))