Categorygithub.com/vanng822/r2router
modulepackage
0.0.0-20150523112421-1023140a4f30
Repository: https://github.com/vanng822/r2router.git
Documentation: pkg.go.dev

# README

r2router

A simple router which supports named parameter. Idea for API or backend without any static content. This package contains 2 router types. Router is for pure routing and Seefor supports middleware stacks.

Middlewares are divided into 2 groups, one runs before routing and one runs after routing. Before middleware is thought for serving static, logging, recovery from panic and so on. After middleware is thought for pre-processing data before executing endpoint handler. One can do this by using AppSet method on Params. This mean that Before middlewares are always executed, except when a middleware cancels and does not call next(), meanwhile After middlewares are only call if a route is hit. Each After middleware also has a chance to response and stop calling next().

By default there is no middleware added. See list bellow for suitable middlewares, including recovery which has been moved from this repos.

One interesting feature this package has is measurement of endpoint performance. The timer measures how long time it takes average for each route. The timer itself is a http.Handler so one can use it to serve these statistics locally (see example/timer.go).

There is also a route manager for registering all your routes. This can use for setting up endpoints and also use for building urls.

GoDoc Build Status Go Walker

Example

Router

package main

import (
	"github.com/vanng822/r2router"
	"net/http"
)

func main() {
	router := r2router.NewRouter()
	router.Get("/users/:user", func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
		w.Write([]byte(p.Get("user")))
	})
	http.ListenAndServe(":8080", router)
}

Demo: http://premailer.isgoodness.com/

If your routes don't contain named params and you have existing http.HandlerFunc then you can wrap as bellow


package main

import (
	"fmt"
	"github.com/vanng822/r2router"
	"net/http"
)

// Wrapper for http.HandlerFunc, similar can be done for http.Handler
func RouteHandlerFunc(next http.HandlerFunc) r2router.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, _ r2router.Params) {
		next(w, r)
	}
}

func main() {
	seefor := r2router.NewSeeforRouter()
	seefor.Get("/hello/world", RouteHandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Hello world!")
	}))
	http.ListenAndServe("127.0.0.1:8080", seefor)
}

Measuring endpoint performance using Timer

package main

import (
	"github.com/vanng822/r2router"
	"net/http"
)

func main() {
	router := r2router.NewSeeforRouter()
	router.Group("/hello", func(r *r2router.GroupRouter) {
		r.Get("/kitty", func(w http.ResponseWriter, r *http.Request, _ r2router.Params) {
			w.Write([]byte("Mau"))
		})

		r.Get("/duck", func(w http.ResponseWriter, r *http.Request, _ r2router.Params) {
			w.Write([]byte("Crispy"))
		})

		r.Get("/:name", func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
			w.Write([]byte(p.Get("name")))
		})
	})
	timer := router.UseTimer(nil)
	
	go http.ListenAndServe("127.0.0.1:8080", router)
	http.ListenAndServe("127.0.0.1:8081", timer)
}

Demo: http://premailer.isgoodness.com/timers

Middleware

package main

import (
	"fmt"
	"github.com/vanng822/r2router"
	"net/http"
	"log"
	"time"
)

func main() {
	seefor := r2router.NewSeeforRouter()
	// measure time middleware
	seefor.Before(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			start := time.Now()
			next.ServeHTTP(w, r)
			log.Printf("took: %s", time.Now().Sub(start))
		})
	})
	// set label "say"
	seefor.After(func(next r2router.Handler) r2router.Handler {
		return r2router.HandlerFunc(func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
			p.AppSet("say", "Hello")
			next.ServeHTTP(w, r, p)
		})
	})

	seefor.After(r2router.Wrap(func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
		p.AppSet("goodbye", "Bye bye")
	}))

	seefor.Get("/hello/:name", func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
		fmt.Fprintf(w, "%s %s!\n%s", p.AppGet("say").(string), p.Get("name"), p.AppGet("goodbye"))
	})
	
	http.ListenAndServe(":8080", seefor)
}

If you want to add middlewares for a specific route then you should create your own wrapper. This way you will have full control over your middlewares. You could do something like bellow


package main

import (
	"fmt"
	"github.com/vanng822/r2router"
	"net/http"
)

// Your own route middle wrapper
func RouteMiddleware(next r2router.HandlerFunc) r2router.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
		p.AppSet("say", "Hello")
		next(w, r, p)
	}
}

func main() {
	seefor := r2router.NewSeeforRouter()
	seefor.Get("/hello/:name", RouteMiddleware(func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
		fmt.Fprintf(w, "%s %s!", p.AppGet("say").(string), p.Get("name"))
	}))
	http.ListenAndServe("127.0.0.1:8080", seefor)
}

Route manager

package main

import (
	"fmt"
	"github.com/vanng822/r2router"
	"net/http"
)

func main() {
	seefor := r2router.NewSeeforRouter()
	rmanager := r2router.NewRouteManager()
	// register and use it at the same time
	seefor.Get(rmanager.Add("hello::name", "/hello/:name"), func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
		fmt.Fprintf(w, "Hello %s!", p.Get("name"))
	})

	// Or register first elsewhere and get it later
	rmanager.Add("redirect::name", "/redirect/:name")

	seefor.Get(rmanager.PathFor("redirect::name"), func(w http.ResponseWriter, r *http.Request, p r2router.Params) {
		// Building url for routename "hello::name" and redirect
		http.Redirect(w, r, rmanager.UrlFor("hello::name", r2router.P{"name": []string{p.Get("name")}}), http.StatusFound)
	})

	http.ListenAndServe("127.0.0.1:8080", seefor)
}

Middlewares & Recommended packages

Middlewares

Panic recovery https://github.com/vanng822/recovery

Access log https://github.com/vanng822/accesslog

Basic auth https://github.com/goji/httpauth

CORS https://github.com/rs/cors

Quick security wins https://github.com/unrolled/secure

HMAC authentication https://github.com/auroratechnologies/vangoh

Static content https://github.com/hypebeast/gojistatic

Generic packages

Rendering https://github.com/unrolled/render

Session https://github.com/gorilla/sessions

HTTP request data binding & validation https://github.com/mholt/binding

# Packages

No description provided by the author

# Functions

NewGroupRouter return GroupRouter which is a helper to construct a group of endpoints, such example could be API-version or different methods for an endpoint You should always use router.Group instead of using this directly.
No description provided by the author
NewRouter return a new Router.
NewSeeforRouter for creating a new instance of Seefor router.
No description provided by the author
Wrap for wrapping a handler to After middleware Be aware that it will not be able to stop execution propagation That is it will continue to execute the next middleware/handler.
WrapBeforeHandler for wrapping a http.Handler to Before middleware.
WrapHandler for wrapping a http.Handler to After middleware.

# Constants

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
HTTP_METHOD_POST
No description provided by the author
No description provided by the author

# Structs

Statistic entry for one endpoint.
GroupRouter is a helper for grouping endpoints All methods are proxy of Router Suitable for grouping different methods of an endpoint.
No description provided by the author
Seefor is a subtype of Router.
Tot, Max, Min and Avg is time.Duration which mean in nanoseconds.
For generate statistics.
Keep track on routes performance.

# Interfaces

No description provided by the author
Params is for parameters that are matched from URL.
For managing route and getting url.

# Type aliases

After defines how a middleware should look like.
Before defines middleware interface.
HandlerFunc define interface handler.
Shortcut for map[string]interface{} Helpful to build data for json response.
Shortcut for map[string][]string.