Хороший способ отключить список каталогов с помощью http.FileServer в Go
Если вы используете http.FileServer в Go, как:
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))
}
Затем доступ к каталогу даст вам список файлов. Часто это отключено для веб-сервисов и вместо этого отвечает 404, и я хотел бы, чтобы такое поведение также.
http.FileServer не имеет опций для этого AFAIK, и я видел предложенный способ решить эту проблему здесь https://groups.google.com/forum/ то, что они делают, это обертывание 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 ответ
Это поведение может быть изменено, если вы заменяете не 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)
}