HTTP 静态文件处理程序不断显示目录列表

Hau*_* Ma 4 http static-files go

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

访问根文件夹

我的代码是:

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))
}
Run Code Online (Sandbox Code Playgroud)

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

icz*_*cza 6

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

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

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

type FileSystem interface {
        Open(name string) (File, error)
}
Run Code Online (Sandbox Code Playgroud)

如果你想禁用目录列表,你所要做的就是提供你自己的实现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
}
Run Code Online (Sandbox Code Playgroud)

使用上面的自定义实现:

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

就这样。尝试浏览http://locahost:3000/statics/将导致默认响应:

404 page not found
Run Code Online (Sandbox Code Playgroud)

笔记:

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

var notFoundFile, notFoundErr = http.Dir("dummy").Open("does-not-exist")
Run Code Online (Sandbox Code Playgroud)

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

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

  • +1 切入正题。如此基本的功能没有作为选项内置,这似乎仍然很奇怪。 (2认同)