Go Gorilla Mux没有按预期进行路由。

huangapple go评论79阅读模式
英文:

Go Gorilla Mux not routing as expected

问题

我在使用Go语言的Gorilla Mux库时遇到了问题。根据我阅读的文档和进行的所有调试,我似乎无法找出问题所在。以下是我的路由设置:

文件夹结构:

项目根目录
  |-- 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/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
}

routes/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) {
    // 做一些可能导致错误的操作

	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响应也是一样。

一切看起来都没问题,我已经三次检查过,但是我无法找出问题所在。

英文:

I am having issues getting the Gorilla Mux library for Go to work. From the documentation I have read and all the debugging I've done, I cannot seem to figure out what the problem is. Here's what I've got for routing:

Folder structure:

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/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
}

routes/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) {
}

Whenever I make a request to root path of the server (i.e. the path that serves the static content), the server responds as intended, with the main page. However, any other calls result in a 404 response (I test requests using cURL). For example, a malformed request to http://localhost:8000/user/new should return a 409, but instead returns a 404. Same if I expect a 201 response.

Everything looks right and I've triple checked it, but I cannot figure out what the issue here is.

答案1

得分: 1

原来解决方案很简单(通常都是这样)。在routes.go文件中,这一行代码:

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

导致了意外的路由问题。当使用PathPrefix时,它似乎将所有URL路由到第一个匹配的前缀(在这种情况下是该前缀)。这就解释了为什么静态文件可以被访问,但其他内容无法正常工作。

修复方法是使用Path函数。文档中解释了PathPrefix和Path之间的微妙差别;PathPrefix "如果给定的模板是完整URL路径的前缀,则匹配",而Path则不是。因此,为了解决我遇到的问题,上面的代码现在变成了这样:

r.Path("/").Handler(http.FileServer(staticDir))
英文:

Turns out the solution was simple (like it usually is). This line in routes.go

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

was causing the unintended routing. When PathPrefix is used, it seems to route all URLs to the first matching prefix (in this case this prefix). This explains why static files were being served, but nothing else works.

The fix is to use the Path function instead. There's a subtle difference as explained in the docs; PathPrefix "matches if the given template is a prefix of the full URL path", whereas Path does not. Hence the line above now looks like this to solve the issue I was having:

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

huangapple
  • 本文由 发表于 2015年2月18日 10:17:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/28574875.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定