Routage

Le rôle du routage dans le cadre du framework Go Fiber est de lier des URL différentes à des fonctions de traitement, afin de prendre en charge le traitement des demandes HTTP. Il sert de point d'entrée pour toutes les demandes du framework web.

Gestionnaires de route (Fonctions)

Enregistrer des routes liées à des méthodes HTTP spécifiques.

Remarque : Dans certains frameworks, les gestionnaires de route sont appelés contrôleurs, ce qui a généralement la même signification : déterminer quelle fonction (méthode) traitera la demande HTTP entrante.

Signature de la fonction :

// Méthodes HTTP
func (app *App) Get(path string, handlers ...Handler) Router
func (app *App) Head(path string, handlers ...Handler) Router
func (app *App) Post(path string, handlers ...Handler) Router
func (app *App) Put(path string, handlers ...Handler) Router
func (app *App) Delete(path string, handlers ...Handler) Router
func (app *App) Connect(path string, handlers ...Handler) Router
func (app *App) Options(path string, handlers ...Handler) Router
func (app *App) Trace(path string, handlers ...Handler) Router
func (app *App) Patch(path string, handlers ...Handler) Router

// Add vous permet de spécifier des méthodes en tant que valeurs
func (app *App) Add(method, path string, handlers ...Handler) Router

// All enregistre la route sur toutes les méthodes HTTP
// Similaire à app.Use mais ne lie pas de préfixe
func (app *App) All(path string, handlers ...Handler) Router

Exemple :

// Gestionnaire GET simple
app.Get("/api/list", func(c *fiber.Ctx) error {
  return c.SendString("Ceci est une requête GET !")
})

// Gestionnaire POST simple
app.Post("/api/register", func(c *fiber.Ctx) error {
  return c.SendString("Ceci est une requête POST !")
})

Use est utilisé pour charger des intergiciels (middlewares) et intercepteurs d'URL de préfixe. Ces routes correspondent uniquement au début de chaque chemin, par exemple, /john correspondra à /john/doe, /johnnnnn, et ainsi de suite.

Signature de la fonction middleware personnalisée :

func (app *App) Use(args ...interface{}) Router

Exemple :

// Correspond à n'importe quelle demande
app.Use(func(c *fiber.Ctx) error {
    return c.Next()
})

// Correspond aux demandes commençant par /api
app.Use("/api", func(c *fiber.Ctx) error {
    return c.Next()
})

// Correspond aux demandes commençant par /api ou /home (prend en charge plusieurs préfixes)
app.Use([]string{"/api", "/home"}, func(c *fiber.Ctx) error {
    return c.Next()
})

// Ajouter plusieurs gestionnaires
app.Use("/api", func(c *fiber.Ctx) error {
  c.Set("X-Custom-Header", random.String(32))
  return c.Next()
}, func(c *fiber.Ctx) error {
  return c.Next()
})

Chemin

Le chemin de la route, combiné à la méthode de demande, définit les points de terminaison auxquels il est possible d'accéder. Le chemin de la route peut être une chaîne de caractères ou un motif de chaîne.

Exemples de chemins de route basés sur des chaînes de caractères

// Ce chemin de route correspondra aux demandes vers le chemin racine, "/":
app.Get("/", func(c *fiber.Ctx) error {
  return c.SendString("Chemin racine")
})

// Ce chemin de route correspondra aux demandes vers "/about":
app.Get("/about", func(c *fiber.Ctx) error {
  return c.SendString("À propos")
})

// Ce chemin de route correspondra aux demandes vers "/random.txt":
app.Get("/random.txt", func(c *fiber.Ctx) error {
  return c.SendString("Random.txt")

De manière similaire au framework expressJs, l'ordre dans lequel les routes sont déclarées est important. Lorsqu'une demande est reçue, les routes sont vérifiées dans l'ordre où elles sont déclarées.

Veuillez noter : Assurez-vous que les routes avec des paramètres variables sont écrites après les routes contenant des parties fixes pour éviter que ces parties variables ne soient associées par erreur, ce qui pourrait entraîner un comportement inattendu.

Paramètres de route

Les paramètres de route sont des éléments dynamiques dans une route et peuvent être soit des segments nommés ou non nommés. Ces segments sont utilisés pour capturer des valeurs à des positions spécifiées dans l'URL. Vous pouvez utiliser la fonction Params pour récupérer ces valeurs, où le paramètre de la fonction est le nom du paramètre de route dans le chemin, ou pour les paramètres non nommés, ce sont les caractères (*, +) et leur nombre.

Le caractère générique (*) ou le signe plus (+) représentent des paramètres gourmands.

Les routes offrent également la possibilité d'utiliser des paramètres optionnels. Pour les paramètres nommés, ces paramètres sont suivis d'un point d'interrogation (?), alors que le signe plus n'est pas facultatif, et vous pouvez utiliser des caractères génériques pour représenter une plage de paramètres facultatifs et gourmands.

Exemple de définition d'une route avec des paramètres de route

// Paramètres
app.Get("/user/:name/books/:title", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s\n", c.Params("name"))
    fmt.Fprintf(c, "%s\n", c.Params("title"))
    return nil
})
// Plus - gourmand - non facultatif
app.Get("/user/+", func(c *fiber.Ctx) error {
    return c.SendString(c.Params("+"))
})

// Paramètre facultatif
app.Get("/user/:name?", func(c *fiber.Ctx) error {
    return c.SendString(c.Params("name"))
})

// Caractère générique - gourmand - facultatif
app.Get("/user/*", func(c *fiber.Ctx) error {
    return c.SendString(c.Params("*"))
})

// Ce chemin de route correspondra à la requête "/v1/some/resource/name:customVerb" car les caractères du paramètre ont été échappés
app.Get(`/v1/some/resource/name\:customVerb`, func(c *fiber.Ctx) error {
    return c.SendString("Bonjour, la communauté")
})

Comme les tirets (-) et les points (.) sont interprétés littéralement, ils peuvent être utilisés avec les paramètres de route pour atteindre des objectifs utiles.

Tous les caractères spéciaux des paramètres peuvent également être échappés en utilisant \ et leurs valeurs seront ignorées, donc si vous souhaitez les utiliser dans la route. Il est recommandé d'utiliser les backticks ``, car dans la documentation des expressions régulières Go, ils sont toujours utilisés pour s'assurer qu'il n'y a pas d'ambiguïté, et que les caractères d'échappement n'affectent pas inadvertamment le motif de l'expression régulière.

// http://localhost:3000/plantae/prunus.persica
app.Get("/plantae/:genus.:species", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s.%s\n", c.Params("genus"), c.Params("species"))
    return nil // prunus.persica
})
// http://localhost:3000/flights/LAX-SFO
app.Get("/flights/:from-:to", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s-%s\n", c.Params("from"), c.Params("to"))
    return nil // LAX-SFO
})

Notre routage intelligent reconnaît que les caractères de paramètre introduits dans ce cas doivent faire partie de la route de la requête et peut les gérer en conséquence.

// http://localhost:3000/shop/product/color:blue/size:xs
app.Get("/shop/product/color::color/size::size", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s:%s\n", c.Params("color"), c.Params("size"))
    return nil // bleu:xs

De plus, les routes peuvent utiliser plusieurs paramètres et plusieurs caractères de paramètres non nommés consécutivement, tels que des caractères génériques ou des signes plus, ce qui élargit considérablement les possibilités pour les utilisateurs dans les routes.

// GET /@v1
// Params: "sign" -> "@", "param" -> "v1"
app.Get("/:sign:param", handler)

// GET /api-v1
// Params: "name" -> "v1" 
app.Get("/api-:name", handler)

// GET /customer/v1/cart/proxy
// Params: "*1" -> "customer/", "*2" -> "/cart"
app.Get("/*v1*/proxy", handler)

// GET /v1/brand/4/shop/blue/xs
// Params: "*1" -> "brand/4", "*2" -> "blue/xs"
app.Get("/v1/*/shop/*", handler)

Contraintes

Lorsqu'il y a une correspondance avec l'URL entrante et que le chemin de l'URL est divisé en valeurs de route à travers des paramètres, les contraintes seront exécutées. Cette fonctionnalité a été introduite dans v2.37.0 et a été inspirée par .NET Core.

Les contraintes ne sont pas destinées à la validation des paramètres. Si la contrainte est invalide pour la valeur du paramètre, Fiber renverra un gestionnaire 404.

Contrainte Exemple Correspondances possibles
int :id 123456789, -123456789
bool :active true, false
guid :id CD2C1638-1638-72D5-1638-DEADBEEF1638
float :weight 1,234, -1,001,01e8
minLen(value) :username<minLen(4)> test (au moins 4 caractères)
maxLen(value) :filename<maxLen(8)> MyFile (jusqu'à 8 caractères)
len(length) :filename<len(12)> somefile.txt (12 caractères)
min(value) :age<min(18)> 19 (la valeur entière doit être au moins 18)
max(value) :age<max(120)> 91 (la valeur entière ne peut pas dépasser 120)
range(min,max) :age<range(18,120)> 91 (la valeur entière doit être au moins 18 mais ne peut pas dépasser 120)
alpha :name Rick (la chaîne doit se composer d'un ou plusieurs caractères alphabétiques, insensible à la casse, a-z)
datetime :dob<datetime(2006\\-01\\-02)> 2005-11-01
regex(expression) :date<regex(\d{4}-\d{2}-\d{2})> 2022-08-27 (doit correspondre à l'expression régulière)

Exemples

  • Contrainte unique
  • Contraintes multiples
  • Contrainte d'expression régulière
app.Get("/:test", func(c *fiber.Ctx) error {
  return c.SendString(c.Params("test"))
})

// curl -X GET http://localhost:3000/12 // 12

// curl -X GET http://localhost:3000/1 // Impossible de trouver GET /1


Vous pouvez utiliser `;` pour ajouter plusieurs contraintes.

app.Get("/:test", func(c *fiber.Ctx) error { return c.SendString(c.Params("test")) })

// curl -X GET http://localhost:3000/120000 // Impossible de trouver GET /120000

// curl -X GET http://localhost:3000/1 // Impossible de trouver GET /1

// curl -X GET http://localhost:3000/250 // 250


Fiber précompile les requêtes d'expressions régulières lors de l'enregistrement des routes, il n'y a donc pas de surcharge de performance pour les contraintes d'expression régulière.

```go
app.Get(`/:date`, func(c *fiber.Ctx) error {
  return c.SendString(c.Params("date"))
})

// curl -X GET http://localhost:3000/125 // Impossible de trouver GET /125

// curl -X GET http://localhost:3000/test // Impossible de trouver GET /test

// curl -X GET http://localhost:3000/2022-08-27 // 2022-08-27


> Lors de l'utilisation de contraintes de date-heure (`*`,`+`,`?`,`:`,`/`,``,``,`>`,';`,`(`,`)`), utilisez `\\` avant d'utiliser des caractères spéciaux dans la route pour éviter toute mauvaise interprétation.

**Exemple de paramètre facultatif**

Vous pouvez également ajouter des contraintes aux paramètres facultatifs.
```go
app.Get("/:test?", func(c *fiber.Ctx) error {
  return c.SendString(c.Params("test"))
})
// curl -X GET http://localhost:3000/42
// 42
// curl -X GET http://localhost:3000/
//
// curl -X GET http://localhost:3000/7.0
// Impossible de trouver GET /7.0

Middleware

Les fonctions conçues pour manipuler les requêtes ou les réponses sont appelées fonctions middleware. Next est une fonction de routage Fiber qui, lorsqu'elle est appelée, exécute la fonction next correspondant à l'itinéraire actuel.

Exemple de fonction middleware

app.Use(func(c *fiber.Ctx) error {
  // Définir un en-tête personnalisé dans toutes les réponses :
  c.Set("X-Custom-Header", "Bonjour tout le monde")

  // Passer au middleware suivant :
  return c.Next()
})

app.Get("/", func(c *fiber.Ctx) error {
  return c.SendString("Bonjour tout le monde !")
})

Le chemin pour la méthode Use peut être un chemin de montage ou un préfixe, et il restreint l'application du middleware aux requêtes dont les chemins commencent par ce chemin.

Ajout de limitations de route à l'exécution

En raison de considérations de conception et de performance, l'ajout dynamique de routes après le démarrage de l'application n'est pas pris en charge. Veuillez vous assurer que toutes les routes sont définies avant le démarrage de l'application.

Regroupement

Si vous avez de nombreuses endpoints, vous pouvez utiliser Group pour organiser les routes.

func main() {
  app := fiber.New()

  api := app.Group("/api", middleware) // /api

  v1 := api.Group("/v1", middleware)   // /api/v1
  v1.Get("/list", handler)             // /api/v1/list
  v1.Get("/user", handler)             // /api/v1/user

  v2 := api.Group("/v2", middleware)   // /api/v2
  v2.Get("/list", handler)             // /api/v2/list
  v2.Get("/user", handler)             // /api/v2/user

  log.Fatal(app.Listen(":3000"))
}