DEV Community

Igor Melo
Igor Melo

Posted on

Go 1.22 e o novo router HTTP

Introdução

O http.ServeMux do Go ganhou novas features muito aguardadas pelos desenvolvedores, e como sempre, essas features são retrocompatíveis.

Em resumo, as features são:

  • Match com base no método HTTP
http.Handle("GET /users", ...)
Enter fullscreen mode Exit fullscreen mode
  • Variavéis no path da requisição
http.Handle("GET /users/{id}", ...)
Enter fullscreen mode Exit fullscreen mode
  • Match exato de paths terminados em barra
// match para qualquer path iniciado com /static/
http.Handle("GET /static/", ...)

// match somente GET /static/
http.Handle("GET /static/{$}", ...)
Enter fullscreen mode Exit fullscreen mode

Essas mudanças vão reduzir bastante a necessidade de utilizar bibliotecas de routers, e como vai para a stdlib, vai ter a garantia de compatibilidade do Go 1.

1. Como funciona o http.ServeMux

O ServeMux tem um comportamento diferente da maioria dos routers.

Caminhos terminados em barra são como pastas

http.Handle("/assets/", ...)
Enter fullscreen mode Exit fullscreen mode

Esse handler processa qualquer requisição com prefixo /assets/, como:

  • GET /assets/
  • GET /assets/img/img.png
  • DELETE /assets/abcd

O match é feito com o path exato se não for terminado em barra

http.Handle("/", ...)
http.Handle("/assets", ...)
Enter fullscreen mode Exit fullscreen mode

Nesse caso o segundo pattern não termina em barra, então só requisições para exatamente /assets vão ser processadas por esse handler, e qualquer outra será processada pelo primeiro handler.

Obs.: O caminho / dá match em qualquer requisição que não dê match em outro handler, então ele é geralmente usado para a página raiz e página de not found.

O match é feito com o path mais similar

Se você tiver:

http.Handle("/users/", ...)
http.Handle("/users/123", ...)
http.Handle("/users/books/", ...)
Enter fullscreen mode Exit fullscreen mode
  • Uma requisição para /users/ vai cair no primeiro handler.
  • Uma requisição para /users/123 vai cair no segundo handler.
  • Uma requisição para /users/1234 vai cair no primeiro handler.
  • Uma requisição para /users/books/123 vai cair no terceiro handler.
  • Uma requisição para /users/a/b/c/d também cai no primeiro handler

2. Entendendo o match com base no método HTTP

O comportamento das funções Handle e HandleFunc vai se manter igual para códigos existentes por conta da retrocompatibilidade da linguagem, então se você não especificar um método HTTP, seu handler vai continuar dando match em qualquer método.

Obs.: Um handler para o método GET vai também bater para requisições do método HEAD.

// GET /users
// HEAD /users
http.HandleFunc("GET /users", ...)


// somente DELETE /users
http.HandleFunc("DELETE /users", ...)
Enter fullscreen mode Exit fullscreen mode

3. Utilizando variáveis de path

Podemos capturar o valor de uma variável de path usando o PathValue.

http.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id")
    ...
})
Enter fullscreen mode Exit fullscreen mode

4. Utilizando matches exatos

Ao utilizar o {$} indicamos que um handler terminado em barra deve somente bater com aquele path, e não com qualquer path com aquele prefixo.

// redirecionar um request de / para /home
http.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) {
    http.Redirect(w, r, "/home")
})

// qualquer outro path que não de match em outro handler vai dar um not found
http.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
    http.NotFound(w, r)
})
Enter fullscreen mode Exit fullscreen mode

Conclusão

Apesar de simples, essa foi uma mudança bem importante na stdlib do Go, tendo em vista que é uma linguagem muito utilizada para desenvolver servidores Web.

Mas é claro que essas foram só algumas das muitas novidades do Go 1.22 e pretendo falar de outras que foram bem expressivas, como no for loop, pacote rand, e outros em próximos artigos.

Top comments (0)