Golang Gorilla mux с http.FileServer, возвращающим 404
Проблема, которую я вижу, заключается в том, что я пытаюсь использовать http.FileServer
с функцией Moll Router.Handle в Gorilla.
Это не работает (изображение возвращает 404).
myRouter := mux.NewRouter()
myRouter.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))
это работает (изображение отображается в порядке).
http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))
Простая программа веб-сервера ниже, показывающая проблему...
package main
import (
"fmt"
"net/http"
"io"
"log"
"github.com/gorilla/mux"
)
const (
HomeFolder = "/root/test/"
)
func HomeHandler(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, htmlContents)
}
func main() {
myRouter := mux.NewRouter()
myRouter.HandleFunc("/", HomeHandler)
//
// The next line, the image route handler results in
// the test.png image returning a 404.
// myRouter.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))
//
myRouter.Host("mydomain.com")
http.Handle("/", myRouter)
// This method of setting the image route handler works fine.
// test.png is shown ok.
http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))
// HTTP - port 80
err := http.ListenAndServe(":80", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
fmt.Printf("ListenAndServe:%s\n", err.Error())
}
}
const htmlContents = `<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Test page</title>
<meta charset = "UTF-8" />
</head>
<body>
<p align="center">
<img src="/images/test.png" height="640" width="480">
</p>
</body>
</html>
`
Ответы
Ответ 1
Я разместил это в группе обсуждения golang-nuts и получил это решение от Toni Cárdenas...
Стандартный net/http ServeMux (который является стандартным обработчиком, который вы используете, когда используете http.Handle
), и маршрутизатор мультиплексирования имеет разные способы согласования адреса.
См. различия между http://golang.org/pkg/net/http/#ServeMux и http://godoc.org/github.com/gorilla/mux.
В принципе, http.Handle('/images/', ...)
соответствует '/images/whatever', а myRouter.Handle('/images/', ...)
соответствует только "/images/", и если вы хотите обрабатывать "/images/whatever", вам нужно...
- установите соответствие регулярного выражения в маршрутизаторе или
- используйте метод PathPrefix на вашем маршрутизаторе, например:
Примеры кода
1.
myRouter.Handle('/images/{rest}',
http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/")))
)
2.
myRouter.PathPrefix("/images/").Handler(
http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/")))
)
Ответ 2
По состоянию на май 2015 г. gorilla/mux пакет по-прежнему не имеет версий выпуска. Но теперь проблема другая. Дело не в том, что myRouter.Handle
не соответствует URL-адресу и нуждается в регулярном выражении, так оно и есть! Но http.FileServer
требует, чтобы префикс удалялся из url. Ниже пример отлично работает.
ui := http.FileServer(http.Dir("ui"))
myRouter.Handle("/ui/", http.StripPrefix("/ui/", ui))
Обратите внимание: в примере abowe нет /ui/ {rest}. Вы также можете обернуть http.FileServer
в gorilla/handler logger и посмотреть запрос на переход к FileServer и ответ 404.
ui := handlers.CombinedLoggingHandler(os.Stderr,http.FileServer(http.Dir("ui"))
myRouter.Handle("/ui/", ui) // getting 404
// works with strip: myRouter.Handle("/ui/", http.StripPrefix("/ui/", ui))