神刀安全网

Lion: A fast HTTP router with middleware support for building modern scalable modular REST …

Lion Lion: A fast HTTP router with middleware support for building modern scalable modular REST ... Lion: A fast HTTP router with middleware support for building modern scalable modular REST ... Lion: A fast HTTP router with middleware support for building modern scalable modular REST ...

Lion is a fast HTTP router for Go with support for middlewares for building modern scalable modular REST APIs.

Lion: A fast HTTP router with middleware support for building modern scalable modular REST ...

Features

  • Context-Aware : Lion uses the de-facto standard net/Context for storing route params and sharing variables between middlewares and HTTP handlers. It could be integrated in thestandard library for Go 1.7 in 2016.
  • Modular : You can define your own modules to easily build a scalable architecture
  • REST friendly : You can define modules to groups http resources together.
  • Zero allocations : Lion generates zero garbage.

Table of contents

Install/Update

$ go get -u github.com/celrenheit/lion

Hello World

package main  import (     "fmt"     "net/http"      "github.com/celrenheit/lion"     "golang.org/x/net/context" )  func Home(c context.Context, w http.ResponseWriter, r *http.Request) {     fmt.Fprintf(w, "Home") }  func Hello(c context.Context, w http.ResponseWriter, r *http.Request) {     name := lion.Param(c, "name")     fmt.Fprintf(w, "Hello "+name) }  func main() {     l := lion.Classic()     l.GetFunc("/", Home)     l.GetFunc("/hello/:name", Hello)     l.Run() }

Try it yourself by running the following command from the current directory:

$ go run examples/hello/hello.go

Getting started with modules and resources

We are going to build a sample products listing REST api (without database handling to keep it simple):

func main() {     l := lion.Classic()     api := l.Group("/api")     api.Module(Products{})     l.Run() }  // Products module is accessible at url: /api/products // It handles getting a list of products or creating a new product type Products struct{}  func (p Products) Base() string {     return "/products" }  func (p Products) Get(c context.Context, w http.ResponseWriter, r *http.Request) {     fmt.Fprintf(w, "Fetching all products") }  func (p Products) Post(c context.Context, w http.ResponseWriter, r *http.Request) {     fmt.Fprintf(w, "Creating a new product") }  func (p Products) Routes(r *lion.Router) {     // Defining a resource for getting, editing and deleting a single product     r.Resource("/:id", OneProduct{}) }  // OneProduct resource is accessible at url: /api/products/:id // It handles getting, editing and deleting a single product type OneProduct struct{}  func (p OneProduct) Get(c context.Context, w http.ResponseWriter, r *http.Request) {     id := lion.Param(c, "id")     fmt.Fprintf(w, "Getting product: %s", id) }  func (p OneProduct) Put(c context.Context, w http.ResponseWriter, r *http.Request) {     id := lion.Param(c, "id")     fmt.Fprintf(w, "Updating article: %s", id) }  func (p OneProduct) Delete(c context.Context, w http.ResponseWriter, r *http.Request) {     id := lion.Param(c, "id")     fmt.Fprintf(w, "Deleting article: %s", id) }

Try it yourself. Run:

$ go run examples/modular-hello/modular-hello.go

Open your web browser to http://localhost:3000/api/products or http://localhost:3000/api/products/123 . You should see " Fetching all products " or " Getting product: 123 ".

Handlers

Handlers should implement the Handler interface:

type Handler interface {     ServeHTTPC(context.Context, http.ResponseWriter, *http.Request) }

Using Handlers

l.Get("/get", get) l.Post("/post", post) l.Put("/put", put) l.Delete("/delete", delete)

Using HandlerFuncs

HandlerFuncs shoud have this function signature:

func handlerFunc(c context.Context, w http.ResponseWriter, r *http.Request)  {   fmt.Fprintf(w, "Hi!") }  l.GetFunc("/get", handlerFunc) l.PostFunc("/post", handlerFunc) l.PutFunc("/put", handlerFunc) l.DeleteFunc("/delete", handlerFunc)

Using native http.Handler

type nativehandler struct {}  func (_ nativehandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {  }  l.GetH("/somepath", nativehandler{}) l.PostH("/somepath", nativehandler{}) l.PutH("/somepath", nativehandler{}) l.DeleteH("/somepath", nativehandler{})

Using native http.Handler using lion.Wrap()

Note : using native http handler you cannot access url params.

func main() {     l := lion.New()     l.Get("/somepath", lion.Wrap(nativehandler{})) }

Using native http.Handler using lion.WrapFunc()

func getHandlerFunc(w http.ResponseWriter, r *http.Request) {  }  func main() {     l := lion.New()     l.Get("/somepath", lion.WrapFunc(getHandlerFunc)) }

Middlewares

Middlewares should implement the Middleware interface:

type Middleware interface {     ServeNext(Handler) Handler }

The ServeNext function accepts a Handler and returns a Handler.

You can also use MiddlewareFuncs. For example:

func middlewareFunc(next Handler) Handler  {     return next }

You can also use Negroni middlewares by registering them using:

l := lion.New() l.UseNegroni(negroni.NewRecovery()) l.Run()

Resources

You can define a resource to represent a REST, CRUD api resource. You define global middlewares using Uses() method. For defining custom middlewares for each http method, you have to create a function which name is composed of the http method suffixed by "Middlewares". For example, if you want to define middlewares for the Get method you will have to create a method called: GetMiddlewares() .

A resource is defined by the following methods. Everything is optional :

// Global middlewares for the resource (Optional) Uses() Middlewares  // Middlewares for the http methods (Optional) GetMiddlewares() Middlewares PostMiddlewares() Middlewares PutMiddlewares() Middlewares DeleteMiddlewares() Middlewares   // HandlerFuncs for each HTTP Methods (Optional) Get(c context.Context, w http.ResponseWriter, r *http.Request) Post(c context.Context, w http.ResponseWriter, r *http.Request) Put(c context.Context, w http.ResponseWriter, r *http.Request) Delete(c context.Context, w http.ResponseWriter, r *http.Request)

Example:

package main  type todolist struct{}  func (t todolist) Uses() lion.Middlewares {     return lion.Middlewares{lion.NewLogger()} }  func (t todolist) Get(c context.Context, w http.ResponseWriter, r *http.Request) {     fmt.Fprintf(w, "getting todos") }  func main() {     l := lion.New()     l.Resource("/todos", todolist{})     l.Run() }

Modules

Modules are a way to modularize an api which can then define submodules, subresources and custom routes. A module is defined by the following methods:

// Required: Base url pattern of the module Base() string  // Routes accepts a Router instance. This method is used to define the routes of this module. // Each routes defined are relative to the Base() url pattern Routes(*Router)  // Optional: Requires named middlewares. Refer to Named Middlewares section Requires() []string
package main  type api struct{}  // Required: Base url func (t api) Base() string { return "/api" }  // Required: Here you can declare sub-resources, submodules and custom routes. func (t api) Routes(r *lion.Router) {     r.Module(v1{})     r.Get("/custom", t.CustomRoute) }  // Optional: Attach Get method to this Module. // ====> A Module is also a Resource. func (t api) Get(c context.Context, w http.ResponseWriter, r *http.Request) {     fmt.Fprintf(w, "This also a resource accessible at http://localhost:3000/api") }  // Optional: Defining custom routes func (t api) CustomRoute(c context.Context, w http.ResponseWriter, r *http.Request) {     fmt.Fprintf(w, "This a custom route for this module http://localhost:3000/api/") }  func main() {     l := lion.New()     // Registering the module     l.Module(api{})     l.Run() }

Examples

Using GET, POST, PUT, DELETE http methods

l := lion.Classic()  // Using Handlers l.Get("/get", get) l.Post("/post", post) l.Put("/put", put) l.Delete("/delete", delete)  // Using functions l.GetFunc("/get", getFunc) l.PostFunc("/post", postFunc) l.PutFunc("/put", putFunc) l.DeleteFunc("/delete", deleteFunc)  l.Run()

Using middlewares

func main() {     l := lion.Classic()      // Using middleware     l.Use(lion.NewLogger())      // Using middleware functions     l.UseFunc(someMiddlewareFunc)      l.GetFunc("/hello/:name", Hello)      l.Run() }

Group routes by a base path

l := lion.Classic() api := l.Group("/api")  v1 := l.Group("/v1") v1.GetFunc("/somepath", gettingFromV1)  v2 := l.Group("/v2") v2.GetFunc("/somepath", gettingFromV2)  l.Run()

Mouting a router into a base path

l := lion.Classic()  sub := lion.New() sub.GetFunc("/somepath", getting)   l.Mount("/api", sub)

Default middlewares

lion.Classic() creates a router with default middlewares (Recovery, RealIP, Logger, Static). If you wish to create a blank router without any middlewares you can use lion.New() .

func main()  {     // This a no middlewares registered     l := lion.New()     l.Use(lion.NewLogger())      l.GetFunc("/hello/:name", Hello)      l.Run() }

Custom Middlewares

Custom middlewares should implement the Middleware interface:

type Middleware interface {     ServeNext(Handler) Handler }

You can also make MiddlewareFuncs to use using .UseFunc() method. It has to accept a Handler and return a Handler:

func(next Handler) Handler

Custom Logger example

type logger struct{}  func (*logger) ServeNext(next lion.Handler) lion.Handler {     return lion.HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {         start := time.Now()          next.ServeHTTPC(c, w, r)          fmt.Printf("Served %s in %s/n", r.URL.Path, time.Since(start))     }) }

Then in the main function you can use the middleware using:

l := lion.New()  l.Use(&logger{}) l.GetFunc("/hello/:name", Hello) l.Run()

License

https://github.com/celrenheit/lion/blob/master/LICENSE

Todo

  • Better static file handling
  • More documentation

Credits

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Lion: A fast HTTP router with middleware support for building modern scalable modular REST …

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮