Мультиплексор Golang Gorilla с http.FileServer, возвращающий 404

Проблема, которую я вижу, заключается в том, что я пытаюсь использовать http.FileServer с функцией Gorilla mux Router.Handle.

Это не работает (изображение возвращает 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/"))))

Ниже приведена простая программа веб-сервера go, показывающая проблему ...

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

person dodgy_coder    schedule 20.01.2014    source источник


Ответы (2)


Я разместил это в группе обсуждения golang-nut и получил это решение от Тони Карденаса ...

Стандартный net / http ServeMux (который является стандартным обработчиком, который вы используете при использовании http.Handle) и маршрутизатор мультиплексора имеют разные способы сопоставления адреса.

Посмотрите различия между http://golang.org/pkg/net/http/#ServeMux и http://godoc.org/github.com/gorilla/mux.

Итак, в основном http.Handle('/images/', ...) соответствует '/ images / something', а myRouter.Handle('/images/', ...) только соответствует '/ images /', и если вы хотите обработать '/ images / something', вы должны ...

Вариант 1. Используйте соответствие регулярному выражению в вашем маршрутизаторе.

myRouter.Handle("/images/{rest}",
     http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))

Вариант 2. Используйте на маршрутизаторе метод PathPrefix:

myRouter.PathPrefix("/images/").Handler(http.StripPrefix("/images/", 
     http.FileServer(http.Dir(HomeFolder + "images/"))))
person dodgy_coder    schedule 21.01.2014
comment
+1 # 2 был для меня успешным в текущем проекте (до того, как я наткнулся на этот ответ. Просто заверил читателей, что # 2 - это то, что я использую и работает). - person eduncan911; 04.06.2014
comment
Просто примечание для добавления, пожалуйста, помните, если вы новичок в golang, как я, golang не любит утверждения, отформатированные в # 2. Мне нужно было объединить все три строки в одну (без изменений синтаксиса, только изменения в пробелах), прежде чем golang перестанет жаловаться на ожидание запятых. №2 - правильный ответ, он просто составлен таким образом, что вызовет проблемы у новичков и новичков, таких как я. - person Owen Ivory; 21.12.2017
comment
Вы правы, мне пришлось заключить заявление в одну строчку. - person farhany; 02.03.2018
comment
Большое спасибо за то, что избавили меня от многих часов страданий, у меня работали PathPrefix и StripPrefix, я перешел с r.Handle("/", fs) на r.PathPrefix("/").Handler(http.StripPrefix("/", fs)) - person SamGamgee; 17.05.2019
comment
@SamGamgee - вы можете пойти еще дальше и опустить http.StripPrefix(), чтобы в итоге получилось r.PathPrefix("/").Handler(fs) - person Rob Bell; 11.04.2020

По состоянию на май 2015 года пакет gorilla / mux все еще не имеет выпусков версий. Но теперь проблема в другом. Дело не в том, что myRouter.Handle не соответствует URL-адресу и требует регулярного выражения, это действительно так! Но http.FileServer требует, чтобы префикс был удален из URL-адреса. Пример ниже работает нормально.

ui := http.FileServer(http.Dir("ui"))
myRouter.Handle("/ui/", http.StripPrefix("/ui/", ui))

Обратите внимание, что в приведенном выше примере нет / ui / {rest}. Вы также можете обернуть http.FileServer в logger gorilla / handler и увидеть запрос на приход к 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))
person smile-on    schedule 01.05.2015
comment
Метод Handle по умолчанию для router по-прежнему создает route так же, как и раньше. Я попробовал метод, который вы указали выше, и "/ui/" не будет соответствовать всем путям с префиксом "/ui/". Решение @ dodgy_coder правильное. Либо включите регулярное выражение с методом по умолчанию Handler, либо используйте PathPrefix - person thecalvinchan; 11.05.2015