Instradamento

Il ruolo del percorso (route) nel framework Go Fiber è quello di associare diversi URL a funzioni di gestione, al fine di supportare l'elaborazione delle richieste HTTP. Serve come punto di ingresso per tutte le richieste del framework web.

Gestori dei percorsi (Funzioni)

Registra i percorsi associati a metodi HTTP specifici.

Nota: In alcuni framework, i gestori dei percorsi sono chiamati controller, che generalmente hanno lo stesso significato: determinare quale funzione (metodo) gestire la richiesta HTTP in ingresso.

Firma della funzione:

// Metodi 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 ti permette di specificare i metodi come valori
func (app *App) Add(method, path string, handlers ...Handler) Router

// Registra il percorso su tutti i metodi HTTP
// Simile a app.Use ma non associa un prefisso
func (app *App) All(path string, handlers ...Handler) Router

Esempio:

// Semplice gestore GET
app.Get("/api/list", func(c *fiber.Ctx) error {
  return c.SendString("Questa è una richiesta GET!")
})

// Semplice gestore POST
app.Post("/api/register", func(c *fiber.Ctx) error {
  return c.SendString("Questa è una richiesta POST!")
})

Use viene utilizzato per caricare middleware e intercettori di URL del prefisso. Questi percorsi corrispondono solo all'inizio di ciascun percorso, ad esempio, /john corrisponderà a /john/doe, /johnnnnn, e così via.

Firma della funzione middleware personalizzata:

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

Esempio:

// Corrispondi a qualsiasi richiesta
app.Use(func(c *fiber.Ctx) error {
    return c.Next()
})

// Corrispondi alle richieste che iniziano con /api
app.Use("/api", func(c *fiber.Ctx) error {
    return c.Next()
})

// Corrispondi alle richieste che iniziano con /api o /home (supporta più prefissi)
app.Use([]string{"/api", "/home"}, func(c *fiber.Ctx) error {
    return c.Next()
})

// Aggiungi più gestori
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()
})

Percorso

Il percorso del percorso, insieme al metodo della richiesta, definisce i endpoint a cui è possibile accedere. Il percorso del percorso può essere una stringa o un modello di stringa.

Esempi di percorsi basati su stringhe

// Questo percorso del percorso corrisponderà alle richieste al percorso radice, "/":
app.Get("/", func(c *fiber.Ctx) error {
  return c.SendString("Percorso radice")
})

// Questo percorso del percorso corrisponderà alle richieste a "/about":
app.Get("/about", func(c *fiber.Ctx) error {
  return c.SendString("Informazioni")
})

// Questo percorso del percorso corrisponderà alle richieste a "/random.txt":
app.Get("/random.txt", func(c *fiber.Ctx) error {
  return c.SendString("Random.txt")

Come nel framework expressJs, l'ordine in cui vengono dichiarati i percorsi è importante. Quando viene ricevuta una richiesta, i percorsi vengono controllati nell'ordine in cui sono dichiarati.

Si prega di notare: Assicurarsi che i percorsi con parametri variabili siano scritti dopo i percorsi contenenti parti fisse per evitare che queste parti variabili vengano corrisposte erroneamente, il che potrebbe portare a un comportamento inaspettato.

Parametri di percorso

I parametri di percorso sono elementi dinamici in un percorso e possono essere segmenti nome o senza nome. Questi segmenti vengono utilizzati per catturare i valori in posizioni specifiche nell'URL. È possibile utilizzare la funzione Params per recuperare questi valori, dove il parametro della funzione è il nome del parametro di percorso nel percorso o, per i parametri senza nome, sono i caratteri (*, +) e il loro conteggio.

Il carattere jolly (*) o il segno più (+) rappresentano parametri avidi.

I percorsi forniscono anche la possibilità di utilizzare parametri opzionali. Per i parametri nominati, questi parametri sono seguiti da un punto interrogativo (?), mentre il segno più non è opzionale e è possibile utilizzare caratteri jolly per rappresentare un intervallo di parametri facoltativi e avidi.

Esempio di definizione di un percorso con parametri di percorso

// Parametri
app.Get("/utente/:nome/libri/:titolo", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s\n", c.Params("nome"))
    fmt.Fprintf(c, "%s\n", c.Params("titolo"))
    return nil
})
// Più - avido - non facoltativo
app.Get("/utente/+", func(c *fiber.Ctx) error {
    return c.SendString(c.Params("+"))
})

// Parametro opzionale
app.Get("/utente/:nome?", func(c *fiber.Ctx) error {
    return c.SendString(c.Params("nome"))
})

// Jolly - avido - facoltativo
app.Get("/utente/*", func(c *fiber.Ctx) error {
    return c.SendString(c.Params("*"))
})

// Questo percorso corrisponderà alla richiesta "/v1/qualche/risorsa/nome:verboPersonalizzato" perché i caratteri del parametro sono stati elusi
app.Get(`/v1/qualche/risorsa/nome\:verboPersonalizzato`, func(c *fiber.Ctx) error {
    return c.SendString("Ciao, Community")
})

Poiché i trattini (-) e i punti (.) sono interpretati letteralmente, possono essere utilizzati insieme ai parametri di percorso per scopi utili.

Tutti i caratteri speciali dei parametri possono anche essere elusi utilizzando \ e i loro valori verranno ignorati, quindi se si desidera utilizzarli nel percorso. È consigliabile utilizzare apici inversi ``, poiché nella documentazione delle espressioni regolari Go vengono sempre utilizzati per garantire l'assenza di ambiguità e i caratteri di escape non influenzano involontariamente il modello di espressione regolare.

// http://localhost:3000/pianeta/prunus.persica
app.Get("/pianeta/:genere.:specie", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s.%s\n", c.Params("genere"), c.Params("specie"))
    return nil // prunus.persica
// http://localhost:3000/voli/LAX-SFO
app.Get("/voli/:da-:a", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s-%s\n", c.Params("da"), c.Params("a"))
    return nil // LAX-SFO
})

Il nostro routing intelligente riconosce che i caratteri del parametro introdotti in questo caso dovrebbero far parte del percorso della richiesta e può gestirlo come tale.

// http://localhost:3000/negozio/prodotto/colore:blu/dimensione:xs
app.Get("/negozio/prodotto/colore::colore/dimensione::dimensione", func(c *fiber.Ctx) error {
    fmt.Fprintf(c, "%s:%s\n", c.Params("colore"), c.Params("dimensione"))
    return nil // blu:xs
})

Inoltre, i percorsi possono utilizzare parametri multipli e caratteri di parametro senza nome multipli consecutivamente, come caratteri jolly o più, espandendo notevolmente le possibilità per gli utenti nei percorsi.

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

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

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

// GET /v1/marchio/4/negozio/blu/xs
// Params: "*1" -> "marchio/4", "*2" -> "blu/xs"
app.Get("/v1/*/negozio/*", handler)

Abbiamo già adattato il routing al routing di Express, ma non supporta ancora le espressioni regolari perché sono relativamente lente.

Vincoli

Quando c'è una corrispondenza con l'URL in ingresso e il percorso dell'URL è diviso in valori di percorso attraverso parametri, i vincoli verranno eseguiti. Questa funzionalità è stata introdotta nella versione v2.37.0 ed è stata ispirata da .NET Core.

I vincoli non sono per la convalida dei parametri. Se il vincolo non è valido per il valore del parametro, Fiber restituirà un gestore 404.

Vincolo Esempio Corrispondenza dell'esempio
int :id 123456789, -123456789
bool :active true, false
guid :id CD2C1638-1638-72D5-1638-DEADBEEF1638
float :weight 1.234, -1,001.01e8
minLen(valore) :username<minLen(4)> test (almeno 4 caratteri)
maxLen(valore) :filename<maxLen(8)> MyFile (fino a 8 caratteri)
len(lunghezza) :filename<len(12)> somefile.txt (12 caratteri)
min(valore) :age<min(18)> 19 (il valore intero deve essere almeno 18)
max(valore) :age<max(120)> 91 (il valore intero non può superare 120)
range(min,max) :age<range(18,120)> 91 (il valore intero deve essere almeno 18 ma non può superare 120)
alpha :name Rick (la stringa deve consistere in uno o più caratteri alfabetici, senza distinzione tra maiuscole e minuscole, a-z)
datetime :dob<datetime(2006\\-01\\-02)> 2005-11-01
regex(espressione) :date<regex(\d{4}-\d{2}-\d{2})> 2022-08-27 (deve corrispondere all'espressione regolare)

Esempi

  • Singolo vincolo
  • Vincoli multipli
  • Vincolo di espressione regolare
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 // Impossibile trovare GET /1

Puoi utilizzare `;` per aggiungere vincoli multipli.

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

// curl -X GET http://localhost:3000/120000 // Impossibile trovare GET /120000

// curl -X GET http://localhost:3000/1 // Impossibile trovare GET /1

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

Fiber precompila le query delle espressioni regolari durante la registrazione dei percorsi, quindi non c'è alcun impatto sulle prestazioni per i vincoli di espressione regolare.

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

// curl -X GET http://localhost:3000/125 // Impossibile trovare GET /125

// curl -X GET http://localhost:3000/test // Impossibile trovare GET /test

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

> Quando si utilizzano i vincoli di data e ora (`*`,`+`,`?`,`:`,`/`,``,``,`>`,`<`,`;`,`(`,`)`), utilizzare `\\` prima di utilizzare caratteri speciali nel percorso per evitare interpretazioni errate.

**Esempio di parametro opzionale**

È anche possibile aggiungere vincoli ai parametri opzionali.
```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
// Impossibile trovare GET /7.0

Middleware

Le funzioni progettate per manipolare richieste o risposte sono chiamate funzioni middleware. Next è una funzione di routing di Fiber che, quando chiamata, esegue la funzione next che corrisponde all'attuale percorso.

Esempio di funzione middleware

app.Use(func(c *fiber.Ctx) error {
  // Imposta un'intestazione personalizzata in tutte le risposte:
  c.Set("X-Custom-Header", "Ciao, mondo")

  // Procedi al middleware successivo:
  return c.Next()
})

app.Get("/", func(c *fiber.Ctx) error {
  return c.SendString("Ciao, mondo!")
})

Il percorso per il metodo Use può essere un percorso di mount o un percorso di prefisso, e limita il middleware da applicare solo alle richieste con percorsi che iniziano con quel percorso.

Aggiunta di Limitazioni dei Percorsi in Esecuzione

A causa di considerazioni di progettazione e prestazioni, non è supportato l'aggiunta dinamica di percorsi dopo l'avvio dell'applicazione. Assicurati che tutti i percorsi siano definiti prima dell'avvio dell'applicazione.

Raggruppamento

Se hai molti endpoint, puoi utilizzare Group per organizzare i percorsi.

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