项目作者: GuilhermeCaruso

项目描述 :
:bell: A simple Go router
高级语言: Go
项目地址: git://github.com/GuilhermeCaruso/bellt.git
创建时间: 2019-02-21T13:13:52Z
项目社区:https://github.com/GuilhermeCaruso/bellt

开源协议:MIT License

下载


Bellt

Simple Golang HTTP router

Mentioned in Awesome Go License: MIT Go Report Card codecov Build Status GitHub GoDoc



Bellt Package implements a request router with the aim of managing controller actions based on fixed and parameterized routes.

The project so far has the following functionalities:

  • Standard definition of route “/health”, in order to prepare the service developed with bellt to act as microservice.
  • Providing the creation of parameterized routes, simple or segmented (groups).
  • All requests can be made through fixed patterns, querystrings and parameters.
  • Obtaining the requisition parameters in the controller functions.

Summary

Install

To get Bellt

> Go CLI
  1. go get -u github.com/GuilhermeCaruso/bellt
> Go DEP
  1. dep ensure -add github.com/GuilhermeCaruso/bellt
> Govendor
  1. govendor fetch github.com/GuilhermeCaruso/bellt

Guide

Router

To initialize our router

  1. var router = bellt.NewRouter()
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/http"
  6. "github.com/GuilhermeCaruso/bellt"
  7. )
  8. func main() {
  9. router := bellt.NewRouter()
  10. log.Fatal(http.ListenAndServe(":8080", nil))
  11. }

HandleFunc

HandleFunc function responsible for initializing a common route or built through the Router. All non-grouped routes must be initialized by this method.

  1. /*
  2. [path] - Endpoint string
  3. [handlerFunc] - Function that will be called on the request
  4. [methods] - Slice for endpoint methods ("GET", "POST", "PUT", "DELETE")
  5. */
  6. router.HandleFunc(path, handlerFunc, methods)
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/http"
  6. "github.com/GuilhermeCaruso/bellt"
  7. )
  8. func main() {
  9. router := bellt.NewRouter()
  10. router.HandleFunc("/bellt", belltHandler, "GET")
  11. log.Fatal(http.ListenAndServe(":8080", nil))
  12. }
  13. func belltHandle(w http.ResponseWriter, r *http.Request){
  14. w.WriteHeader(http.StatusOK)
  15. w.Write([]byte("Simple Golang HTTP router")
  16. }

HandleGroup

HandleGroup is responsible for creating a group of routes. The main path can be set for all other routes.

  1. /*
  2. [mainPath] - Main route used in all subr-outes
  3. [subHandleFunc] - SubHandleFunc function responsiblefor initializing a common route or
  4. built through the Router. All grouped routes must be initialized by this method
  5. */
  6. router.HandleGroup(mainPath, ...SubHandleFunc)

SubHandleFunc

SubHandleFunc is responsible for initializing a common or built route. Its use must be made within the scope of the HandleGroup method, where the main path will be declared.

  1. /*
  2. [path] - Endpoint string
  3. [handlerFunc] - Function that will be called on the request
  4. [methods] - Slice for endpoint methods ("GET", "POST", "PUT", "DELETE")
  5. */
  6. router.SubHandleFunc(path, handlerFunc, methods)
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/http"
  6. "github.com/GuilhermeCaruso/bellt"
  7. )
  8. func main() {
  9. router := bellt.NewRouter()
  10. router.HandleGroup("/api",
  11. router.SubHandleFunc("/bellt", belltHandle, "GET"),
  12. router.SubHandleFunc("/check", checkHandle, "GET"),
  13. )
  14. log.Fatal(http.ListenAndServe(":8080", nil))
  15. }
  16. func belltHandle(w http.ResponseWriter, r *http.Request){
  17. w.WriteHeader(http.StatusOK)
  18. w.Write([]byte("Simple Golang HTTP router")
  19. }
  20. func checkHandle(w http.ResponseWriter, r *http.Request){
  21. w.WriteHeader(http.StatusOK)
  22. w.Write([]byte("Ok!")
  23. }

Middleware

The declaration of middlewares in HandleFunc or SubHandleFunc should be done using the Use method

Use

  1. /*
  2. handlerFunc - Function that will be called on the request
  3. middlewareList - Slice of middleware that will be used in the request (Middleware)
  4. */
  5. bellt.Use(handlerFunc, ...middlewareList)

The middleware type has a following signature

  1. type Middleware func(http.HandlerFunc) http.HandlerFunc

Applying middlewares to routes

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/http"
  6. "github.com/GuilhermeCaruso/bellt"
  7. )
  8. func main() {
  9. router := bellt.NewRouter()
  10. router.HandleFunc("/hello", bellt.Use(
  11. exampleHandler,
  12. middlewareOne,
  13. middlewareTwo,
  14. ), "GET")
  15. router.HandleGroup("/api",
  16. router.SubHandleFunc("/hello", bellt.Use(
  17. exampleHandler,
  18. middlewareOne,
  19. middlewareTwo,
  20. ), "GET"),
  21. )
  22. log.Fatal(http.ListenAndServe(":8080", nil))
  23. }
  24. func exampleHandler(w http.ResponseWriter, r *http.Request) {
  25. w.WriteHeader(http.StatusOK)
  26. w.Write([]byte(`Hello Middleware!`))
  27. }
  28. func middlewareOne(next http.HandlerFunc) http.HandlerFunc {
  29. return func(w http.ResponseWriter, r *http.Request) {
  30. fmt.Println("Step One")
  31. next.ServeHTTP(w, r)
  32. }
  33. }
  34. func middlewareTwo(next http.HandlerFunc) http.HandlerFunc {
  35. return func(w http.ResponseWriter, r *http.Request) {
  36. fmt.Println("Step Two")
  37. next.ServeHTTP(w, r)
  38. }
  39. }

Parameterized Routes

Route parameters must be passed using {} as scope limiter

  1. router.HandleFunc("/hello/{name}", handlerFunc, "GET")
  2. router.HandleGroup("/api",
  3. SubHandleFunc("/item/{id}", handlerFunc, "GET")
  4. )

Route Variables

RouteVariables used to capture and store parameters passed to built routes.

Need to pass the *Request of the HandlerFunc used in the HandleFunc method.

  1. /*
  2. r = *Request of the HandlerFunc
  3. */
  4. rv := bellt.RouteVariables(r)

The declaration must be made within the HandlerFunc

  1. func exampleHandler(w http.ResponseWriter, r *http.Request) {
  2. rv := bellt.RouteVariables(r)
  3. /*[...]*/
  4. w.WriteHeader(http.StatusOK)
  5. w.Write([]byte("Hello!"))
  6. }

GetVar

GetVar returns the parameter value of the route

  1. /*
  2. r = *Request of the HandlerFunc
  3. param = Parameter name string
  4. */
  5. rv := bellt.RouteVariables(r)
  6. rv.GetVar(param)
  1. func exampleHandler(w http.ResponseWriter, r *http.Request) {
  2. rv := bellt.RouteVariables(r)
  3. w.WriteHeader(http.StatusOK)
  4. w.Write([]byte(fmt.Sprintf(`Hello %v gopher!`, rv.GetVar("color")))))
  5. }

The complete implementation of parameterized routes should look like this:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/http"
  6. "github.com/GuilhermeCaruso/bellt"
  7. )
  8. func main() {
  9. router := bellt.NewRouter()
  10. router.HandleFunc("/contact/{id}/{user}", exampleHandler, "GET")
  11. router.HandleGroup("/api",
  12. router.SubHandleFunc("/check/{id}/{user}", exampleHandler, "GET"),
  13. )
  14. log.Fatal(http.ListenAndServe(":8080", nil))
  15. }
  16. func exampleHandler(w http.ResponseWriter, r *http.Request) {
  17. rv := bellt.RouteVariables(r)
  18. w.Header().Set("Content-Type", "application/json")
  19. w.WriteHeader(http.StatusOK)
  20. w.Write([]byte(fmt.Sprintf(`{"id": %v, "user": %v}`, rv.GetVar("user"), rv.GetVar("id"))))
  21. }

Full Example

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/http"
  6. "github.com/GuilhermeCaruso/bellt"
  7. )
  8. func main() {
  9. router := bellt.NewRouter()
  10. router.HandleFunc("/contact/{id}/{user}", bellt.Use(
  11. exampleHandler,
  12. middlewareOne,
  13. middlewareTwo,
  14. ), "GET")
  15. router.HandleFunc("/contact", bellt.Use(
  16. exampleNewHandler,
  17. middlewareOne,
  18. middlewareTwo,
  19. ), "GET")
  20. router.HandleGroup("/api",
  21. router.SubHandleFunc("/check", bellt.Use(
  22. exampleNewHandler,
  23. middlewareOne,
  24. middlewareTwo,
  25. ), "GET"),
  26. router.SubHandleFunc("/check/{id}/{user}", bellt.Use(
  27. exampleHandler,
  28. middlewareOne,
  29. middlewareTwo,
  30. ), "GET"),
  31. )
  32. log.Fatal(http.ListenAndServe(":8080", nil))
  33. }
  34. func exampleHandler(w http.ResponseWriter, r *http.Request) {
  35. rv := bellt.RouteVariables(r)
  36. w.Header().Set("Content-Type", "application/json")
  37. w.WriteHeader(http.StatusOK)
  38. w.Write([]byte(fmt.Sprintf(`{"id": %v, "user": %v}`, rv.GetVar("user"), rv.GetVar("id"))))
  39. }
  40. func exampleNewHandler(w http.ResponseWriter, r *http.Request) {
  41. rv := bellt.RouteVariables(r)
  42. w.Header().Set("Content-Type", "application/json")
  43. w.WriteHeader(http.StatusOK)
  44. w.Write([]byte(`{"msg": "Works"}`))
  45. }
  46. func middlewareOne(next http.HandlerFunc) http.HandlerFunc {
  47. return func(w http.ResponseWriter, r *http.Request) {
  48. fmt.Println("Step One")
  49. next.ServeHTTP(w, r)
  50. }
  51. }
  52. func middlewareTwo(next http.HandlerFunc) http.HandlerFunc {
  53. return func(w http.ResponseWriter, r *http.Request) {
  54. fmt.Println("Step Two")
  55. next.ServeHTTP(w, r)
  56. }
  57. }

Benchmark

Applying requisition performance tests, the following results were obtained, showing the initial potency of the Bellt package.



Author

Guilherme Caruso @guicaruso_ on twitter

Presentation

Guilherme Caruso - Cabify- GolangSP Meetup 2 - 21/03/2019 - São Paulo /Brazil

Slides - Construindo Rotas Parametrizadas em GO

Video - GolangSP Meetup 2

License

MIT licensed. See the LICENSE file for details.