【问题标题】:http.FileServer caching files and serving old versions after edithttp.FileServer 缓存文件并在编辑后提供旧版本
【发布时间】:2013-12-20 11:05:09
【问题描述】:

go 核心中的 http 包存在问题。尽管响应正文中的 Content-Length 是正确的,但文件内容似乎已被缓存。在这里演示的是我正在编写的应用程序的简化版本。

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.Handle("/", http.FileServer(http.Dir("./www/")))
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        fmt.Println(err)
    }
}

现在假设我们有一个非常简单的 html 页面:

<!doctype html>
<html>
<body>
    <p>Hello there</p>
</body>
</html>

我执行 go 程序并在浏览器中访问http://localhost:8080 以显示:

Hello there

检查响应头我可以看到以下内容:

Status Code:200 OK
Accept-Ranges:bytes
Content-Length:68
Content-Type:text/html; charset=utf-8
Date:Fri, 20 Dec 2013 10:04:03 GMT
Last-Modified:Fri, 20 Dec 2013 10:03:32 GMT

现在我编辑 html 文件,使 &lt;p&gt; 标记包含 Hello there everyone 并重新加载页面。我得到以下信息:

Hello there

再次查看我得到的响应标头

Status Code:200 OK
Accept-Ranges:bytes
Content-Length:77
Content-Type:text/html; charset=utf-8
Date:Fri, 20 Dec 2013 10:04:34 GMT
Last-Modified:Fri, 20 Dec 2013 10:04:14 GMT

所以Content-Length 已更改以及上次修改,但不是 http.FileServer 处理程序传递的实际文件内容。即使在关闭程序并执行go run src/.../main.go 之后也会发生此问题。到目前为止,我发现清除明显缓存的文件版本的唯一方法是重新启动正在运行程序的机器。

我尝试了以下方法:

  • 在 win/ubuntu/osx 10.8.5 上执行程序
  • 通过 golang.org/src 上的函数/接口链查看服务文件是否缓存在磁盘上的任何位置

对此的任何帮助将不胜感激。

【问题讨论】:

  • 您使用的是网络浏览器还是命令行工具?
  • 感谢您的输入,请阅读 cmets。我已经使用多个 Web 浏览器、命令行工具以及在 Windows、Linux 和 Mac 上运行 go 服务器复制了这种行为。
  • 我无法使用这个版本go version go1.2 darwin/amd64重现问题。

标签: http go


【解决方案1】:

好的,所以在忽略了这个问题几周并继续前进之后,我终于弄清楚了问题所在。

为了让我的主计算机完全不定制,我使用 Vagrant 来开发使用 golang、nodejs 和 php 的应用程序。似乎在 Virtual Box 共享上运行 go 应用程序并在该共享上存储所有 html 文件会导致此问题。

为了证明这一点,我创建了一个 Vagrant 框并将文件从 /vagrant 共享目录复制到 /home/vagrant/testing/,然后复制了之前列出的所有操作。这使问题消失了。

换句话说,不要使用 Virtual Box 共享文件夹来托管打算在 http.FileServer 方法中使用的文件。

【讨论】:

【解决方案2】:

直到 VirtualBox 解决了这个问题,我制作了一个 go 文件,可以将其放入项目中以禁用对当前进程的 sendfile 支持,然后 go http 包将回退到 io.Copy。还可以与 boot2docker 一起使用,只需进行一些小的 docker 配置更改。

https://github.com/wader/disable_sendfile_vbox_linux

使用较新版本的 firejail,您可以使用以下方法执行相同的操作:

firejail --seccomp.enotsup=sendfile ./program

【讨论】:

  • 太棒了,解决了确切的问题!我很早就知道这个问题在 vboxsf 中,这实际上使得在 Win 主机 + Linux 客户机上的开发无法使用。令人难以置信的是,这个错误已经存在了多长时间并且没有得到修复。
  • 不错。如果您可以使用 docker mac/windows 进行开发,我认为您不再需要破解
【解决方案3】:

如果您使用某种代理,那就是问题所在。一些代理缓存经常使用的文件(通常只有 .js、.css 等,但通常不是 .html)和 IP 地址。如果服务器在您的本地计算机上,请尝试使用localhost127.0.0.1 而不是IP 地址,这样请求就不会通过代理。如果不是,您必须配置或禁用代理才能访问最新版本的网站。我不知道这有多普遍,但是,这将是问题所在。

【讨论】:

  • 感谢您的意见。没有代理服务器在本地机器上运行(我尝试过mac、windows pc和ubuntu pc)。问题在于跨浏览器、命令行(wget 等)以及 go 程序在 VM 和物理机器上的多个不同机器(windows、mac、linux)上运行。
【解决方案4】:

这可能是客户端问题,您使用的是什么浏览器? 也许你可以尝试不同的浏览器,curl,wget 等...

【讨论】:

  • 感谢您的输入,我在 Ubuntu/os10.8.5/win 和 ie10/11 上尝试过 chrome 和 ff。没有尝试使用 curl/wget,但如果所有这些浏览器/操作系统组合都失败,则意义不大。
  • 浏览器可以在重启和系统重启之间缓存响应,但 wget 不会。
  • 嗨,是的,我明白了。我现在已经用 wget 进行了测试,并且和以前一样存在同样的问题。我很确定这不会是浏览器问题,因为尝试了几个浏览器,在编辑提供的 html 文件之间完全清除缓存。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-09
  • 1970-01-01
  • 2011-11-18
  • 1970-01-01
  • 2019-10-31
  • 2014-05-09
  • 1970-01-01
相关资源
最近更新 更多