HttpRouter
Repository-Adresse: julienschmidt/httprouter: A high performance HTTP request router that scales well (github.com)
Die Routing-Komponente von Gin verwendet HttpRouter, was ebenfalls eine leichtgewichtige, hochleistungsfähige Routing-Komponente ist. Die gesamte Komponente besteht nur aus drei .go-Dateien, der Code ist sehr übersichtlich. Sie hat folgende Hauptmerkmale:
Eins-zu-eins-Zuordnung: Eine Anfrage kann null oder einer Route zugeordnet werden, was vorteilhaft für die SEO-Optimierung ist.
Automatische Pfadkorrektur: Wählen Sie Ihren bevorzugten URL-Stil. Selbst wenn ein Schrägstrich zu viel oder zu wenig ist, wird automatisch umgeleitet. Bei Groß-/Kleinschreibungsfehlern wird bei der Suche die Groß-/Kleinschreibung ignoriert und korrekt umgeleitet.
Automatische Parsing von Routenparametern: Geben Sie einfach einem Pfadsegment einen Namen, und der Router übergibt Ihnen die dynamischen Werte. Aufgrund des Router-Designs ist der Aufwand für das Parsing von Pfadparametern sehr gering.
Zero Garbage: Während des Routing- und Dispatching-Prozesses wird kein Speichermüll erzeugt.
RESTful-API-Unterstützung: Das Router-Design fördert eine vernünftige, geschichtete RESTful-API.
Fehlerbehandlung: Sie können einen Fehlerhandler einrichten, um Ausnahmen in Anfragen zu behandeln. Der Router fängt sie ab, protokolliert sie und leitet dann zur Fehlerseite um.
Grundlegende Verwendung
Wie bei springboot wird eine Funktion an eine URL gebunden und entspricht einem Handler.
package main
import (
"fmt"
"github.com/julienschmidt/httprouter"
"log"
"net/http"
)
func Hello(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprintf(w, "<h1>Hello World!")
}
func main() {
router := httprouter.New()
router.GET("/hello", Hello)
log.Fatal(http.ListenAndServe(":8080", router))
}Geben Sie dann in einem Browser oder einem beliebigen API-Testtool 127.0.0.1:8080 ein, um den korrekten Inhalt zu sehen. Wir können feststellen, dass HttpRouter nur das Routing übernimmt. Tatsächlich wird weiterhin die Standardkomponente net/http verwendet, ebenso bei gin, nur ist die Kapselung etwas tiefer.
Benannte Parameter
package main
import (
"fmt"
"github.com/julienschmidt/httprouter"
"log"
"net/http"
)
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "<h1>Hello World!")
}
func main() {
router := httprouter.New()
router.GET("/hello:name", Hello)
log.Fatal(http.ListenAndServe(":8080", router))
}Dieses Mal wurde am Ende der Route :name hinzugefügt. name ist ein benannter Parameter, auf den über httprouter.Params zugegriffen werden kann, um die Parameter-Slice zu erhalten. Sie können Parameter über den Index oder ByName(name) abrufen. Ebenso können Sie http.handler und http.handlerFunc als httprouter.handler verwenden, da der Router selbst deren Schnittstelle implementiert, wie im folgenden Beispiel.
func Hello(w http.ResponseWriter, r *http.Request) {
params := httprouter.ParamsFromContext(r.Context())
//params := r.Context().Value(httprouter.ParamsKey) geht auch
fmt.Fprintf(w, "hello, %s!\n", params.ByName("name"))
}Wenn die an die Methode gebundene Route /user/:user ist, sehen die Übereinstimmungen für folgende URLs so aus:
/user/gordon Übereinstimmung
/user/you Übereinstimmung
/user/gordon/profile keine Übereinstimmung
/user/ keine ÜbereinstimmungSie können /user/new und /user/:user nicht für dieselbe Anfragemethode registrieren. Jede Anfragemethode sollte unabhängig sein.
Alle Parameter erfassen
Der zweite Typ ist das Erfassen aller Parameter. Wie der Name schon sagt, stimmen sie mit allem überein und müssen daher am Ende des Pattern stehen.
Pattern: /src/*filepath
/src/ Übereinstimmung
/src/somefile.go Übereinstimmung
/src/subdir/somefile.go ÜbereinstimmungDie Funktionsweise von HttpRouter basiert auf dem Aufbau zahlreicher Präfixbäume. Interessierte können mehr erfahren unter: httprouter package - github.com/julienschmidt/httprouter - Go Packages.
OPTIONS & CORS
Manche möchten möglicherweise die automatische Antwort auf OPTIONS ändern und einige Response-Header setzen, um CORS-Preflight-Anfragen zu unterstützen. Diese Anforderungen können durch die Verwendung des Router.GlobalOPTIONS-Handlers erfüllt werden.
router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Access-Control-Request-Method") != "" {
// CORS-Response-Header setzen
header := w.Header()
header.Set("Access-Control-Allow-Methods", r.Header.Get("Allow"))
header.Set("Access-Control-Allow-Origin", "*")
}
// Statuscode 204 anpassen
w.WriteHeader(http.StatusNoContent)
})NOT FOUND Handler
TIP
Möglicherweise müssen Sie Router.HandleMethodNotAllowed deaktivieren, um einige Probleme zu vermeiden.
router.NotFound = http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
// Ihre Logik
})Basis-Authentifizierung
package main
import (
"fmt"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// Basis-Authentifizierungsdaten abrufen
user, password, hasAuth := r.BasicAuth()
if hasAuth && user == requiredUser && password == requiredPassword {
// Anfrage an den angegebenen Handler weiterleiten
h(w, r, ps)
} else {
// Andernfalls Authentifizierung anfordern
w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
}
}
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprint(w, "Not protected!\n")
}
func Protected(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprint(w, "Protected!\n")
}
func main() {
user := "gordon"
pass := "secret!"
router := httprouter.New()
router.GET("/", Index)
router.GET("/protected/", BasicAuth(Protected, user, pass))
log.Fatal(http.ListenAndServe(":8080", router))
}