Обработчик статических файлов HTTP постоянно показывает список каталогов - PullRequest
0 голосов
/ 04 июля 2018

Когда я реализую статический серверный обработчик, если я получаю доступ к корневому пути, он покажет весь каталог, например:

access to root folder

Мой код:

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

перейти к: http://locahost:3000/statics/

1 Ответ

0 голосов
/ 04 июля 2018

К счастью или нет, стандартное поведение http.FileServer заключается в том, что если путь обозначает каталог без файла index.html, список каталогов будет обслуживаться. И это не обеспечивает простой способ выключить это. Но ...

http.FileServer работает на виртуальной файловой системе, описанной интерфейсом http.FileSystem.

Этот интерфейс имеет единственный метод, который сообщает, как открыть файл и получить http.File «просмотр» его:

type FileSystem interface {
        Open(name string) (File, error)
}

Если вы хотите отключить список каталогов, все, что вам нужно сделать, - это предоставить собственную реализацию 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
}

Использование вышеуказанной пользовательской реализации:

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

И это все. Попытка просмотреть http://locahost:3000/statics/ приведет к ответу по умолчанию:

404 page not found

Примечания:

Приведенная выше реализация выполняет второй Dir.Open() вызов, чтобы вернуть ошибку, которая всегда одинакова. Чтобы «ускорить процесс», мы можем сохранить этот ответ и просто повторно использовать его:

var notFoundFile, notFoundErr = http.Dir("dummy").Open("does-not-exist")

И когда мы обнаруживаем каталог в нашем myfs.Open() методе:

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