All Projects → bmf-san → goblin

bmf-san / goblin

Licence: MIT license
A golang http router based on trie tree.

Programming Languages

go
31211 projects - #10 most used programming language
Makefile
30231 projects

Projects that are alternatives of or similar to goblin

Flash
Golang Keyword extraction/replacement Datastructure using Tries instead of regexes
Stars: ✭ 79 (+51.92%)
Mutual labels:  trie
Slim
Surprisingly space efficient trie in Golang(11 bits/key; 100 ns/get).
Stars: ✭ 1,705 (+3178.85%)
Mutual labels:  trie
Leetcode
High-quality LeetCode solutions
Stars: ✭ 178 (+242.31%)
Mutual labels:  trie
Completely
Java autocomplete library.
Stars: ✭ 90 (+73.08%)
Mutual labels:  trie
Trienet
.NET Implementations of Trie Data Structures for Substring Search, Auto-completion and Intelli-sense. Includes: patricia trie, suffix trie and a trie implementation using Ukkonen's algorithm.
Stars: ✭ 122 (+134.62%)
Mutual labels:  trie
Algorithms
A collection of common algorithms and data structures implemented in java, c++, and python.
Stars: ✭ 142 (+173.08%)
Mutual labels:  trie
Efrt
neato compression for key-value data
Stars: ✭ 58 (+11.54%)
Mutual labels:  trie
Data Structures
A collection of powerful data structures
Stars: ✭ 2,534 (+4773.08%)
Mutual labels:  trie
Java Ds Algorithms
Data Structures and Algorithms in Java
Stars: ✭ 125 (+140.38%)
Mutual labels:  trie
Algo Tree
Algo-Tree is a collection of Algorithms and data structures which are fundamentals to efficient code and good software design. Creating and designing excellent algorithms is required for being an exemplary programmer. It contains solutions in various languages such as C++, Python and Java.
Stars: ✭ 166 (+219.23%)
Mutual labels:  trie
Buckets Swift
Swift Collection Data Structures Library
Stars: ✭ 106 (+103.85%)
Mutual labels:  trie
Gse
Go efficient multilingual NLP and text segmentation; support english, chinese, japanese and other. Go 高性能多语言 NLP 和分词
Stars: ✭ 1,695 (+3159.62%)
Mutual labels:  trie
Opends
Template Library of Data Structures in C++17
Stars: ✭ 151 (+190.38%)
Mutual labels:  trie
Tongrams
A C++ library providing fast language model queries in compressed space.
Stars: ✭ 88 (+69.23%)
Mutual labels:  trie
Opencc4j
🇨🇳Open Chinese Convert is an opensource project for conversion between Traditional Chinese and Simplified Chinese.(java 中文繁简体转换)
Stars: ✭ 187 (+259.62%)
Mutual labels:  trie
Adaptive Radix Tree
A fast and space efficient Radix tree in Java
Stars: ✭ 76 (+46.15%)
Mutual labels:  trie
Trie4j
PATRICIA, Double Array, LOUDS Trie implementations for Java
Stars: ✭ 139 (+167.31%)
Mutual labels:  trie
xcdat
Fast compressed trie dictionary library
Stars: ✭ 51 (-1.92%)
Mutual labels:  trie
Patricia
Garbage collector-sensitive patricia tree for IP/CIDR tagging
Stars: ✭ 194 (+273.08%)
Mutual labels:  trie
Router
⚡️ A lightning fast HTTP router
Stars: ✭ 158 (+203.85%)
Mutual labels:  trie

goblin

Mentioned in Awesome Go GitHub release CircleCI Go Report Card codecov GitHub license Go Reference Sourcegraph

A golang http router based on trie tree.

Features

  • Support Go1.20 >= 1.16
  • Easy to use
  • Lightweight
  • Fully compatible with net/http
  • No external dependencies
  • Support custom error handler
  • Support default OPTIONS handler
  • Support method-based routing
  • Support variables in URL paths
  • Support regexp route patterns
  • Support middlewares

Install

go get -u github.com/bmf-san/goblin

Usage

Method-based routing

Goblin supports method-based routing.

GET/POST/PUT/PATCH/DELETE/OPTIONS

You can define routing as follows.

r := goblin.NewRouter()

r.Methods(http.MethodGet).Handler(`/`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "/")
}))

r.Methods(http.MethodGet, http.MethodPost).Handler(`/methods`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodGet {
        fmt.Fprintf(w, "GET")
    }
    if r.Method == http.MethodPost {
        fmt.Fprintf(w, "POST")
    }
}))

http.ListenAndServe(":9999", r)

Variables in URL paths

goblin supports variabled in URL paths.

r := goblin.NewRouter()

r.Methods(http.MethodGet).Handler(`/foo/:id`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    id := goblin.GetParam(r.Context(), "id")
    fmt.Fprintf(w, "/foo/%v", id)
}))

r.Methods(http.MethodGet).Handler(`/foo/:name`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    name := goblin.GetParam(r.Context(), "name")
    fmt.Fprintf(w, "/foo/%v", name)
}))

http.ListenAndServe(":9999", r)

If you use the named parameters without regular expression as in the above case, it is internally interpreted as a wildcard ((.+)) regular expression.

So :id is substantially defined as :id[(.+)] internaly.

Regexp route patterns

goblin support regexp route patterns.

:paramName[pattern]

r.Methods(http.MethodGet).Handler(`/foo/:id[^\d+$]`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    id := goblin.GetParam(r.Context(), "id")
    fmt.Fprintf(w, "/foo/%v", id)
}))

Matching priority

A routing pattern matching priority depends on an order of routing definition.

The one defined earlier takes precedence over the one defined later.

r := goblin.NewRouter()

r.Methods(http.MethodGet).Handler(`/foo/:id`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, `/foo/:id`)
}))
r.Methods(http.MethodGet).Handler(`/foo/:id[^\d+$]`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, `/foo/:id[^\d+$]`)
}))
r.Methods(http.MethodGet).Handler(`/foo/:id[^\D+$]`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, `/foo/:id[^\D+$]`)
}))

http.ListenAndServe(":9999", r)

In the above case, when accessing /foo/1, it matches the routing defined first.

So it doesn't match the 2nd and 3rd defined routings.

Custom error handler

goblin supports custom error handler.

You can be able to set your customized error handler.

func customMethodNotFound() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "customMethodNotFound")
	})
}

func customMethodAllowed() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "customMethodNotAllowed")
	})
}

r := goblin.NewRouter()
r.NotFoundHandler = customMethodNotFound()
r.MethodNotAllowedHandler = customMethodAllowed()

http.ListenAndServe(":9999", r)

Default OPTIONS handler

goblin supports default OPTIONS handler.

You can be able to set your default handler for OPTIONS http method.

func DefaultOPTIONSHandler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusNoContent)
	})
}

r := goblin.NewRouter()
r.DefaultOPTIONSHandler = DefaultOPTIONSHandler()

http.ListenAndServe(":9999", r)

Middlewares

goblin supports middlewares.

You can be able to set one or more middlewares.

There is no problem even if you do not set the middleware.

func global(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "global: before\n")
		next.ServeHTTP(w, r)
		fmt.Fprintf(w, "global: after\n")
	})
}

func first(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "first: before\n")
		next.ServeHTTP(w, r)
		fmt.Fprintf(w, "first: after\n")
	})
}

func second(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "second: before\n")
		next.ServeHTTP(w, r)
		fmt.Fprintf(w, "second: after\n")
	})
}

func third(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "third: before\n")
		next.ServeHTTP(w, r)
		fmt.Fprintf(w, "third: after\n")
	})
}

r := goblin.NewRouter()

r.UseGlobal(global)
r.Methods(http.MethodGet).Handler(`/globalmiddleware`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "/globalmiddleware\n")
}))
r.Methods(http.MethodGet).Use(first).Handler(`/middleware`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "middleware\n")
}))
r.Methods(http.MethodGet).Use(second, third).Handler(`/middlewares`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "middlewares\n")
}))

http.ListenAndServe(":9999", r)

Accessing /globalmiddleware will produce ouput similar to the following:

global: before
/globalmiddleware
global: after

In the above case, accessing /middleware will produce ouput similar to the following:

global: before
first: before
middleware
first: after
global: after

Accessing /middlewares will produce ouput similar to the following:

global: before
second: before
third: before
middlewares
third: after
second: after
global: after

Examples

See _examples.

Wiki

See Wiki.

Benchmark tests

Interested in a comparison with other HTTP routers? Please take a look here.

bmf-san/go-router-benchmark

Contribution

We are always accepting issues, pull requests, and other requests and questions.

We look forward to your contribution!

License

This project is licensed under the terms of the MIT license.

Author

bmf - A Web Developer in Japan.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].