Второй FileServer обслуживает html, но не изображения - PullRequest
1 голос
/ 19 марта 2020

Я сталкиваюсь со следующей проблемой с Go и gorilla/mux маршрутизаторами при создании простого API. Я уверен, что это обычная глупая ошибка, которая прямо на моем лице, но я ее не вижу.

Упрощенная структура проекта

|--main.go
|
|--public/--index.html
|        |--image.png
|
|--img/--img1.jpg
|     |--img2.jpg
|     |--...
|...

main.go

package main

import (
    "net/http"
    "github.com/gorilla/mux"
)

var Router = mux.NewRouter()

func InitRouter() {
    customers := Router.PathPrefix("/customers").Subrouter()

    customers.HandleFunc("/all", getAllCustomers).Methods("GET")
    customers.HandleFunc("/{customerId}", getCustomer).Methods("GET")
    // ...
    // Registering whatever middleware
    customers.Use(middlewareFunc)

    users := Router.PathPrefix("/users").Subrouter()

    users.HandleFunc("/register", registerUser).Methods("POST")
    users.HandleFunc("/login", loginUser).Methods("POST")
    // ...

    // Static files (customer pictures)
    var dir string
    flag.StringVar(&dir, "images", "./img/", "Directory to serve the images")
    Router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir))))

    var publicDir string
    flag.StringVar(&publicDir, "public", "./public/", "Directory to serve the homepage")
    Router.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(publicDir))))
}

func main() {
    InitRouter()
    // Other omitted configuration
    server := &http.Server{
        Handler: Router,
        Addr:    ":" + port,
        // Adding timeouts
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }

    err := server.ListenAndServe()
    // ...
}

Подпрограммы работают нормально, с промежуточным ПО и всем. Изображения под img корректно обслуживаются, если я go до localhost:5000/static/img1.png.

Дело в том, что при переходе на localhost:5000 подается index.html, который находится в public, но затем localhost:5000/image.png вместо 404 not found.

Что здесь происходит?

1 Ответ

1 голос
/ 19 марта 2020

Измените эту строку:

// handles '/' and *ONLY* '/'
Router.Handle("/",
        http.StripPrefix("/", http.FileServer(http.Dir(publicDir))))

На это:

// handles '/' and all sub-routes
Router.PathPrefix("/").Handler(
        http.StripPrefix("/",http.FileServer(http.Dir(publicPath))))

По сути, в вашем исходном коде маршрутизатор для / обрабатывает этот путь и только этот путь (без под-маршрутов).

Вы можете удивиться, почему ваш исходный код "работал" хотя бы для одного файла (index.html). Причина в том, что http.FileServer с указанным путем, который является каталогом, а не файлом, по умолчанию будет обслуживать файл страницы индекса index.html (см. FileServer source ).

Использование PathPrefix позволяет обработчику (fileserver) принимать все пути URL ниже пути /.

...