Skip to content

HttpRouter

Adresse du dépôt : julienschmidt/httprouter: A high performance HTTP request router that scales well (github.com)

Le composant de routage de Gin utilise HttpRouter, qui est également un composant de routage léger et haute performance. L'ensemble du composant ne contient que trois fichiers .go, le code est très concis, avec les caractéristiques principales suivantes.

Correspondance un-à-un : Une requête ne peut correspondre qu'à zéro ou une seule route, ce qui est favorable au référencement SEO.

Correction automatique du chemin : Choisissez le style d'URL que vous préférez, même s'il y a une barre oblique en plus ou en moins, une redirection automatique sera effectuée. S'il y a une erreur de casse, la recherche ignorera également la casse pour effectuer une redirection correcte.

Analyse automatique des paramètres de route : Donnez simplement un nom au segment de chemin, le routeur vous transmettra les valeurs dynamiques. Grâce à la conception du routeur, l'analyse des paramètres de chemin a un coût très faible.

Zéro déchet : Aucune mémoire n'est gaspillée pendant le processus d'allocation et de dispatching des routes.

Support RestfulAPI : La conception du routeur encourage une architecture Restful API raisonnable et hiérarchisée.

Gestion des erreurs : Vous pouvez définir un gestionnaire d'erreurs pour traiter les exceptions dans les requêtes, le routeur les capturera et les enregistrera, puis redirigera vers une page d'erreur.

Utilisation de base

Comme avec springboot, une fonction est liée à une URL et correspond à un gestionnaire.

go
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))
}

Ensuite, avec un navigateur ou tout outil de test d'API, entrez 127.0.0.1:8080, et vous verrez le contenu correct. Nous pouvons voir que HttpRouter fait uniquement le routage, en réalité il utilise toujours les composants par défaut de net/http, gin fait de même, mais avec une encapsulation un peu plus profonde.

Paramètres nommés

go
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))
}

Cette fois, la route a :name ajouté à la fin, name est un paramètre nommé, accessible via le slice de paramètres httprouter.Params, par index ou via ByName(name). De même, vous pouvez utiliser http.handler et http.handlerFunc comme httprouter.handler, le routeur lui-même implémente son interface, comme dans l'exemple ci-dessous.

go
func Hello(w http.ResponseWriter, r *http.Request) {
    params := httprouter.ParamsFromContext(r.Context())
    //params := r.Context().Value(httprouter.ParamsKey) fonctionne aussi

    fmt.Fprintf(w, "hello, %s!\n", params.ByName("name"))
}

Lorsque la route liée à la méthode est /user/:user, les correspondances pour les URLs suivantes sont :

 /user/gordon              correspond
 /user/you                 correspond
 /user/gordon/profile      ne correspond pas
 /user/                    ne correspond pas

Vous ne pouvez pas enregistrer /user/new et /user/:user pour la même méthode HTTP, chaque méthode HTTP doit être indépendante.

Capture de tous les paramètres

Le deuxième type est la capture de tous les paramètres, comme son nom l'indique, ils correspondent à tout, et doivent donc être à la fin du Pattern.

go
Pattern: /src/*filepath

 /src/                     correspond
 /src/somefile.go          correspond
 /src/subdir/somefile.go   correspond

Le principe de fonctionnement de HttpRouter est de construire un grand nombre d'arbres préfixes, si vous êtes intéressé, vous pouvez en savoir plus : httprouter package - github.com/julienschmidt/httprouter - Go Packages.

OPTIONS & CORS

Certaines personnes peuvent souhaiter modifier la réponse automatique pour OPTIONS et définir certains en-têtes de réponse pour s'adapter aux requêtes de pré-vérification CORS, ces besoins peuvent être réalisés en utilisant le handler Router.GlobalOPTIONS.

go
router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    if r.Header.Get("Access-Control-Request-Method") != "" {
        // Définir les en-têtes CORS
        header := w.Header()
        header.Set("Access-Control-Allow-Methods", r.Header.Get("Allow"))
        header.Set("Access-Control-Allow-Origin", "*")
    }

    // Adapter le code de statut 204
    w.WriteHeader(http.StatusNoContent)
})

Gestionnaire NOT FOUND

TIP

Il peut être nécessaire de désactiver Router.HandleMethodNotAllowed pour éviter certains problèmes.

go
router.NotFound = http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
  // Votre logique
})

Authentification basique

go
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) {
    // Obtenir les identifiants d'authentification basique
    user, password, hasAuth := r.BasicAuth()

    if hasAuth && user == requiredUser && password == requiredPassword {
      // Déléguer la requête au gestionnaire donné
      h(w, r, ps)
    } else {
      // Sinon demander l'authentification
      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))
}

Golang by www.golangdev.cn edit