bingo_router

package module
v0.0.0-...-236be48 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2018 License: Apache-2.0 Imports: 10 Imported by: 0

README

bingo-router

基于httprouter的路由模块

简介

这个包是为了自己的go web项目 Bingo 所开发的模块之一,负责核心路由功能,这里将其抽出来作为单独包, 可以轻松的在其他项目中使用,而无需依赖 Bingo 框架

特性:

  • 路由快速查找

  • 动态路由传参

  • 子路由支持(路由组)

  • 中间件支持

bingo-router 基于 httprouter , 性能强劲, httprouter 拥有的特性,bingo-router也有,并且参考 LaravelPipeline 功能,为 bingo-router 添加中间件支持,可以快速实现拦截器等常见功能

后续准备加入的功能

  • 会话管理

  • 路由跳转

  • 服务的平滑重启和关闭

  • 工具方法补充(e.g.封装json返回等方法)

  • 测试代码补充

安装

go get -u github.com/silsuer/bingo-router

bingo-router 使用 glide 管理依赖,如果遇到无法 go install 问题,请先安装 glide 后,去 $PATH/src/github.com/silsuer/bingo-router 目录下执行 glide install 命令安装依赖

使用

bingo-router 已内置在 [Bingo](https://github.com/silsuer/bingo) 框架中,开箱即用,对于第三方项目:

  1. 初始化路由器对象 router:
  	// 创建一个路由器
  	router := bingo_router.New()

路由器 Router 上挂载路由 Route,一个服务只能存在一个 Router,可存在多个Route,不要弄混

  1. 创建路由
  route := bingo_router.NewRoute().Get("/").Target(func(c *bingo_router.Context) {
  		fmt.Fprint(c.Writer,"hello! bingo-router!")
  	})

目前上下文对象context只是对 httprouter 中对象的一个简单封装,用法与 httprouter 完全一致:

  type Context struct {
  	Writer  http.ResponseWriter // 响应
  	Request *http.Request       // 请求
  	Params  Params              //参数
  }

NewRoute 方法将会返回一个路由指针,可以调用:

  • Get() 方法,设定为Get方法

  • Post() 方法,设定为Get方法

  • Patch() 方法,设定为Get方法

  • Put() 方法,设定为Get方法

  • Delete() 方法,设定为Get方法

  • Handle() 方法,设定为Get方法

  • Target() 方法,指定该路由所对应的方法

  • Middleware() 方法,设定一个将在其中设置的中间件

  • MiddlewareGroup() 方法,批量设置中间件

  • Prefix() 方法,设置路由前缀,该前缀将对该路由的所有子路由有效,对当前路由无效

  • Mount() 方法,设置子路由

  1. 将路由挂载到路由器中
  router.Mount(route)

路由器 Router

  1. 开启服务器
  http.ListenAndServe(":8080", r)
  1. 在浏览器中访问 http://localhost:8080, 可以看到输出 hello, bingo-router!

进阶

1. 使用中间件

使用 NewRoute() 方法之后将会获得一个 Route 对象指针,采用责任链模式,随意进行链式操作:


  r2 := bingo_router.NewRoute().Get("/test").Middleware(func(c *bingo_router.Context, next func(c *bingo_router.Context)) {
  	fmt.Fprint(c.Writer,"middleware")
  	next(c)
  }).Target(func(c *bingo_router.Context) {
  	fmt.Fprintln(c.Writer,"target")
  })

中间件是一种 MiddlewareHandle 类型的方法 func(c *Context, next func(c *Context))

Middleware 方法传入一个回调函数,该函数接受两个参数,第一个参数context 是上下文,是封装的http.ResponseWriter,*http.Requesthttprouter.Params

第二个参数是 next 方法,用来指定何时跳入下一个中间件,主要是用来实现前置中间件和后置中间件功能,当执行 next 方法后,将会跳入下一个中间件,直到所有中间件运行完毕后,才会继续执行下面的代码

例如,上面的r2的效果是输出:

  middleware
  target

如果将中间件中的next() 方法向上提一行的话:

    r2 := bingo_router.NewRoute().Get("/test").Middleware(func(c *bingo_router.Context, next func(c *bingo_router.Context)) {
          next(c)
          fmt.Fprint(c.Writer,"middleware")
      }).Target(func(c *bingo_router.Context) {
          fmt.Fprintln(c.Writer,"target")
      })

这样将会输出:

   target
   middleware

这样就可以实现后置中间件的效果了,可以做一些访问完控制器方法之后的后续工作

当然,如果不在中间件中调用 next() 方法,请求就将在这个中间件中终止。

2. 使用中间件组

Route 对象的 MiddlewareGroup() 方法可以实现批量注册中间件的功能,传入一个 MiddlwareHandle 的数组即可,不再赘述

3. 使用子路由和路由前缀

Laravel 中,我们经常会用到路由组的概念,可以方便的进行整体控制,在 bingo-router 中,我也实现了这样的功能,但是bingo-router中没有路由组的概念,可以使用子路由实现类似效果,

调用 Route 对象的 Mount 方法添加子路由:


  bingo_router.NewRoute().Prefix("/api").Middleware(MiddlewareFunction).Mount(func(b *bingo_router.Builder) {
  		b.NewRoute().Get("/mount").Target(func(c *bingo_router.Context) {
  			fmt.Fprint(c.Writer, "hello mount")
  		})

  		b.NewRoute().Get("/mount2").Target(func(c *bingo_router.Context) {
              			fmt.Fprint(c.Writer, "hello mount2")
          })
  	})

Prefix 方法,传入一个字符串,这个字符串将作用在所有子路由路径前,例如上面的代码,我们最终的访问路径就是 /api/mount/api/mount2

Mount 方法传入一个 Builder 指针,我们可以调用 Builder对象的 NewRoute() 方法为当前路由添加子路由,例如上面的代码,我们在访问 /api/mount/api/mount2时都会经过我们指定的MiddlewareFunction 中间件

这个包还没有完全开发完成,后续会继续补充,也会在这两天内内置到 Bingo 框架中

请大家多多关注主框架 Bingo , 欢迎 STAR 、 PR

Documentation

Overview

// +build go1.7

Index

Constants

View Source
const DELETE = "DELETE"
View Source
const GET = "GET"
View Source
const PATCH = "PATCH"
View Source
const POST = "POST"
View Source
const PUT = "PUT"

Variables

This section is empty.

Functions

func CleanPath

func CleanPath(p string) string

CleanPath is the URL version of path.Clean, it returns a canonical URL path for p, eliminating . and .. elements.

The following rules are applied iteratively until no further processing can be done:

  1. Replace multiple slashes with a single slash.
  2. Eliminate each . path name element (the current directory).
  3. Eliminate each inner .. path name element (the parent directory) along with the non-.. element that precedes it.
  4. Eliminate .. elements that begin a rooted path: that is, replace "/.." by "/" at the beginning of a path.

If the result of this process is an empty string, "/" is returned

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

路由的构建器

func (*Builder) NewRoute

func (b *Builder) NewRoute() *Route

type Context

type Context struct {
	Writer  http.ResponseWriter // 响应
	Request *http.Request       // 请求
	Params  Params              //参数

}

上下文结构体

func (*Context) File

func (*Context) Get

func (c *Context) Get(key string) string

获取get表单的参数

func (*Context) GetWithDefault

func (c *Context) GetWithDefault(key, def string) string

func (*Context) Post

func (c *Context) Post(key string) string

获取post表单的参数

func (*Context) PostWithDefault

func (c *Context) PostWithDefault(key, def string) string

func (*Context) Redirect

func (c *Context) Redirect(path string)

重定向,传入路径和状态码

func (*Context) ResponseJson

func (c *Context) ResponseJson(data interface{})

输出json

func (*Context) String

func (c *Context) String(data string)

输出字符串

type Controller

type Controller struct {
}

默认基本控制器

func (*Controller) Create

func (cc *Controller) Create(c *Context)

func (*Controller) Destroy

func (cc *Controller) Destroy(c *Context)

func (*Controller) Edit

func (cc *Controller) Edit(c *Context)

func (*Controller) Index

func (cc *Controller) Index(c *Context)

func (*Controller) Show

func (cc *Controller) Show(c *Context)

func (*Controller) Store

func (cc *Controller) Store(c *Context)

func (*Controller) Update

func (cc *Controller) Update(c *Context)

type Handle

type Handle func(http.ResponseWriter, *http.Request, Params)

type IController

type IController interface {
	Index(c *Context)   // 对应 get : path方法
	Create(c *Context)  // 对应 get : path/create 方法
	Store(c *Context)   // 对应 post : path 方法
	Update(c *Context)  // 对应put/patch : path/:id   方法
	Edit(c *Context)    // 对应get : path/:id/edit
	Show(c *Context)    // 对应 get: route/:id
	Destroy(c *Context) // 对应 delete: route/:id
}

控制器接口

type MiddlewareHandle

type MiddlewareHandle func(c *Context, next func(c *Context))

type Output

type Output struct {
	Method     string
	URI        string
	Name       string
	Action     string
	Middleware string
}

type Param

type Param struct {
	Key   string
	Value string
}

type Params

type Params []Param

func (Params) ByName

func (ps Params) ByName(name string) string

type Pipeline

type Pipeline struct {
	// contains filtered or unexported fields
}

func (*Pipeline) Exec

func (p *Pipeline) Exec()

func (*Pipeline) Send

func (p *Pipeline) Send(context *Context) *Pipeline

func (*Pipeline) Then

func (p *Pipeline) Then(then func(context *Context))

这里是路由的最后一站

func (*Pipeline) Through

func (p *Pipeline) Through(middlewares []MiddlewareHandle) *Pipeline

type Route

type Route struct {
	// contains filtered or unexported fields
}

路由

func NewRoute

func NewRoute() *Route

func (*Route) Delete

func (r *Route) Delete(path string) *Route

添加路由时需要,设置为delete方法

func (*Route) Get

func (r *Route) Get(path string) *Route

添加路由时需要,设置为Get方法

func (*Route) Middleware

func (r *Route) Middleware(h MiddlewareHandle) *Route

func (*Route) MiddlewareGroup

func (r *Route) MiddlewareGroup(hg []MiddlewareHandle) *Route

func (*Route) Mount

func (r *Route) Mount(rr func(b *Builder)) *Route

挂载子路由,这里只是将回调中的路由放入

func (*Route) Name

func (r *Route) Name(name string) *Route

func (*Route) Patch

func (r *Route) Patch(path string) *Route

添加路由时需要,设置为patch方法

func (*Route) Post

func (r *Route) Post(path string) *Route

添加路由时需要,设置为Post方法

func (*Route) Prefix

func (r *Route) Prefix(prefix string) *Route

路由前缀,该前缀仅会对子路由有效,对当前路由无效

func (*Route) Put

func (r *Route) Put(path string) *Route

添加路由时需要,设置为put方法

func (*Route) Request

func (r *Route) Request(method string, path string, target TargetHandle) *Route

func (*Route) Resource

func (r *Route) Resource(path string, controller IController) *Route

传入一个控制器,自动构建多个路由

func (*Route) Target

func (r *Route) Target(target TargetHandle) *Route

这里传入一个回调

type Router

type Router struct {
	RedirectTrailingSlash bool

	RedirectFixedPath bool

	HandleMethodNotAllowed bool

	HandleOPTIONS bool

	NotFound http.HandlerFunc

	MethodNotAllowed http.Handler

	PanicHandler func(http.ResponseWriter, *http.Request, interface{})
	// contains filtered or unexported fields
}

func New

func New() *Router

func (*Router) DELETE

func (r *Router) DELETE(path string, route *Route)

DELETE is a shortcut for router.Handle("DELETE", path, handle)

func (*Router) GET

func (r *Router) GET(path string, route *Route)

GET is a shortcut for router.Handle("GET", path, handle)

func (*Router) HEAD

func (r *Router) HEAD(path string, route *Route)

HEAD is a shortcut for router.Handle("HEAD", path, handle)

func (*Router) Handle

func (r *Router) Handle(method, path string, route *Route)

Handle registers a new request handle with the given path and method.

For GET, POST, PUT, PATCH and DELETE requests the respective shortcut functions can be used.

This function is intended for bulk loading and to allow the usage of less frequently used, non-standardized or custom methods (e.g. for internal communication with a proxy).

func (*Router) Handler

func (r *Router) Handler(method, path string, handler http.Handler)

func (*Router) HandlerFunc

func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc)

HandlerFunc is an adapter which allows the usage of an http.HandlerFunc as a request handle.

func (*Router) Lookup

func (r *Router) Lookup(method, path string) (Route, Params, bool)

Lookup allows the manual lookup of a method + path combo. This is e.g. useful to build a framework around this router. If the path was found, it returns the handle function and the path parameter values. Otherwise the third return value indicates whether a redirection to the same path with an extra / without the trailing slash should be performed.

func (*Router) Mount

func (r *Router) Mount(routes ...*Route)

func (*Router) MountRoute

func (r *Router) MountRoute(route *Route)

向其中挂载路由

func (*Router) OPTIONS

func (r *Router) OPTIONS(path string, route *Route)

OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle)

func (*Router) PATCH

func (r *Router) PATCH(path string, route *Route)

PATCH is a shortcut for router.Handle("PATCH", path, handle)

func (*Router) POST

func (r *Router) POST(path string, route *Route)

POST is a shortcut for router.Handle("POST", path, handle)

func (*Router) PUT

func (r *Router) PUT(path string, route *Route)

PUT is a shortcut for router.Handle("PUT", path, handle)

func (*Router) PrintRoutes

func (r *Router) PrintRoutes()

在控制台中打印所有路由

func (*Router) ServeFiles

func (r *Router) ServeFiles(path string, root http.FileSystem)

ServeFiles serves files from the given file system root. The path must end with "/*filepath", files are then served from the local path /defined/root/dir/*filepath. For example if root is "/etc" and *filepath is "passwd", the local file "/etc/passwd" would be served. Internally a http.FileServer is used, therefore http.NotFound is used instead of the Router's NotFound handler. To use the operating system's file system implementation, use http.Dir:

router.ServeFiles("/src/*filepath", http.Dir("/var/www"))

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP makes the router implement the http.Handler interface.

type TargetHandle

type TargetHandle func(c *Context)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL