为什么在golang web处理程序中“写入”文件后的消息没有显示?

1qczuiv0  于 2023-01-18  发布在  Go
关注(0)|答案(2)|浏览(139)

我正在使用golang web服务器和处理程序,遇到了一个小问题。我想提供一个包含以下文本的文件。问题是消息没有显示。下面是处理程序代码:

mux := http.NewServeMux()

mux.HandleFunc("/myfile", func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "./ui/static/js/main.js")
    w.Write([]byte("Message after (1)"))
    w.Write([]byte("Message after (2)"))
    fmt.Println("Console message!")
})

http.ListenAndServe(":4000", mux)

浏览器中的输出为:

var navLinks = document.querySelectorAll("nav a");
for (var i = 0; i < navLinks.length; i++) {
    var link = navLinks[i]
    if (link.getAttribute('href') == window.location.pathname) {
        link.classList.add("live");
        break;
    }
}

但是当我在文件之前写入一条(或多条)消息时,它会同时显示文件之前和之后的消息:

mux := http.NewServeMux()

mux.HandleFunc("/myfile", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Message 1 (before)"))
    http.ServeFile(w, r, "./ui/static/js/main.js")
    w.Write([]byte("Message 1 (after)"))
    w.Write([]byte("Message 2 (after)"))
    fmt.Println("Console message!")
})

http.ListenAndServe(":4000", mux)

浏览器中的输出为:

Message 1 (before)var navLinks = document.querySelectorAll("nav a");
for (var i = 0; i < navLinks.length; i++) {
    var link = navLinks[i]
    if (link.getAttribute('href') == window.location.pathname) {
        link.classList.add("live");
        break;
    }
}Message 1 (after)Message 2 (after)

有没有人知道为什么会发生这种情况,以及如何修复它?换句话说,为什么文件之前没有消息,文件之后的消息却没有显示?
fmt.Println("Console message!")始终显示在控制台中。

t3psigkw

t3psigkw1#

net/http服务器会执行以下三项与响应主体的帧相关的操作:

  • 如果应用程序在第一次调用write之前设置了响应内容长度标头,则服务器使用标识编码和应用程序指定的内容长度标头。
  • 如果响应正文适合固定大小的缓冲区(当前为2048字节),则服务器将内容长度标头设置为实际内容长度并使用标识编码。
  • 否则,服务器将使用没有内容长度响应头的分块编码。

以上是指服务器写入网络的内容。服务器不会使用这些值更新响应写入器标头。

第一个示例:

对http.serveFile的调用将响应内容长度标头设置为第一次调用Write之前的文件大小。客户端读取内容长度标头指定的字节数。
内容长度不包括两条消息的大小。客户端将忽略这两条消息,或者这两条消息将导致网络连接上的下一个HTTP事务出错。

第二个示例(调用ServeFile之前写入):

在第一次调用Write之后,对响应标头的修改将被忽略。ServeFile函数将响应内容长度标头设置为文件的大小,但该值将被忽略。
客户机读取所有消息和文件,因为服务器使用了分块编码或将内容长度标头设置为文件的实际大小。
由于ServeFile无法设置响应标头或响应状态代码,因此某些ServeFile功能可能会正常工作。

修复

在处理程序中打开文件并复制到响应。不能使用http. ServeFile。

wbgh16ku

wbgh16ku2#

http.ServeFile尝试设置Content-Length标头(沿着一堆其他的头文件,这些头文件很适合服务静态文件,比如Last-Modified)。由于它将Content-Length设置为文件的长度,浏览器在文件的最后一个字节后退出侦听。如果执行w.Write([]byte("Message 1 (before)")),则会跳到响应主体部分,使http.ServeFile无法设置任何头部。

相关问题