【问题标题】:HTTP Static file handler keeps showing the directory listHTTP 静态文件处理程序不断显示目录列表
【发布时间】:2018-12-12 15:49:21
【问题描述】:

当我实现一个静态服务器处理程序时,如果我访问根路径,它将显示整个目录,如下所示:

我的代码是:

package main

import (
    "flag"
    "log"
    "net/http"
    "strings"
)

func main() {
    port := flag.String("p", "3000", "port to serve on")
    directory := flag.String("d", ".", "the directory of static file to host")
    flag.Parse()

    http.Handle("/statics/", http.StripPrefix(strings.TrimRight("/statics/", "/"), http.FileServer(http.Dir(*directory))))

    log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
    log.Fatal(http.ListenAndServe(":"+*port, nil))
}

转到:http://locahost:3000/statics/

【问题讨论】:

  • 也许这就是您要找的东西?然而,由此产生的答案对我来说有点肮脏。它基本上只包括检查当前请求的资源是目录还是文件并相应地处理它。 stackoverflow.com/questions/49589685/…
  • 呃,是的,这就是Dir 所做的:A Dir implements FileSystem using the native file system restricted to a specific directory tree 到底是什么问题?
  • @RickyA 问题是大多数其他服务器在访问目录时默认返回 404,这是一个非常明智的安全默认设置。 Go 没有提供关闭它的方法。基本上,问题的答案归结为Dir 文档的最后一段:“创建自定义文件系统实现。”
  • @RayfenWindspear 这是一个假设。也许 OP 期望一个 index.html 被渲染,所以我想从 OP 那里听到它。
  • @RickyA 不要显得粗鲁,但这似乎是一个安全的假设。使用 css、js 等提供“静态”目录通常不会在目录的statics/ 级别有 index.html,因为它只是单独类型静态的容器。但是,是的,尽管如此,一个假设......

标签: http go static-files


【解决方案1】:

幸运与否,http.FileServer 的默认行为是,如果路径表示没有index.html 文件的目录,则将提供目录列表。而且它没有提供一种简单的方法来关闭它。但是……

http.FileServerhttp.FileSystem 接口描述的虚拟文件系统上运行。

这个接口有一个方法告诉如何打开一个文件,并获得一个http.File“视图”:

type FileSystem interface {
        Open(name string) (File, error)
}

如果你想禁用目录列表,你所要做的就是提供你自己的http.FileSystem 实现,当一个目录被定位时,你只需报告/返回一个错误。仅此而已。

当然,您不必自己做这一切。您可以创建自己的FileSystem,它使用/利用http.Dir,这是使用本机文件系统的默认实现(仅限于特定的目录树)。

type myfs struct {
    http.Dir
}

func (m myfs) Open(name string) (result http.File, err error) {
    f, err := m.Dir.Open(name)
    if err != nil {
        return
    }

    fi, err := f.Stat()
    if err != nil {
        return
    }
    if fi.IsDir() {
        // Return a response that would have been if directory would not exist:
        return m.Dir.Open("does-not-exist")
    }
    return f, nil
}

使用上面的自定义实现:

handler := http.FileServer(myfs{http.Dir(*directory)})
http.Handle(
    "/statics/",
    http.StripPrefix(strings.TrimRight("/statics/", "/"), handler),
)

仅此而已。尝试浏览 http://locahost:3000/statics/ 将导致默认响应:

404 page not found

注意事项:

上面的实现第二次调用Dir.Open() 来返回一个错误,这总是一样的。为了“加快速度”,我们可以存储此响应并重复使用它:

var notFoundFile, notFoundErr = http.Dir("dummy").Open("does-not-exist")

当我们在myfs.Open() 方法中检测到目录时:

if fi.IsDir() {
    // Return a response that "belogns" to opening a non-existing folder:
    return notFoundFile, notFoundErr
}

【讨论】:

  • +1 开门见山。如此基本的功能没有作为选项内置似乎仍然很奇怪。
  • @RayfenWindspear 我同意,http.FileServer 可以使用一点定制,以符合公众的最大利益...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 2011-07-21
  • 2020-01-15
  • 1970-01-01
  • 2018-01-22
相关资源
最近更新 更多