Documentation
¶
Overview ¶
Package gorouter provide request router with middleware
Router ¶
The router determines how to handle that request. GoRouter uses a routing tree. Once one branch of the tree matches, only routes inside that branch are considered, not any routes after that branch. When instantiating router, the root node of tree is created.
Route types ¶
- Static `/hello` (will match requests matching given route)
- Named `/{name}` (will match requests matching given route scheme)
- Regexp `/{name:[a-z]+}` (will match requests matching given route scheme and its regexp)
Wildcards ¶
The values of *named parameter* or *regexp parameters* are accessible via *request context* `params, ok := gorouter.FromContext(req.Context())`. You can get the value of a parameter either by its index in the slice, or by using the `params.Value(name)` method: `:name` or `/{name:[a-z]+}` can be retrieved by `params.Value("name")`.
Defining Routes ¶
A full route definition contain up to three parts:
1. HTTP method under which route will be available
2. The URL path route. This is matched against the URL passed to the router, and can contain named wildcard placeholders *(e.g. {placeholder})* to match dynamic parts in the URL.
3. `http.HandleFunc`, which tells the router to handle matched requests to the router with handler.
Take the following example:
router.GET("/hello/{name:r([a-z]+)go}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
params, _ := gorouter.FromContext(r.Context())
fmt.Fprintf(w, "hello, %s!\n", params.Value("name"))
}))
In this case, the route is matched by `/hello/rxxxxxgo` for example, because the `:name` wildcard matches the regular expression wildcard given (`r([a-z]+)go`). However, `/hello/foo` does not match, because "foo" fails the *name* wildcard. When using wildcards, these are returned in the map from request context. The part of the path that the wildcard matched (e.g. *rxxxxxgo*) is used as value.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/vardius/gorouter"
)
func main() {
hello := func(w http.ResponseWriter, r *http.Request) {
params, _ := gorouter.FromContext(r.Context())
fmt.Printf("Hello, %s!\n", params.Value("name"))
}
router := gorouter.New()
router.GET("/hello/{name}", http.HandlerFunc(hello))
// Normally you would call ListenAndServe starting an HTTP server
// with a given address and router as a handler
// log.Fatal(http.ListenAndServe(":8080", router))
// but for this example we will mock request
w := httptest.NewRecorder()
req, err := http.NewRequest(gorouter.GET, "/hello/guest", nil)
if err != nil {
return
}
router.ServeHTTP(w, req)
}
Output: Hello, guest!
Index ¶
Examples ¶
Constants ¶
const ( GET = "GET" POST = "POST" PUT = "PUT" DELETE = "DELETE" PATCH = "PATCH" OPTIONS = "OPTIONS" HEAD = "HEAD" CONNECT = "CONNECT" TRACE = "TRACE" )
HTTP methods constants
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type MiddlewareFunc ¶
MiddlewareFunc is a middleware function type. It accepts as a parameter http.Handler and returns http.Handler as well Long story - short: it is a http.Handler wrapper
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/vardius/gorouter"
)
func main() {
// Global middleware example
// applies to all routes
hello := func(w http.ResponseWriter, r *http.Request) {
params, _ := gorouter.FromContext(r.Context())
fmt.Printf("Hello, %s!\n", params.Value("name"))
}
logger := func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("[%s] %q\n", r.Method, r.URL.String())
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
// apply middlewares to all routes
// can pass as many as you want
router := gorouter.New(logger)
router.GET("/hello/{name}", http.HandlerFunc(hello))
// Normally you would call ListenAndServe starting an HTTP server
// with a given address and router as a handler
// log.Fatal(http.ListenAndServe(":8080", router))
// but for this example we will mock request
w := httptest.NewRecorder()
req, err := http.NewRequest(gorouter.GET, "/hello/guest", nil)
if err != nil {
return
}
router.ServeHTTP(w, req)
}
Output: [GET] "/hello/guest" Hello, guest!
Example (Second) ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/vardius/gorouter"
)
func main() {
// Route level middleware example
// applies to route and its lower tree
hello := func(w http.ResponseWriter, r *http.Request) {
params, _ := gorouter.FromContext(r.Context())
fmt.Printf("Hello, %s!\n", params.Value("name"))
}
logger := func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("[%s] %q\n", r.Method, r.URL.String())
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
router := gorouter.New()
router.GET("/hello/{name}", http.HandlerFunc(hello))
// apply middlewares to route and all it children
// can pass as many as you want
router.USE("GET", "/hello/{name}", logger)
// Normally you would call ListenAndServe starting an HTTP server
// with a given address and router as a handler
// log.Fatal(http.ListenAndServe(":8080", router))
// but for this example we will mock request
w := httptest.NewRecorder()
req, err := http.NewRequest(gorouter.GET, "/hello/guest", nil)
if err != nil {
return
}
router.ServeHTTP(w, req)
}
Output: [GET] "/hello/guest" Hello, guest!
Example (Third) ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/vardius/gorouter"
)
func main() {
// Http method middleware example
// applies to all routes under this method
hello := func(w http.ResponseWriter, r *http.Request) {
params, _ := gorouter.FromContext(r.Context())
fmt.Printf("Hello, %s!\n", params.Value("name"))
}
logger := func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("[%s] %q\n", r.Method, r.URL.String())
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
router := gorouter.New()
router.GET("/hello/{name}", http.HandlerFunc(hello))
// apply middlewares to all routes with GET method
// can pass as many as you want
router.USE("GET", "", logger)
// Normally you would call ListenAndServe starting an HTTP server
// with a given address and router as a handler
// log.Fatal(http.ListenAndServe(":8080", router))
// but for this example we will mock request
w := httptest.NewRecorder()
req, err := http.NewRequest(gorouter.GET, "/hello/guest", nil)
if err != nil {
return
}
router.ServeHTTP(w, req)
}
Output: [GET] "/hello/guest" Hello, guest!
type Params ¶
type Params []Param
Params slice returned from request context
func FromContext ¶
FromContext extracts the request Params ctx, if present.
type Router ¶
type Router interface {
// POST adds http.Handler as router handler
// under POST method and given patter
POST(pattern string, handler http.Handler)
// GET adds http.Handler as router handler
// under GET method and given patter
GET(pattern string, handler http.Handler)
// PUT adds http.Handler as router handler
// under PUT method and given patter
PUT(pattern string, handler http.Handler)
// DELETE adds http.Handler as router handler
// under DELETE method and given patter
DELETE(pattern string, handler http.Handler)
// PATCH adds http.Handler as router handler
// under PATCH method and given patter
PATCH(pattern string, handler http.Handler)
// OPTIONS adds http.Handler as router handler
// under OPTIONS method and given patter
OPTIONS(pattern string, handler http.Handler)
// HEAD adds http.Handler as router handler
// under HEAD method and given patter
HEAD(pattern string, handler http.Handler)
// CONNECT adds http.Handler as router handler
// under CONNECT method and given patter
CONNECT(pattern string, handler http.Handler)
// TRACE adds http.Handler as router handler
// under TRACE method and given patter
TRACE(pattern string, handler http.Handler)
// USE adds middleware functions ([]MiddlewareFunc)
// to whole router branch under given method and patter
USE(method, pattern string, fs ...MiddlewareFunc)
// Handle adds http.Handler as router handler
// under given method and patter
Handle(method, pattern string, handler http.Handler)
// HandleFunc adds http.HandlerFunc as router handler
// under given method and patter
HandleFunc(method, pattern string, handler http.HandlerFunc)
// Mount another handler as a subrouter
Mount(pattern string, handler http.Handler)
// ServeHTTP dispatches the request to the route handler
// whose pattern matches the request URL
ServeHTTP(http.ResponseWriter, *http.Request)
// ServeFile replies to the request with the
// contents of the named file or directory.
ServeFiles(root http.FileSystem, path string, strip bool)
// NotFound replies to the request with the
// 404 Error code
NotFound(http.Handler)
// NotFound replies to the request with the
// 405 Error code
NotAllowed(http.Handler)
}
Router is a micro framwework, HTTP request router, multiplexer, mux
Example (Mount) ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/vardius/gorouter"
)
func main() {
hello := func(w http.ResponseWriter, r *http.Request) {
params, _ := gorouter.FromContext(r.Context())
fmt.Printf("Hello, %s!\n", params.Value("name"))
}
subrouter := gorouter.New()
subrouter.GET("/{name}", http.HandlerFunc(hello))
router := gorouter.New()
router.Mount("/hello", subrouter)
// Normally you would call ListenAndServe starting an HTTP server
// with a given address and router as a handler
// log.Fatal(http.ListenAndServe(":8080", router))
// but for this example we will mock request
w := httptest.NewRecorder()
req, err := http.NewRequest(gorouter.GET, "/hello/guest", nil)
if err != nil {
return
}
router.ServeHTTP(w, req)
}
Output: Hello, guest!
Example (Mount_second) ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/vardius/gorouter"
)
func main() {
subrouter := http.NewServeMux()
subrouter.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
fmt.Println("Hello, guest!")
})
router := gorouter.New()
router.Mount("/hello", subrouter)
// Normally you would call ListenAndServe starting an HTTP server
// with a given address and router as a handler
// log.Fatal(http.ListenAndServe(":8080", router))
// but for this example we will mock request
w := httptest.NewRecorder()
req, err := http.NewRequest(gorouter.GET, "/hello/guest", nil)
if err != nil {
return
}
router.ServeHTTP(w, req)
}
Output: Hello, guest!