使用Go中的http.FileServer禁用目录列表的好方法 [英] Good way to disable directory listing with http.FileServer in Go

查看:2175
本文介绍了使用Go中的http.FileServer禁用目录列表的好方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If you use the http.FileServer in Go like:

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响应,我也想要这种行为。

Then accessing a directory will give you a listing of files. Often this is disabled for web services and instead responds with 404 and I would like this behaviour too.

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

http.FileServer has no options for this AFAIK and I have seen a proposed way to solve this here https://groups.google.com/forum/#!topic/golang-nuts/bStLPdIVM6w what they do is wrapping the http.FileSystem type and implementing an own Open method. However this doesn't give a 404 when the path is a directory, it just gives a blank page, and it's unclear how to modify it to accomodate this. This is what they do:

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 返回nil,os.ErrNotExist 然后你得到一个500响应错误阅读目录 - 而不是404。

Note: if you make Readdir return nil, os.ErrNotExist then you get a 500 response with "Error reading directory" - not 404.

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

Any ideas on how to neatly present a 404 and still preserving the feature of automatically finding an index.html if present?

推荐答案

如果不替换 Readdir 方法,可以更改此行为,但 Stat

请查看下面的工作代码。它支持 index.html 文件的服务,如果它们在请求的目录中并且返回 404 以防没有 index.html ,它是一个目录。

This behavior can be changed if you substitute not a Readdir method, but the Stat.
Please take a look at working code below. It supports serving of index.html files if they are inside of requested directory and returns 404 in case there is no index.html and it is a directory.

    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)
    }

这篇关于使用Go中的http.FileServer禁用目录列表的好方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆