Go Gorilla Mux не выполняет маршрутизацию, как ожидалось

У меня возникли проблемы с получением библиотеки Gorilla Mux для работы с Go. Из документации, которую я прочитал, и всей отладки, которую я сделал, я не могу понять, в чем проблема. Вот что у меня есть для маршрутизации:

Структура папки:

project_root
  |-- main.go
  |-- routes
         |-- routes.go
         |-- user.go

main.go:

package main

import (
    "fmt"
    "net/http"

    "./routes"
)

func main() {
    r := routes.CreateRoutes(http.Dir("./content"))

    http.Handle("/", r)
    err := http.ListenAndServe(fmt.Sprintf("%s:%d", "localhost", 8000), nil)
    if err != nil {
        fmt.Println("Error: ", err)
    }
}

маршруты/routes.go

package routes

import (
    "net/http"

    "github.com/gorilla/mux"
)

func CreateRoutes(staticDir http.FileSystem) *mux.Router {
    r := mux.NewRouter()

    // Serve static pages (i.e. web app)
    r.PathPrefix("/").Handler(http.FileServer(staticDir))

    // Serve User Pages
    createUserRoutes(r)

    return r
}

маршруты /user.go

package routes

import (
    "fmt"
    "net/http"

    "github.com/gorilla/mux"
)

func createUserRoutes(r *mux.Router) {
    user := r.PathPrefix("/user/").Subrouter()

    // Create a new user
    user.Path("/new").Methods("PUT").HandlerFunc(newUserHandler)

    // Remove a user
    user.Path("/remove/{username:[a-z][a-z0-9]+}").Methods("DELETE").HandlerFunc(removeUserHandler)

    // Update a user
    user.Path("update/{username:[a-z][a-z0-9]+").Methods("POST").HandlerFunc(updateUserHandler)

    // Get a user (Get user information)
    user.Path("/{username:[a-z][a-z0-9]+").Methods("GET").HandlerFunc(getUserHandler)
}

func newUserHandler(resp http.ResponseWriter, req *http.Request) {
    // Do something that might cause an error        

    if err != nil {
        fmt.Println(err)
        resp.WriteHeader(409)
        resp.Write([]byte(err.Error()))
    } else {
        fmt.Println("Created new user")
        resp.WriteHeader(201)
        resp.Write([]byte("Created new user"))
    }
}

func removeUserHandler(resp http.ResponseWriter, req *http.Request) {
}

func updateUserHandler(resp http.ResponseWriter, req *http.Request) {
}

func getUserHandler(resp http.ResponseWriter, req *http.Request) {
}

Всякий раз, когда я делаю запрос на корневой путь сервера (т. е. путь, который обслуживает статический контент), сервер отвечает, как и предполагалось, с главной страницей. Однако любые другие вызовы приводят к ответу 404 (я тестирую запросы, используя cURL). Например, неправильно сформированный запрос к http://localhost:8000/user/new должен вернуть 409, но вместо этого возвращает 404. То же самое, если я ожидаю ответа 201.

Все выглядит правильно, и я трижды проверил это, но я не могу понять, в чем здесь проблема.


person tugayac    schedule 18.02.2015    source источник
comment
gorilla/mux и net/http обрабатывают маршруты по-разному: stackoverflow.com/questions/21234639/   -  person korylprince    schedule 18.02.2015
comment
Спасибо, но я не думаю, что это решает мою проблему (если только я не упустил что-то из этого поста, что я должен применить в своем). У меня нет проблем с обслуживанием статических файлов. Моя проблема связана с другими вызовами HTTP, такими как запрос PUT на localhost:8000/user/new на создать нового пользователя.   -  person tugayac    schedule 19.02.2015
comment
Извиняюсь. Я неправильно понял, что вы сказали. Я думал, что вы получаете 404 на статических файлах.   -  person korylprince    schedule 19.02.2015
comment
Не волнуйтесь! Я все-таки решил проблему. Опубликовал мой ответ ниже, если вам интересно.   -  person tugayac    schedule 19.02.2015


Ответы (1)


Оказывается, решение было простым (как обычно). Эта строка в route.go

r.PathPrefix("/").Handler(http.FileServer(staticDir))

вызывал непреднамеренную маршрутизацию. Когда используется PathPrefix, кажется, что все URL-адреса направляются к первому подходящему префиксу (в данном случае этому префиксу). Это объясняет, почему статические файлы обслуживались, но больше ничего не работает.

Исправление заключается в использовании вместо этого функции Path. Есть тонкая разница, как объясняется в документах; PathPrefix «соответствует, если данный шаблон является префиксом полного пути URL», а Path — нет. Следовательно, строка выше теперь выглядит так, чтобы решить проблему, с которой я столкнулся:

r.Path("/").Handler(http.FileServer(staticDir))
person tugayac    schedule 19.02.2015