Popularity
3.2
Growing
Activity
0.0
-
44
5
2

Programming language: Go
Tags: Web Frameworks     Routers    

bellt alternatives and similar packages

Based on the "Routers" category

Do you think we are missing an alternative of bellt or a related project?

Add another 'Routers' Package

README

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
go get -u github.com/GuilhermeCaruso/bellt
> Go DEP
dep ensure -add github.com/GuilhermeCaruso/bellt
> Govendor
govendor fetch github.com/GuilhermeCaruso/bellt

Guide

Router

To initialize our router

var router = bellt.NewRouter()
package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {
    router := bellt.NewRouter()

    log.Fatal(http.ListenAndServe(":8080", nil))
}

HandleFunc

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

/*
    [path] - Endpoint string
    [handlerFunc] - Function that will be called on the request
    [methods] - Slice for endpoint methods ("GET", "POST", "PUT", "DELETE")
*/

router.HandleFunc(path, handlerFunc, methods)

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {
    router := bellt.NewRouter()

    router.HandleFunc("/bellt", belltHandler, "GET")

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func belltHandle(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Simple Golang HTTP router")
}

HandleGroup

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

/*
    [mainPath] - Main route used in all subr-outes

    [subHandleFunc] - SubHandleFunc function responsiblefor initializing a common route or
    built through the Router. All grouped routes must be initialized by this method
*/

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.

/*
    [path] - Endpoint string
    [handlerFunc] - Function that will be called on the request
    [methods] - Slice for endpoint methods ("GET", "POST", "PUT", "DELETE")
*/

router.SubHandleFunc(path, handlerFunc, methods)

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {
    router := bellt.NewRouter()

    router.HandleGroup("/api",
        router.SubHandleFunc("/bellt", belltHandle, "GET"),
        router.SubHandleFunc("/check", checkHandle, "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func belltHandle(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Simple Golang HTTP router")
}

func checkHandle(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Ok!")
}

Middleware

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

Use

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

The middleware type has a following signature

type Middleware func(http.HandlerFunc) http.HandlerFunc

Applying middlewares to routes

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {

    router := bellt.NewRouter()

    router.HandleFunc("/hello", bellt.Use(
        exampleHandler,
        middlewareOne,
        middlewareTwo,
    ), "GET")

    router.HandleGroup("/api",
        router.SubHandleFunc("/hello", bellt.Use(
            exampleHandler,
            middlewareOne,
            middlewareTwo,
        ), "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func exampleHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`Hello Middleware!`))
}

func middlewareOne(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step One")
        next.ServeHTTP(w, r)
    }
}

func middlewareTwo(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step Two")
        next.ServeHTTP(w, r)
    }
}

Parameterized Routes

Route parameters must be passed using {} as scope limiter

router.HandleFunc("/hello/{name}", handlerFunc, "GET")

router.HandleGroup("/api", 
    SubHandleFunc("/item/{id}", handlerFunc, "GET")
)

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.

/*
    r = *Request of the HandlerFunc
*/
rv := bellt.RouteVariables(r)

The declaration must be made within the HandlerFunc

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

GetVar

GetVar returns the parameter value of the route

/*
    r = *Request of the HandlerFunc
    param = Parameter name string
*/
rv := bellt.RouteVariables(r)

rv.GetVar(param)
func exampleHandler(w http.ResponseWriter, r *http.Request) {
    rv := bellt.RouteVariables(r)
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(fmt.Sprintf(`Hello %v gopher!`, rv.GetVar("color")))))
}

The complete implementation of parameterized routes should look like this:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {

    router := bellt.NewRouter()

    router.HandleFunc("/contact/{id}/{user}", exampleHandler, "GET")

    router.HandleGroup("/api",
        router.SubHandleFunc("/check/{id}/{user}", exampleHandler, "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func exampleHandler(w http.ResponseWriter, r *http.Request) {
    rv := bellt.RouteVariables(r)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(fmt.Sprintf(`{"id": %v, "user": %v}`, rv.GetVar("user"), rv.GetVar("id"))))
}

Full Example

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {

    router := bellt.NewRouter()

    router.HandleFunc("/contact/{id}/{user}", bellt.Use(
        exampleHandler,
        middlewareOne,
        middlewareTwo,
    ), "GET")

    router.HandleFunc("/contact", bellt.Use(
        exampleNewHandler,
        middlewareOne,
        middlewareTwo,
    ), "GET")

    router.HandleGroup("/api",
        router.SubHandleFunc("/check", bellt.Use(
            exampleNewHandler,
            middlewareOne,
            middlewareTwo,
        ), "GET"),
        router.SubHandleFunc("/check/{id}/{user}", bellt.Use(
            exampleHandler,
            middlewareOne,
            middlewareTwo,
        ), "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func exampleHandler(w http.ResponseWriter, r *http.Request) {

    rv := bellt.RouteVariables(r)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(fmt.Sprintf(`{"id": %v, "user": %v}`, rv.GetVar("user"), rv.GetVar("id"))))
}

func exampleNewHandler(w http.ResponseWriter, r *http.Request) {
    rv := bellt.RouteVariables(r)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`{"msg": "Works"}`))
}

func middlewareOne(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step One")

        next.ServeHTTP(w, r)
    }
}

func middlewareTwo(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step Two")

        next.ServeHTTP(w, r)
    }
}

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.


*Note that all licence references and agreements mentioned in the bellt README section above are relevant to that project's source code only.