Имеет ли значение, где я рутирую FileServer? - PullRequest
0 голосов
/ 09 июня 2018

На https://www.alexedwards.net/blog/serving-static-sites-with-go, приведен пример статического файлового сервера, обслуживающего сайты в одном каталоге: static.

File: app.go
...
func main() {
  fs := http.FileServer(http.Dir("static"))
  http.Handle("/static/", http.StripPrefix("/static/", fs))

  log.Println("Listening...")
  http.ListenAndServe(":3000", nil)
}

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

func main() {
  fs := http.FileServer(http.Dir(".")) // root at the root directory.
  http.Handle("/static/", fs) //leave off the StripPrefix call.

  log.Println("Listening...")
  http.ListenAndServe(":3000", nil)
}

Существуют ли какие-либо недостатки (производительность или безопасность) при выполнении этого способа?Я вижу, что мне пришлось бы использовать StripPrefix, если мое местоположение файлов в файловой системе не совпадало с URL-адресом, по которому они были предоставлены, но в этом случае кажется, что вызов StripPrefix не нужен.

Редактировать: Я забыл упомянуть, но я сам посмотрел на это.С точки зрения производительности, это не проблема, поскольку вызов FileServer фактически не загружает файлы в память;он просто хранит адрес.С точки зрения безопасности, это похоже на одно и то же: я предпринял попытку обхода каталога, используя что-то вроде следующего.

$ curl -i --path-as-is 'http://localhost:3000/static/../sensitive.txt'

, но я получил ответ 301 с обеими версиями, что меня немного удивило.

1 Ответ

0 голосов
/ 09 июня 2018

То же самое, когда вы используете http.ServeMux обработчик

http.ServeMux вызовет функцию cleanPath до пути совпадения

https://github.com/golang/go/blob/master/src/net/http/server.go#L2305

func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
// snip
    path := cleanPath(r.URL.Path)
//snip
}  

Функция cleanPath возвращаетканонический путь для р, исключая.и .. элементы.

https://github.com/golang/go/blob/master/src/net/http/server.go#L2174-L2193

// cleanPath returns the canonical path for p, eliminating . and .. elements.

func cleanPath(p string) string {
    if p == "" {
        return "/"
    }
    if p[0] != '/' {
        p = "/" + p
    }
    np := path.Clean(p)
    // path.Clean removes trailing slash except for root;
    // put the trailing slash back if necessary.
    if p[len(p)-1] == '/' && np != "/" {
        // Fast path for common case of p being the string we want:
        if len(p) == len(np)+1 && strings.HasPrefix(p, np) {
            np = p
        } else {
            np += "/"
        }
    }
    return np
}
...