使用Go中的http.FileServer禁用目录列表的好方法

时间:2018-03-31 15:57:33

标签: http go fileserver

如果你在Go中使用http.FileServer:

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

    http.Handle("/", http.FileServer(http.Dir(*directory)))

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

然后访问目录将为您提供文件列表。通常这对于Web服务是禁用的,而是以404响应,我也希望这种行为。

http.FileServer没有这个AFAIK的选项,我已经看到了一种解决这个问题的方法https://groups.google.com/forum/#!topic/golang-nuts/bStLPdIVM6w他们做的是包装http.FileSystem类型并实现自己的Open方法。然而,当路径是目录时,这不会给出404,它只是给出一个空白页面,并且不清楚如何修改它以容纳这个。这就是他们所做的:

type justFilesFilesystem struct {
    fs http.FileSystem
}

func (fs justFilesFilesystem) Open(name string) (http.File, error) {
    f, err := fs.fs.Open(name)
    if err != nil {
        return nil, err
    }
    return neuteredReaddirFile{f}, nil
}

type neuteredReaddirFile struct {
    http.File
}

func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
    return nil, nil
}

func main() {
    fs := justFilesFilesystem{http.Dir("/tmp/")}
    http.ListenAndServe(":8080", http.FileServer(fs))
}

注意:如果您使用Readdir return nil, os.ErrNotExist,那么您将获得500响应“错误读取目录” - 而不是404.

关于如何巧妙地呈现404并仍然保留自动查找index.html的功能的任何想法?

1 个答案:

答案 0 :(得分:2)

如果您不是Readdir方法,而是替换Stat,则可以更改此行为 请看下面的工作代码。如果index.html文件位于请求的目录中,它支持提供404文件,如果没有index.html则返回 package main import ( "io" "net/http" "os" ) type justFilesFilesystem struct { fs http.FileSystem // readDirBatchSize - configuration parameter for `Readdir` func readDirBatchSize int } func (fs justFilesFilesystem) Open(name string) (http.File, error) { f, err := fs.fs.Open(name) if err != nil { return nil, err } return neuteredStatFile{File: f, readDirBatchSize: fs.readDirBatchSize}, nil } type neuteredStatFile struct { http.File readDirBatchSize int } func (e neuteredStatFile) Stat() (os.FileInfo, error) { s, err := e.File.Stat() if err != nil { return nil, err } if s.IsDir() { LOOP: for { fl, err := e.File.Readdir(e.readDirBatchSize) switch err { case io.EOF: break LOOP case nil: for _, f := range fl { if f.Name() == "index.html" { return s, err } } default: return nil, err } } return nil, os.ErrNotExist } return s, err } func main() { fs := justFilesFilesystem{fs: http.Dir("/tmp/"), readDirBatchSize: 2} fss := http.FileServer(fs) http.ListenAndServe(":8080", fss) } 并且它是一个目录。

        r = requests.get('https://api.wit.ai/message?v=20160918&q=%s' % speech,
                         headers={"Authorization": wit_ai_token})
        print r.text
        json_resp = json.loads(r.text)
        entities = None
        intent = None
        if 'entities' in json_resp:
            entities = json_resp['entities']
            intent = json_resp['entities']['time']['value']