Go HTTP router

Overview

GoDoc Build Status Coverage Status Go Report Card

violetear

Go HTTP router

http://violetear.org

Design Goals

  • Keep it simple and small, avoiding extra complexity at all cost. KISS
  • Support for static and dynamic routing.
  • Easy middleware compatibility so that it satisfies the http.Handler interface.
  • Common context between middleware.
  • Trace Request-ID per request.
  • HTTP/2 native support Push Example
  • Versioning based on Accept header application/vnd.*

Package GoDoc

How it works

The router is capable off handle any kind or URI, static, dynamic or catchall and based on the HTTP request Method accept or discard the request.

For example, suppose we have an API that exposes a service that allow to ping any IP address.

To handle only "GET" request for any IPv4 addresss:

http://api.violetear.org/command/ping/127.0.0.1
                        \______/\___/\________/
                            |     |      |
                             static      |
                                      dynamic

The router HandlerFunc would be:

router.HandleFunc("/command/ping/:ip", ip_handler, "GET")

For this to work, first the regex matching :ip should be added:

router.AddRegex(":ip", `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`)

Now let's say you also want to be available to ping ipv6 or any host:

http://api.violetear.org/command/ping/*
                        \______/\___/\_/
                            |     |   |
                             static   |
                                   catch-all

A catch-all could be used and also a different handler, for example:

router.HandleFunc("/command/ping/*", any_handler, "GET, HEAD")

The * indicates the router to behave like a catch-all therefore it will match anything after the /command/ping/ if no other condition matches before.

Notice also the "GET, HEAD", that indicates that only does HTTP methods will be accepted, and any other will not be allowed, router will return a 405 the one can also be customised.

Usage

Requirementes go >= 1.7 (https://golang.org/pkg/context/ required)

import "github.com/nbari/violetear"

HandleFunc:

 func HandleFunc(path string, handler http.HandlerFunc, http_methods ...string)

Handle (useful for middleware):

 func Handle(path string, handler http.Handler, http_methods ...string)

http_methods is a comma separted list of allowed HTTP methods, example:

router.HandleFunc("/view", handleView, "GET, HEAD")

AddRegex adds a ":named" regular expression to the dynamicRoutes, example:

router.AddRegex(":ip", `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`)

Basic example:

package main

import (
    "github.com/nbari/violetear"
    "log"
    "net/http"
)

func catchAll(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("I'm catching all\n"))
}

func handleGET(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("I handle GET requests\n"))
}

func handlePOST(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("I handle POST requests\n"))
}

func handleUUID(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("I handle dynamic requests\n"))
}

func main() {
    router := violetear.New()
    router.LogRequests = true
    router.RequestID = "Request-ID"

    router.AddRegex(":uuid", `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}`)

    router.HandleFunc("*", catchAll)
    router.HandleFunc("/method", handleGET, "GET")
    router.HandleFunc("/method", handlePOST, "POST")
    router.HandleFunc("/:uuid", handleUUID, "GET,HEAD")

    srv := &http.Server{
        Addr:           ":8080",
        Handler:        router,
        ReadTimeout:    5 * time.Second,
        WriteTimeout:   7 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }
    log.Fatal(srv.ListenAndServe())

}

Running this code will show something like this:

$ go run test.go
2015/10/22 17:14:18 Adding path: * [ALL]
2015/10/22 17:14:18 Adding path: /method [GET]
2015/10/22 17:14:18 Adding path: /method [POST]
2015/10/22 17:14:18 Adding path: /:uuid [GET,HEAD]

Using router.Verbose = false will omit printing the paths.

test.go contains the code show above

Testing using curl or http

Any request 'catch-all':

$ http POST http://localhost:8080/
HTTP/1.1 200 OK
Content-Length: 17
Content-Type: text/plain; charset=utf-8
Date: Thu, 22 Oct 2015 15:18:49 GMT
Request-Id: POST-1445527129854964669-1

I'm catching all

A GET request:

$ http http://localhost:8080/method
HTTP/1.1 200 OK
Content-Length: 22
Content-Type: text/plain; charset=utf-8
Date: Thu, 22 Oct 2015 15:43:25 GMT
Request-Id: GET-1445528605902591921-1

I handle GET requests

A POST request:

$ http POST http://localhost:8080/method
HTTP/1.1 200 OK
Content-Length: 23
Content-Type: text/plain; charset=utf-8
Date: Thu, 22 Oct 2015 15:44:28 GMT
Request-Id: POST-1445528668557478433-2

I handle POST requests

A dynamic request using an UUID as the URL resource:

$ http http://localhost:8080/50244127-45F6-4210-A89D-FFB0DA039425
HTTP/1.1 200 OK
Content-Length: 26
Content-Type: text/plain; charset=utf-8
Date: Thu, 22 Oct 2015 15:45:33 GMT
Request-Id: GET-1445528733916239110-5

I handle dynamic requests

Trying to use POST on the /:uuid resource will cause a Method not Allowed 405 this because only GET and HEAD methods are allowed:

$ http POST http://localhost:8080/50244127-45F6-4210-A89D-FFB0DA039425
HTTP/1.1 405 Method Not Allowed
Content-Length: 19
Content-Type: text/plain; charset=utf-8
Date: Thu, 22 Oct 2015 15:47:19 GMT
Request-Id: POST-1445528839403536403-6
X-Content-Type-Options: nosniff

Method Not Allowed

RequestID

To keep track of the "requests" an existing "request ID" header can be used, if the header name for example is Request-ID therefore to continue using it, the router needs to know the name, example:

router := violetear.New()
router.RequestID = "X-Appengine-Request-Log-Id"

If the proxy is using another name, for example "RID" then use something like:

router := violetear.New()
router.RequestID = "RID"

If router.RequestID is not set, no "request ID" is going to be added to the headers. This can be extended using a middleware same has the logger check the AppEngine example.

NotFoundHandler

For defining a custom http.Handler to handle 404 Not Found example:

...

func my404() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        http.Error(w, "ne ne ne", 404)
    })
}

func main() {
    router := violetear.New()
    router.NotFoundHandler = my404()
    ...

NotAllowedHandler

For defining a custom http.Handler to handle 405 Method Not Allowed.

PanicHandler

For using a custom http.HandlerFunc to handle panics

Middleware

Violetear uses Alice to handle middleware.

Example:

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/nbari/violetear"
	"github.com/nbari/violetear/middleware"
)

func commonHeaders(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-app-Version", "1.0")
		next.ServeHTTP(w, r)
	})
}

func middlewareOne(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println("Executing middlewareOne")
		ctx := context.WithValue(r.Context(), "m1", "m1")
		ctx = context.WithValue(ctx, "key", 1)
		next.ServeHTTP(w, r.WithContext(ctx))
		log.Println("Executing middlewareOne again")
	})
}

func middlewareTwo(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println("Executing middlewareTwo")
		if r.URL.Path != "/" {
			return
		}
		ctx := context.WithValue(r.Context(), "m2", "m2")
		next.ServeHTTP(w, r.WithContext(ctx))
		log.Println("Executing middlewareTwo again")
	})
}

func catchAll(w http.ResponseWriter, r *http.Request) {
	log.Printf("Executing finalHandler\nm1:%s\nkey:%d\nm2:%s\n",
		r.Context().Value("m1"),
		r.Context().Value("key"),
		r.Context().Value("m2"),
	)
	w.Write([]byte("I catch all"))
}

func foo(w http.ResponseWriter, r *http.Request) {
	panic("this will never happen, because of the return")
}

func main() {
	router := violetear.New()

	stdChain := middleware.New(commonHeaders, middlewareOne, middlewareTwo)

	router.Handle("/", stdChain.ThenFunc(catchAll), "GET,HEAD")
	router.Handle("/foo", stdChain.ThenFunc(foo), "GET,HEAD")
	router.HandleFunc("/bar", foo)

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

Notice the use or router.Handle and router.HandleFunc when using middleware you normally would use route.Handle

Request output example:

$ http http://localhost:8080/
HTTP/1.1 200 OK
Content-Length: 11
Content-Type: text/plain; charset=utf-8
Date: Thu, 22 Oct 2015 16:08:18 GMT
Request-Id: GET-1445530098002701428-3
X-App-Version: 1.0

I catch all

On the server you will see something like this:

$ go run test.go
2016/08/17 18:08:42 Adding path: / [GET,HEAD]
2016/08/17 18:08:42 Adding path: /foo [GET,HEAD]
2016/08/17 18:08:42 Adding path: /bar [ALL]
2016/08/17 18:08:47 Executing middlewareOne
2016/08/17 18:08:47 Executing middlewareTwo
2016/08/17 18:08:47 Executing finalHandler
m1:m1
key:1
m2:m2
2016/08/17 18:08:47 Executing middlewareTwo again
2016/08/17 18:08:47 Executing middlewareOne again

AppEngine

The app.yaml file:

application: 'app-name'
version: 1
runtime: go
api_version: go1

handlers:

- url: /.*
  script: _go_app

The app.go file:

package app

import (
    "appengine"
    "github.com/nbari/violetear"
    "github.com/nbari/violetear/middleware"
    "net/http"
)

func init() {
    router := violetear.New()
    stdChain := middleware.New(requestID)
    router.Handle("*", stdChain.ThenFunc(index), "GET, HEAD")
    http.Handle("/", router)
}

func requestID(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        c := appengine.NewContext(r)
        w.Header().Set("Request-ID", appengine.RequestID(c))
        next.ServeHTTP(w, r)
    })
}

func index(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello world!"))
}

Demo: http://api.violetear.org

Using curl or http:

$ http http://api.violetear.org
HTTP/1.1 200 OK
Cache-Control: private
Content-Encoding: gzip
Content-Length: 32
Content-Type: text/html; charset=utf-8
Date: Sun, 25 Oct 2015 06:14:55 GMT
Request-Id: 562c735f00ff0902f823e514a90001657e76696f6c65746561722d31313037000131000100
Server: Google Frontend

Hello world!

Context & Named parameters

In some cases there is a need to pass data across handlers/middlewares, for doing this Violetear uses net/context.

When using dynamic routes :regex, you can use GetParam or GetParams, see below.

Example:

package main

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

    "github.com/nbari/violetear"
)

func catchAll(w http.ResponseWriter, r *http.Request) {
    // Get & print the content of named-param *
    params := r.Context().Value(violetear.ParamsKey).(violetear.Params)
    fmt.Fprintf(w, "CatchAll value:, %q", params["*"])
}

func handleUUID(w http.ResponseWriter, r *http.Request) {
    // get router params
    params := r.Context().Value(violetear.ParamsKey).(violetear.Params)
    // using GetParam
    uuid := violetear.GetParam("uuid", r)
    // add a key-value pair to the context
    ctx := context.WithValue(r.Context(), "key", "my-value")
    // print current value for :uuid
    fmt.Fprintf(w, "Named parameter: %q, uuid; %q,  key: %s",
        params[":uuid"],
        uuid,
        ctx.Value("key"),
    )
}

func main() {
    router := violetear.New()

    router.AddRegex(":uuid", `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}`)

    router.HandleFunc("*", catchAll)
    router.HandleFunc("/:uuid", handleUUID, "GET,HEAD")

    srv := &http.Server{
        Addr:           ":8080",
        Handler:        router,
        ReadTimeout:    5 * time.Second,
        WriteTimeout:   7 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }
    log.Fatal(srv.ListenAndServe())
}

Duplicated named parameters

In cases where the same named parameter is used multiple times, example:

/test/:uuid/:uuid/

An slice is created, for getting the values you need to do something like:

params := r.Context().Value(violetear.ParamsKey).(violetear.Params)
uuid := params[":uuid"].([]string)

Notice the : prefix when getting the named_parameters

Or by using GetParams:

uuid := violetear.GetParams("uuid")

After this you can access the slice like normal:

fmt.Println(uuid[0], uuid[1])
Issues
  • create tests to cover when client closes request

    create tests to cover when client closes request

    If a client close the request and the router is configured to log requests the returned status is 499, like Nginx is doing it, for example:

    package main
    
    import (
    	"log"
    	"net/http"
    	"time"
    
    	"github.com/nbari/violetear"
    )
    
    func helloWorld(w http.ResponseWriter, r *http.Request) {
    	time.Sleep(time.Second)
    	w.Write([]byte("hello world"))
    }
    
    func main() {
    	router := violetear.New()
    	router.LogRequests = true
    	router.HandleFunc("*", helloWorld)
    	log.Fatal(http.ListenAndServe(":8080", router))
    }
    

    This is the output of some requests:

    $ go run main.go
    2017/10/07 14:58:11 Adding path: * [ALL]
    2017/10/07 14:58:13 127.0.0.1:58916 [/] 200 11 1.000748552s
    2017/10/07 14:58:16 127.0.0.1:58918 [/] 200 11 1.005227763s
    2017/10/07 14:58:18 127.0.0.1:58920 [/] 499 11 1.001131965s
    

    Notice the last entry, it returned a 499, in this case, the user closed the request (ctrl + c) after doing curl 0:8080

    This is working but the tests are missing specific to cover this block https://github.com/nbari/violetear/blob/master/responsewriter.go#L24-L30

    help wanted Hacktoberfest 
    opened by nbari 14
  • Added parameter reader helper func

    Added parameter reader helper func

    Hi, @nbari. Since we end up rewriting the same piece of code in order to access parameter values, I decided to make this PR. Let me know what you think and if you agree with the solution I will update the README file as well.

    Example:

    // Define parameter via regexp
    router := violetear.New()
    router.AddRegex(":language", `^\w+$`)
    
    // Read parameter in your handler
    func HandleLanguage(w http.ResponseWriter, r *http.Request) {
        language := violetear.GetParam("language")
        fmt.Fprintf(w, "your language is: %s", language)
    }
    
    enhancement 
    opened by makarski 14
  • NewResponseWriter appears to leak goroutines

    NewResponseWriter appears to leak goroutines

    https://github.com/nbari/violetear/blob/7450092af2f65a7a183f6d58f353876490c89894/responsewriter.go#L26-L29

    https://golang.org/pkg/net/http/#CloseNotifier

            // After the Handler has returned, there is no guarantee
            // that the channel receives a value.
    

    That's 1 goroutine to leak for each request. To reproduce.

    1. Start a http server with pprof enabled.
    2. Access any url handled by violetear multiple times.
    3. Visit http://localhost:8080/debug/pprof/goroutine?debug=2 (adjust url to your server)
    4. Notice the following goroutine , showing up roughly the number of requests made during step 2
    goroutine 11 [chan receive, 7 minutes]:
    github.com/nbari/violetear.NewResponseWriter.func1(0xc420066000, 0xc4245596d0)
    	/home/sajal/go/src/github.com/nbari/violetear/responsewriter.go:27 +0x34
    created by github.com/nbari/violetear.NewResponseWriter
    	/home/sajal/go/src/github.com/nbari/violetear/responsewriter.go:26 +0x153
    

    I am not sure what is the purpose of that goroutine, but I think it should be cancelled once the response has been satisfied.

    enhancement help wanted Hacktoberfest fixed 
    opened by sajal 7
  • Allow passing custom logger

    Allow passing custom logger

    Currently setting router.LogRequests = true , the requests logs are printed to stderr using default format. But I would like some way to pass a custom logger, example: logrus . Most logging implementations can be abstracted to a simple interface.

    If provided use it, otherwise use the default behavior.

    enhancement Hacktoberfest 
    opened by sajal 5
  • ResponseWriter Interface to support Hijack() to allow websocket

    ResponseWriter Interface to support Hijack() to allow websocket

    In order to support websocket with violetear, using something like Gorilla websocket, violetear's ResponseWriter implementation would need to support the Hijack() function. The Gin project added that feature for the same reason; see https://github.com/gin-gonic/gin/pull/105/commits/4a24c47a69f56e8275ef330beca3c2925d270948

    Thanks!

    opened by JeffMerlet 4
  • do some benchmarks

    do some benchmarks

    Router currently implementing a trie, but when specifying methods per request uses a map.

    router.HandleFunc("/test_get", handleView, "GET, HEAD")
    router.HandleFunc("/test_post", handleView, "POST")
    

    Besides that router supports dynamic routing, but for this uses regex

    router.AddRegex(":ip", `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`)
    router.HandleFunc("/command/ping/:ip", ip_handler, "GET")
    

    Router working fine and in theory "fast" but nothing better than doing some benchmarks.

    help wanted Hacktoberfest 
    opened by nbari 3
  • implement versioning via http headers

    implement versioning via http headers

    find a way to implement versioning based on custom HTTP headers, example:

    Accept: application/vnd.github.v3+json
    

    so that will serve from a tree (root)

    /root
    |--main.go
    |--handlers
    `--vX
       `-- handlers
    
    enhancement 
    opened by nbari 2
  • add method or to the context a way to retrieve the endpoint

    add method or to the context a way to retrieve the endpoint

    When instrumenting endpoints with a wildcard *, instead of logging all the possible requests would be better to just use the name of the "endpoint", this would avoid having to do something like this:

     endpoint := "*"
     for _, v := range []string{"/foo/", "/foo"} {
           if r.URL.Path == v {
                endpoint = "/foo"
                break
           }
     }
    
    enhancement fixed 
    opened by nbari 1
  • structured loggin using the logger

    structured loggin using the logger

    Create some examples using the Logger option to satisfy the 12 factor - Treat logs as event streams

    By using any custom function that satisfies the logger:

    Logger func(*ResponseWriter, *http.Request)
    

    Should be easy to write to stdout in any structured format like JSON.

    Hacktoberfest 
    opened by nbari 1
  • try to reduce the number of allocations

    try to reduce the number of allocations

    When using named params (https://violetear.org/post/context-named/) the router uses 6 allocations, when not it uses 0.

    $ make bench
    go test -run=^$ -bench=.
    2017/10/05 21:57:31 Adding path: /hello [GET,HEAD]
    goos: darwin
    goarch: amd64
    pkg: github.com/nbari/violetear
    BenchmarkRouterStatic-4         2017/10/05 21:57:31 Adding path: /hello [GET,HEAD]
    2017/10/05 21:57:31 Adding path: /hello [GET,HEAD]
    2017/10/05 21:57:31 Adding path: /hello [GET,HEAD]
    2017/10/05 21:57:32 Adding path: /hello [GET,HEAD]
    10000000               122 ns/op               0 B/op          0 allocs/op
    2017/10/05 21:57:33 Adding path: /test/:word [GET,HEAD]
    BenchmarkRouterDynamic-4        2017/10/05 21:57:33 Adding path: /test/:word [GET,HEAD]
    2017/10/05 21:57:33 Adding path: /test/:word [GET,HEAD]
    2017/10/05 21:57:33 Adding path: /test/:word [GET,HEAD]
    2017/10/05 21:57:34 Adding path: /test/:word [GET,HEAD]
     2000000               913 ns/op             784 B/op          6 allocs/op
    PASS
    ok      github.com/nbari/violetear      4.144s
    
    

    Try to optimize the router to do allocs as little as possible.

    enhancement help wanted Hacktoberfest 
    opened by nbari 1
  • centralized error handler

    centralized error handler

    Find a way to have a centralized error handler, so that handlers can return an error and that error can be handled globally.

    This implies to change default signature to something like:

    type ErrorHandler func(w http.ResponseWriter, r *http.Request) error
    
    enhancement help wanted 
    opened by nbari 1
  • improve README / docs

    improve README / docs

    Check the README/ docs https://github.com/nbari/violetear-docs/tree/master/post

    mainly the examples test if they work etc.

    The prometheus sections need to be updated with the usage of promhttp.Handler(): https://github.com/nbari/violetear-docs/edit/master/post/prometheus.md

    help wanted Hacktoberfest 
    opened by nbari 2
Releases(7.0.0)
Owner
Nicolas Embriz
$ dig ping.nbari.com txt +short
Nicolas Embriz
Go HTTP router

violetear Go HTTP router http://violetear.org Design Goals Keep it simple and small, avoiding extra complexity at all cost. KISS Support for static an

Nicolas Embriz 105 Mar 21, 2022
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

Gin Web Framework Gin is a web framework written in Go (Golang). It features a martini-like API with performance that is up to 40 times faster thanks

Gin-Gonic 61.7k Aug 8, 2022
Go http middleware handler for request coalescing

HTTP Coala NOTE: a new and improved implementation is available at https://github.com/go-chi/stampede Just a little bit of performance enhancing middl

go-chi 128 Apr 3, 2022
Idiomatic HTTP Middleware for Golang

Negroni Notice: This is the library formerly known as github.com/codegangsta/negroni -- Github will automatically redirect requests to this repository

null 7.2k Aug 4, 2022
Simple HTTP and REST client library for Go

Resty Simple HTTP and REST client library for Go (inspired by Ruby rest-client) Features section describes in detail about Resty capabilities Resty Co

Go Resty 6.5k Aug 9, 2022
Bxog is a simple and fast HTTP router for Go (HTTP request multiplexer).

Bxog is a simple and fast HTTP router for Go (HTTP request multiplexer). Usage An example of using the multiplexer: package main import ( "io" "net

Eduard 103 Apr 10, 2022
Simple Golang HTTP router

Bellt Simple Golang HTTP router Bellt Package implements a request router with the aim of managing controller actions based on fixed and parameterized

Guilherme Caruso 54 Jul 18, 2022
FastRouter is a fast, flexible HTTP router written in Go.

FastRouter FastRouter is a fast, flexible HTTP router written in Go. FastRouter contains some customizable options, such as TrailingSlashesPolicy, Pan

Razon Yang 21 Apr 19, 2022
Go Server/API micro framework, HTTP request router, multiplexer, mux

?? gorouter Go Server/API micro framework, HTTP request router, multiplexer, mux. ?? ABOUT Contributors: Rafał Lorenz Want to contribute ? Feel free t

Rafał Lorenz 130 Jul 24, 2022
A high performance HTTP request router that scales well

HttpRouter HttpRouter is a lightweight high performance HTTP request router (also called multiplexer or just mux for short) for Go. In contrast to the

Julien Schmidt 14.3k Aug 8, 2022
High-speed, flexible tree-based HTTP router for Go.

httptreemux High-speed, flexible, tree-based HTTP router for Go. This is inspired by Julien Schmidt's httprouter, in that it uses a patricia tree, but

Daniel Imfeld 549 Jul 25, 2022
:rotating_light: Is a lightweight, fast and extensible zero allocation HTTP router for Go used to create customizable frameworks.

LARS LARS is a fast radix-tree based, zero allocation, HTTP router for Go. view examples. If looking for a more pure Go solution, be sure to check out

Go Playgound 389 Jul 27, 2022
A powerful HTTP router and URL matcher for building Go web servers with 🦍

gorilla/mux https://www.gorillatoolkit.org/pkg/mux Package gorilla/mux implements a request router and dispatcher for matching incoming requests to th

Gorilla Web Toolkit 17.1k Aug 4, 2022
An extremely fast Go (golang) HTTP router that supports regular expression route matching. Comes with full support for building RESTful APIs.

ozzo-routing You may consider using go-rest-api to jumpstart your new RESTful applications with ozzo-routing. Description ozzo-routing is a Go package

Ozzo Framework 441 Aug 8, 2022
Pure is a fast radix-tree based HTTP router

package pure Pure is a fast radix-tree based HTTP router that sticks to the native implementations of Go's "net/http" package; in essence, keeping the

Go Playgound 128 Aug 8, 2022
Go HTTP router

violetear Go HTTP router http://violetear.org Design Goals Keep it simple and small, avoiding extra complexity at all cost. KISS Support for static an

Nicolas Embriz 105 Mar 21, 2022
xujiajun/gorouter is a simple and fast HTTP router for Go. It is easy to build RESTful APIs and your web framework.

gorouter xujiajun/gorouter is a simple and fast HTTP router for Go. It is easy to build RESTful APIs and your web framework. Motivation I wanted a sim

徐佳军 527 Jul 16, 2022
Go HTTP request router and web framework benchmark

Go HTTP Router Benchmark This benchmark suite aims to compare the performance of HTTP request routers for Go by implementing the routing structure of

Julien Schmidt 1.6k Aug 6, 2022
A lightweight and fast http router from outer space

Alien Alien is a lightweight http router( multiplexer) for Go( Golang ), made for humans who don't like magic. Documentation docs Features fast ( see

Geofrey Ernest 122 Jul 21, 2022
A high performance HTTP request router that scales well

HttpRouter HttpRouter is a lightweight high performance HTTP request router (also called multiplexer or just mux for short) for Go. In contrast to the

Julien Schmidt 14.3k Aug 3, 2022
Go HTTP router

violetear Go HTTP router http://violetear.org Design Goals Keep it simple and small, avoiding extra complexity at all cost. KISS Support for static an

Nicolas Embriz 105 Mar 21, 2022
lightweight, idiomatic and composable router for building Go HTTP services

chi is a lightweight, idiomatic and composable router for building Go HTTP services. It's especially good at helping you write large REST API services

go-chi 11.9k Aug 6, 2022
Gerasimos (Makis) Maropoulos 22.7k Aug 7, 2022
lightweight, idiomatic and composable router for building Go HTTP services

chi is a lightweight, idiomatic and composable router for building Go HTTP services. It's especially good at helping you write large REST API services

go-chi 11.9k Aug 9, 2022
:tongue: CleverGo is a lightweight, feature rich and high performance HTTP router for Go.

CleverGo CleverGo is a lightweight, feature rich and trie based high performance HTTP request router. go get -u clevergo.tech/clevergo English 简体中文 Fe

CleverGo Web Framework 251 May 30, 2022
Fast and flexible HTTP router

treemux - fast and flexible HTTP router Basic example Debug logging CORS example Error handling Rate limiting using Redis Gzip compression OpenTelemet

Vladimir Mihailenco 458 Jul 29, 2022
Fast, simple, and lightweight HTTP router for Golang

Sariaf Fast, simple and lightweight HTTP router for golang Install go get -u github.com/majidsajadi/sariaf Features Lightweight compatible with net/ht

defectivepixel 34 Jul 27, 2022
Simple router build on `net/http` supports custom middleWare.

XMUS-ROUTER Fast lightweight router build on net/http supports delegate and in url params. usage : Create new router using NewRouter() which need rout

amupxm [amir hossein mokarrami far] 5 Dec 27, 2021
Simple HTTP router for Go

ngamux Simple HTTP router for Go Installation Examples Todo Installation Run this command with correctly configured Go toolchain. go get github.com/ng

null 51 Jun 1, 2022