Gibt es bei der Registrierung von Handlern in Go (Sprache) eine Möglichkeit, Platzhalter im Muster anzugeben?
Zum Beispiel:
http.HandleFunc("/groups/*/people", peopleInGroupHandler)
Wo *
könnte eine gültige URL-Zeichenfolge sein. Oder ist die einzige Lösung, um /groups
den Rest aus der Handler ( peopleInGroupHandler
) -Funktion heraus abzugleichen und herauszufinden ?
Antworten:
Die Muster für http.Handler und http.HandleFunc sind keine regulären Ausdrücke oder Globs. Es gibt keine Möglichkeit, Platzhalter anzugeben. Sie sind hier dokumentiert .
Es ist jedoch nicht allzu schwierig, einen eigenen Handler zu erstellen, der reguläre Ausdrücke oder andere gewünschte Muster verwenden kann. Hier ist eine, die reguläre Ausdrücke verwendet (kompiliert, aber nicht getestet):
type route struct { pattern *regexp.Regexp handler http.Handler } type RegexpHandler struct { routes []*route } func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) { h.routes = append(h.routes, &route{pattern, handler}) } func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) { h.routes = append(h.routes, &route{pattern, http.HandlerFunc(handler)}) } func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { for _, route := range h.routes { if route.pattern.MatchString(r.URL.Path) { route.handler.ServeHTTP(w, r) return } } // no pattern matched; send 404 response http.NotFound(w, r) }
quelle
*
-ähnlichenthe pattern "/" matches all paths not matched by other registered patterns
(h *RegexpHandler) Handler
sollte es sein(h *RegexpHandler) Handle
? Siehe hier: golang.org/pkg/net/http/#ServeMux.Handle :)net/http
. Können Sie ein vollständiges Beispiel geben? Danke.Seit 2011 können Sie jetzt (2014+) andere Lösungen finden.
Zum Beispiel bietet das Mux-Paket des Gorilla Web Toolkits alle Arten von Routing-Optionen:
Es kann problemlos in jede BYOR-HTTP-Bibliothek (Bring your own Router) wie negroni integriert werden .
Hier ist ein Beispiel aus dem Artikel " Gorilla vs Pat vs Routes: Ein Mux Showdown ":
package main import ( "github.com/gorilla/mux" "log" "net/http" ) func main() { rtr := mux.NewRouter() rtr.HandleFunc("/user/{name:[a-z]+}/profile", profile).Methods("GET") http.Handle("/", rtr) log.Println("Listening...") http.ListenAndServe(":3000", nil) } func profile(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) name := params["name"] w.Write([]byte("Hello " + name)) }
In diesem Fall wird die "Magie" in "
gorilla/mux/regexp.go
" definiert und hier getestet .Die Idee ist, benannte Variablen zu extrahieren, einen zu passenden regulären Ausdruck zusammenzustellen, eine "umgekehrte" Vorlage zum Erstellen von URLs zu erstellen und reguläre Ausdrücke zu kompilieren, um die beim Erstellen von URLs verwendeten Variablenwerte zu validieren.
quelle
Ich wollte nur hinzufügen
julienschmidt/httprouter
, was sich einfach so verhält,net/http
aber mit einem zusätzlichen Parameter für URL-Werte und Unterstützung für Anforderungsmethoden:https://github.com/julienschmidt/httprouter
package main import ( "fmt" "github.com/julienschmidt/httprouter" "net/http" "log" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Welcome!\n") } func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) } func main() { router := httprouter.New() router.GET("/", Index) router.GET("/hello/:name", Hello) log.Fatal(http.ListenAndServe(":8080", router)) }
Es scheint auch etwas beliebter zu sein als
gorilla/mux
(laut GitHub) und es behauptet auch, weniger Speicher zu benötigen.https://github.com/julienschmidt/go-http-routing-benchmark
quelle
Hier ist ein Beispiel für die Verwendung des Codebeispiels von @evanshaw
func handleDigits(res http.ResponseWriter, req *http.Request) { res.Write([]byte("Digits in the URL\n")) } func handleStrings(res http.ResponseWriter, req *http.Request) { res.Write([]byte("Strings in the URL\n")) } func main() { handler := &RegexpHandler{} reg1, _ := regexp.Compile("/foo-\\d+") handler.HandleFunc(reg1, handleDigits) reg2, _ := regexp.Compile("/foo-\\w+") handler.HandleFunc(reg2, handleStrings) http.ListenAndServe(":3000", handler) }
quelle
Sie können überprüfen, wie Violetear mit dynamischen + Catchall-Mustern (Platzhaltermustern) umgeht. Dies ist nur eine Ergänzung zum Beispiel:
uuid := `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}` router.AddRegex(":uuid") router.HandleFunc("/test/:uuid/:uuid", handleUUID, "GET,HEAD")
In diesem Fall kann die Anforderung 2 verschiedene haben
UUIDS
Für eine Dynamik / einen Platzhalter könnte dies gelten:
http://api.violetear.org/command/ping/127.0.0.1 \______/\___/\________/ | | | static | dynamic
Ein regulärer Ausdruck kann verwendet werden, um der IP zu entsprechen:
router.AddRegex(":ip", `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`) router.HandleFunc("/command/ping/:ip", ipHandler, "GET")
Oder einfach nur ein Fang aller erlaubten
GET
undHEAD
nur Methoden:router.HandleFunc("/command/ping/*", anyHandler, "GET, HEAD")
Weitere Beispiele finden Sie hier: https://violetear.org/post/how-it-works/
quelle
Beego, die Antwort auf alle Fragen zum Golang-Webserver. Wetalk ist eine Blog-Site, die auf Beego basiert.
quelle