dsh1102
2018-03-31 15:57
浏览 410
已采纳

在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
", *directory, *port)
    log.Fatal(http.ListenAndServe(":"+*port, nil))
}

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

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

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

图片转代码服务由CSDN问答提供 功能建议

如果在Go语言中使用http.FileServer,例如:

  func main(){
端口:= flag.String(“ p”,“ 8100”,“要使用的端口”)
目录:= flag.String(“ d”,“。”,“目录 静态文件到主机“)
 flag.Parse()
 
 http.Handle(” /“,http.FileServer(http.Dir(* directory)))
 
 log.Printf(”正在服务%  s在HTTP端口上:%s 
“,*目录,* 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(名称字符串)(http.File  ,错误){
f,err:= fs.fs.Open(name)
如果err!= nil {
返回nil,err 
} 
返回neuteredReaddirFile {f},nil 
} 
 \  ntype neuteredReaddirFile struct {
 http.File 
} 
 
func(f neuteredReaddirFile)Readdir(count int)([] os.FileInfo,error){
返回nil,nil 
} 
 
func main(  ){
 fs:= justFilesFilesystem {http.Dir(“ / tmp /”)} 
 http.ListenAndServe(“:8080”,http.FileServer(fs))
} 
   
 
 

注意:如果您使Readdir 返回nil,即os.ErrNotExist ,那么您将收到500错误,显示“错误读取目录”,而不是404。 \ n

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

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • duankange2433 2018-03-31 20:45
    已采纳

    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)
        }
    
    已采纳该答案
    打赏 评论

相关推荐 更多相似问题