大猩猩Mux – 路由不如预期那样工作

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

Gorilla Mux - not routing as expected

问题

帮助将不胜感激,显然我错过了一些非常简单的东西。

我创建了一个应该很简单的测试装置,将调用路由到不同的处理程序的不同方法。

但是,简单的获取处理程序获取了所有的获取请求,而删除和放置请求则无法识别!

所以,localhost:8080/users 和 localhost:8080/users?id=1 都被路由到了getUsers路由。这个问题的答案肯定很简单,但我看不到,所以希望你能帮助我。

以下是测试装置的完整列表:

package main

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

type User struct {
	Id   string `json:"id"`
	Name string `json:"name"`
}

type Users []User

var users = Users{
	User{
		Id:   "1",
		Name: "Tula",
	},
	User{
		Id:   "2",
		Name: "Monty",
	},
	User{
		"3",
		"Merry",
	},
	User{
		Id:   "4",
		Name: "Paddy",
	},
	User{
		Id:   "5",
		Name: "Hendrix",
	},
	User{
		Id:   "6",
		Name: "Purdy",
	},
	User{
		Id:   "7",
		Name: "turnip",
	},
}

func main() {
	r := mux.NewRouter()

	r.Path("/users/{id:[0-9]+}").
		Queries("id", "{id:[0-9]*?}").
		Methods(http.MethodGet).
		HandlerFunc(getUser).
		Name("getUser")

	r.Path("/users").
		Methods(http.MethodGet).
		HandlerFunc(getUsers).
		Name("getUsers")

	r.Path("/users").
		Methods(http.MethodPost).
		HandlerFunc(CreateUser).
		Name("CreateUser")

	r.Path("/users/{id:[0-9]+}").
		Queries("id", "{id:[0-9]*?}").
		Methods(http.MethodPut).
		HandlerFunc(updateUser).
		Name("updateUser")

	r.Path("/users/{id:[0-9]+}").
		Queries("id", "{id:[0-9]*?}").
		Methods(http.MethodDelete).
		HandlerFunc(deleteUser).
		Name("deleteUser")

	log.Fatal(http.ListenAndServe(":8080", r))
}

func getUsers(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)

	err := json.NewEncoder(w).Encode(users)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	} else {
		_, _ = fmt.Fprintf(w, "GetUsers!")
	}
}

func getUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	_, _ = fmt.Fprintf(w, "GetUser!")
}

func CreateUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	_, _ = fmt.Fprintf(w, "CreateUser!")

	var newUser User
	err := json.NewDecoder(r.Body).Decode(&newUser)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	} else {
		users = append(users, newUser)
		_ = json.NewEncoder(w).Encode(users)
	}
}

func updateUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	_, _ = fmt.Fprintf(w, "Update!")
}

func deleteUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	_, _ = fmt.Fprintf(w, "Delete!")
}

希望这可以帮助你找到问题所在。

英文:

Help would be appreciated, clearly i am missing something very simple.

I have created what should be a simple test rig to route calls to different methods to different handlers.

In stead the simple get handler is getting all get requests and delete and put are not recognised!

so both localhost:8080/users
and

localhost:8080/users?id=1

get. routed to the getUsers route. The answer to this must be trivial but i cant see it and hence you help would be appreciated.

Below is a complete listing of the test rig

package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"log"
"net/http"
)
type User struct {
Id   string `json:"id"`
Name string `json:"name"`
}
type Users []User
var users = Users{
User{
Id:   "1",
Name: "Tula",
},
User{
Id:   "2",
Name: "Monty",
},
User{
"3",
"Merry",
},
User{
Id:   "4",
Name: "Paddy",
},
User{
Id:   "5",
Name: "Hendrix",
},
User{
Id:   "6",
Name: "Purdy",
},
User{
Id:   "7",
Name: "turnip",
},
}
func main() {
r := mux.NewRouter()
r.Path("/users/{id:[0-9]+}").
Queries("id", "{id:[0-9]*?}").
Methods(http.MethodGet).
HandlerFunc(getUser).
Name("getUser")
r.Path("/users").
Methods(http.MethodGet).
HandlerFunc(getUsers).
Name("getUsers")
r.Path("/users").
Methods(http.MethodPost).
HandlerFunc(CreateUser).
Name("CreateUser")
r.Path("/users/{id:[0-9]+}").
Queries("id", "{id:[0-9]*?}").
Methods(http.MethodPut).
HandlerFunc(updateUser).
Name("updateUser")
r.Path("/users/{id:[0-9]+}").
Queries("id", "{id:[0-9]*?}").
Methods(http.MethodDelete).
HandlerFunc(deleteUser).
Name("deleteUser")
log.Fatal(http.ListenAndServe(":8080", r))
}
func getUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(users)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
} else {
_, _ = fmt.Fprintf(w, "GetUsers!")
}
}
func getUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprintf(w, "GetUser!")
}
func CreateUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprintf(w, "CreateUser!")
var newUser User
err := json.NewDecoder(r.Body).Decode(&newUser)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
} else {
users = append(users, newUser)
_ = json.NewEncoder(w).Encode(users)
}
}
func updateUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprintf(w, "Update!")
}
func deleteUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprintf(w, "Delete!")
}

答案1

得分: 2

当你获取url localhost:8080/users?id=1时,路径是/users。唯一映射到GET /users的路径是:

	r.Path("/users").
		Methods(http.MethodGet).
		HandlerFunc(getUsers).
		Name("getUsers")

这就是为什么请求映射到getUsers方法。getUser的配置实际上没有任何意义。你有:

	r.Path("/users/{id:[0-9]+}").
		Queries("id", "{id:[0-9]*?}").
		Methods(http.MethodGet).
		HandlerFunc(getUser).
		Name("getUser")

这将需要一个类似于http://localhost:8080/users/1?id=1的请求(然后忽略路径中的id)。我会修改配置,使其如下所示:

	r.Path("/users/{id:[0-9]+}").
		Methods(http.MethodGet).
		HandlerFunc(getUser).
		Name("getUser")

然后你的请求将变成http://localhost:8080/users/1http://localhost:8080/users/2等等。

英文:

When you fetch the url localhost:8080/users?id=1, the path is /users. The only path that maps to GET /users is:

	r.Path("/users").
Methods(http.MethodGet).
HandlerFunc(getUsers).
Name("getUsers")

That's why the request maps to the getUsers method. The configuration for getUser doesn't actually make any sense. You have:

	r.Path("/users/{id:[0-9]+}").
Queries("id", "{id:[0-9]*?}").
Methods(http.MethodGet).
HandlerFunc(getUser).
Name("getUser")

Which would require a request like to something like http://localhost:8080/users/1?id=1 (and then it ignores the id in the path). I would modify the configuration to look like this:

	r.Path("/users/{id:[0-9]+}").
Methods(http.MethodGet).
HandlerFunc(getUser).
Name("getUser")

And then your requests would look like http://localhost:8080/users/1, http://localhost:8080/users/2, etc.

答案2

得分: 0

简单来说,只需要将代码中的路径部分从/users/{id:[0-9]+}改为/users,同时将处理函数getUser改为GetUser即可。

英文:

Simple in the end only

r.Path("/users/{id:[0-9]+}").
Queries("id", "{id:[0-9]*?}").
Methods(http.MethodGet).
HandlerFunc(getUser).
Name("updateUser")

Became

r.Path("/users").
Queries("id", "{id:[0-9]*?}").
Methods(http.MethodGet).
HandlerFunc(GetUser).
Name("updateUser")

huangapple
  • 本文由 发表于 2022年1月11日 19:36:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/70666118.html
匿名

发表评论

匿名网友

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

确定