Подтвердить что ты не робот

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>
`
4b9b3361

Ответ 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))