gobox 中的 http 请求处理框架

阅读数:26 2019 年 11 月 18 日 11:46

gobox中的http请求处理框架

今天和大家介绍下我们自主开发的 go 语言轻型框架 gobox,为什么叫 gobox 呢?因为我们设计让每一个单独的模块都作为一个 box,那这些 box 的集合就称为 gobox,再使用 go 的 pkg 管理机制引入到项目中。随着 go 官方推出了 dep 这个包管理工具,我们把 gobox 中的每一个 box 都单独拿出来作为一个项目管理,这就是现在的 gobox;今天这一期,主要来说下使用 gobox 中的 http 请求处理框架。

http 请求处理架构图

gobox中的http请求处理框架

重要的对象

System

system 用于实现 go 官方包中的 http.Handler 接口,它的 ServeHTTP 方法中实现了请求处理框架。

Router

定义和实现 MVC 的路由查找过程。

复制代码
type Router interface {
MapRouteItems(cls ...controller.Controller) // ⾃动将 Controller 对象中的 Action⽅法映射到路由表
DefineRouteItem(pattern string, cl controller.Controller, actionName string) // ⼿动添加路由规则,pattern 为正则表达式
FindRoute(path string) *Route // 实现路由查找过程
}

SimpleRouter

Router 接口的一个实现,自动映射规则为:

1.controller 名称规则为: ([A-Z][A-Za-z0-9_])Controller$,匹配内容转小写即为 controllerName
2.action 名称规则为: ^([A-Z][A-Za-z0-9_]
)Action$,匹配内容转小写后过滤掉 before 和 after 即为 actionName

自动路由查找规则如下:

1. 将 request_uri 视为: /controller/action
2.controller 不存在,则默认为 index,可以修改
3.action 不存在,则默认为 index,可以修改

自定义路由查找规则如下:

1. 对 request_uri 做正则匹配
2. 如果匹配后存在捕获,则捕获内容会作为 action 中除 context 外的参数,依次传入,都是 string 类型

ActionContext 和 Controller

ActionContext

处理每个请求会创建一个对应 Controller 的 ActionContext 对象:

复制代码
type ActionContext interface {
Request() *http.Request
ResponseWriter() http.ResponseWriter
ResponseBody() []byte
SetResponseBody(body []byte)
BeforeAction()
AfterAction()
Destruct()
}

Controller

组织 Action:

复制代码
type Controller interface {
NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext
}

gracehttp

这是一个支持平滑重启的 httpserver,平滑重启过程如下:

gobox中的http请求处理框架

示例代码

最后附上一个最简单的使用示例:

复制代码
package main
import (
"github.com/goinbox/gohttp/controller"
"github.com/goinbox/gohttp/gracehttp"
"github.com/goinbox/gohttp/router"
"github.com/goinbox/gohttp/system"
"net/http"
)
func main() {
dcl := new(DemoController)
r := router.NewSimpleRouter()
r.DefineRouteItem("^/g/([0-9]+)$", dcl, "get")
r.MapRouteItems(new(IndexController), dcl)
sys := system.NewSystem(r)
gracehttp.ListenAndServe(":8001", sys)
}
type BaseActionContext struct {
Req *http.Request
RespWriter http.ResponseWriter
RespBody []byte
}
func (this *BaseActionContext) Request() *http.Request {
return this.Req
}
func (this *BaseActionContext) ResponseWriter() http.ResponseWriter {
return this.RespWriter
}
func (this *BaseActionContext) ResponseBody() []byte {
return this.RespBody
}
func (this *BaseActionContext) SetResponseBody(body []byte) {
this.RespBody = body
}
func (this *BaseActionContext) BeforeAction() {
this.RespBody = append(this.RespBody, []byte(" index before ")...)
}
func (this *BaseActionContext) AfterAction() {
this.RespBody = append(this.RespBody, []byte(" index after ")...)
}
func (this *BaseActionContext) Destruct() {
println(" index destruct ")
}
type IndexController struct {
}
func (this *IndexController) NewActionContext(req *http.Request, respWriter http.R
return &BaseActionContext{
Req: req,
RespWriter: respWriter,
}
}
{1}
func (this *IndexController) IndexAction(context
*BaseActionContext) {
context.RespBody = append(context.RespBody, []byte(" index action ")...)
}
func (this *IndexController) RedirectAction(context
*BaseActionContext) {
system.Redirect302("https://github.com/goinbox")
}
type DemoActionContext struct {
*BaseActionContext
}
func (this *DemoActionContext) BeforeAction() {
this.RespBody = append(this.RespBody, []byte(" demo before ")...)
}
func (this *DemoActionContext) AfterAction() {
this.RespBody = append(this.RespBody, []byte(" demo after ")...)
}
func (this *DemoActionContext) Destruct() {
println(" demo destruct ")
}
type DemoController struct {
}
func (this *DemoController) NewActionContext(req *http.Request, respWriter http.Re
return &DemoActionContext{
&BaseActionContext{
Req: req,
RespWriter: respWriter,
},
}
}
{1}
{1}
func (this *DemoController) DemoAction(context *DemoActionContext) {
context.RespBody = append(context.RespBody, []byte(" demo action ")...)
}
func (this *DemoController) GetAction(context *DemoActionContext, id string) {
context.RespBody = append(context.RespBody, []byte(" get action id = "+id)...)
}

运⾏这个代码,请求示例及输出如下:

复制代码
curl http://127.0.0.1:8001/
index before index action index after
curl http://127.0.0.1:8001/index/redirect -I
HTTP/1.1 302 Found
Content-Type: text/html; charset=utf-8
Location: https://github.com/goinbox
Date: Fri, 24 Aug 2018 11:57:11 GMT
Content-Length: 14
curl http://127.0.0.1:8001/demo/demo
demo before demo action demo after
curl http://127.0.0.1:8001/g/123
demo before get action id = 123 demo after

所有 destruct 输出为:

复制代码
index destruct
index destruct
index destruct
demo destruct
demo destruc

欢迎大家使用,使用中有遇到问题随时反馈,我们会尽快响应,谢谢!

本文转载自公众号 360 云计算(ID:hulktalk)。

原文链接:

https://mp.weixin.qq.com/s/WEOW2Sxe1Y_YgnFZ_Af4Og

评论

发布