Skip to content

Commit 11245a1

Browse files
authored
Merge pull request #238 from devfeel/develop
Version 1.7.16: replace *HttpContext to Context interface & fix middleware chain misbehaving in netsed groups
2 parents 34470fa + 2869b37 commit 11245a1

File tree

11 files changed

+302
-99
lines changed

11 files changed

+302
-99
lines changed

README.md

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ go get github.com/devfeel/dotweb
2323
```
2424

2525
## 2. Getting Started
26-
```go
26+
``` go
2727
package main
2828

2929
import (
@@ -58,6 +58,7 @@ func main() {
5858
* Feature支持,可绑定HttpServer全局启用
5959
* 支持STRING/JSON/JSONP/HTML格式输出
6060
* 集成Mock能力
61+
* 支持自定义Context
6162
* 集成Timeout Hook
6263
* 全局HTTP错误处理
6364
* 全局日志处理
@@ -103,26 +104,26 @@ cpu | 内存 | Samples | Average | Median | 90%Line | 95%Line | 99%Line | Min |
103104
* 支持通过配置开启默认添加HEAD方式
104105
* 支持注册Handler,以启用配置化
105106
* 支持检查请求与指定路由是否匹配
106-
```go
107-
1Router.GET(path string, handle HttpHandle)
108-
2Router.POST(path string, handle HttpHandle)
109-
3Router.HEAD(path string, handle HttpHandle)
110-
4Router.OPTIONS(path string, handle HttpHandle)
111-
5Router.PUT(path string, handle HttpHandle)
112-
6Router.PATCH(path string, handle HttpHandle)
113-
7Router.DELETE(path string, handle HttpHandle)
114-
8Router.HiJack(path string, handle HttpHandle)
115-
9Router.WebSocket(path string, handle HttpHandle)
116-
10Router.Any(path string, handle HttpHandle)
117-
11Router.RegisterRoute(routeMethod string, path string, handle HttpHandle)
118-
12Router.RegisterHandler(name string, handler HttpHandle)
119-
13Router.GetHandler(name string) (HttpHandle, bool)
120-
14Router.MatchPath(ctx Context, routePath string) bool
107+
``` go
108+
Router.GET(path string, handle HttpHandle)
109+
Router.POST(path string, handle HttpHandle)
110+
Router.HEAD(path string, handle HttpHandle)
111+
Router.OPTIONS(path string, handle HttpHandle)
112+
Router.PUT(path string, handle HttpHandle)
113+
Router.PATCH(path string, handle HttpHandle)
114+
Router.DELETE(path string, handle HttpHandle)
115+
Router.HiJack(path string, handle HttpHandle)
116+
Router.WebSocket(path string, handle HttpHandle)
117+
Router.Any(path string, handle HttpHandle)
118+
Router.RegisterRoute(routeMethod string, path string, handle HttpHandle)
119+
Router.RegisterHandler(name string, handler HttpHandle)
120+
Router.GetHandler(name string) (HttpHandle, bool)
121+
Router.MatchPath(ctx Context, routePath string) bool
121122
```
122123
接受两个参数,一个是URI路径,另一个是 HttpHandle 类型,设定匹配到该路径时执行的方法;
123124
#### 2) static router
124125
静态路由语法就是没有任何参数变量,pattern是一个固定的字符串。
125-
```go
126+
``` go
126127
package main
127128

128129
import (
@@ -141,7 +142,7 @@ test:
141142
curl http://127.0.0.1/hello
142143
#### 3) parameter router
143144
参数路由以冒号 : 后面跟一个字符串作为参数名称,可以通过 HttpContext的 GetRouterName 方法获取路由参数的值。
144-
```go
145+
``` go
145146
package main
146147

147148
import (
@@ -165,7 +166,7 @@ test:
165166
<br>curl http://127.0.0.1/hello/devfeel
166167
<br>curl http://127.0.0.1/hello/category1/1
167168
#### 4) group router
168-
```go
169+
``` go
169170
g := server.Group("/user")
170171
g.GET("/", Index)
171172
g.GET("/profile", Profile)
@@ -178,7 +179,7 @@ test:
178179
## 6. Binder
179180
* HttpContext.Bind(interface{})
180181
* Support data from json、xml、Form
181-
```go
182+
``` go
182183
type UserInfo struct {
183184
UserName string `form:"user"`
184185
Sex int `form:"sex"`
@@ -213,7 +214,7 @@ func TestBind(ctx dotweb.HttpContext) error{
213214
* Recover
214215
* HeaderOverride
215216

216-
```go
217+
``` go
217218
app.Use(NewAccessFmtLog("app"))
218219

219220
func InitRoute(server *dotweb.HttpServer) {
@@ -286,13 +287,13 @@ func NewAccessFmtLog(index string) *AccessFmtLog {
286287
#### 500 error
287288
* Default: 当发生未处理异常时,会根据RunMode向页面输出默认错误信息或者具体异常信息,并返回 500 错误头
288289
* User-defined: 通过DotServer.SetExceptionHandle(handler *ExceptionHandle)实现自定义异常处理逻辑
289-
```go
290+
``` go
290291
type ExceptionHandle func(Context, error)
291292
```
292293
#### 404 error
293294
* Default: 当发生404异常时,会默认使用http.NotFound处理
294295
* User-defined: 通过DotWeb.SetNotFoundHandle(handler NotFoundHandle)实现自定义404处理逻辑
295-
```go
296+
``` go
296297
type NotFoundHandle func(http.ResponseWriter, *http.Request)
297298
```
298299

context.go

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,24 @@ type (
9595
WriteJsonBlobC(code int, b []byte) error
9696
WriteJsonp(callback string, i interface{}) error
9797
WriteJsonpBlob(callback string, b []byte) error
98+
99+
//inner func
100+
getMiddlewareStep() string
101+
setMiddlewareStep(step string)
102+
release()
103+
reset(res *Response, r *Request, server *HttpServer, node RouterNode, params Params, handler HttpHandle)
104+
setSessionID(id string)
105+
setRouterParams(params Params)
106+
setRouterNode(node RouterNode)
107+
setHandler(handler HttpHandle)
108+
getCancel() context.CancelFunc
109+
setCancel(cancel context.CancelFunc)
98110
}
99111

100112
HttpContext struct {
101113
context context.Context
102114
// Reserved
103-
cancle context.CancelFunc
115+
cancel context.CancelFunc
104116
middlewareStep string
105117
request *Request
106118
routerNode RouterNode
@@ -132,6 +144,13 @@ type (
132144
}
133145
)
134146

147+
// defaultContextCreater return new HttpContex{}
148+
func defaultContextCreater() Context {
149+
return &HttpContext{}
150+
}
151+
152+
//************* HttpContext public func **********************
153+
135154
// reset response attr
136155
func (ctx *HttpContext) reset(res *Response, r *Request, server *HttpServer, node RouterNode, params Params, handler HttpHandle) {
137156
ctx.request = r
@@ -179,7 +198,7 @@ func (ctx *HttpContext) Context() context.Context {
179198
// set Context & cancle
180199
// withvalue RequestID
181200
func (ctx *HttpContext) SetTimeoutContext(timeout time.Duration) context.Context {
182-
ctx.context, ctx.cancle = context.WithTimeout(context.Background(), timeout)
201+
ctx.context, ctx.cancel = context.WithTimeout(context.Background(), timeout)
183202
ctx.context = context.WithValue(ctx.context, "RequestID", ctx.Request().RequestID())
184203
return ctx.context
185204
}
@@ -639,6 +658,50 @@ func (ctx *HttpContext) WriteJsonpBlob(callback string, b []byte) error {
639658
return err
640659
}
641660

661+
//**************** HttpContext inner func ************************
662+
663+
// setMiddlewareStep
664+
func (ctx *HttpContext) setMiddlewareStep(step string) {
665+
ctx.middlewareStep = step
666+
}
667+
668+
// getMiddlewareStep
669+
func (ctx *HttpContext) getMiddlewareStep() string {
670+
return ctx.middlewareStep
671+
}
672+
673+
// setSessionID
674+
func (ctx *HttpContext) setSessionID(id string) {
675+
ctx.sessionID = id
676+
}
677+
678+
// setRouterParams
679+
func (ctx *HttpContext) setRouterParams(params Params) {
680+
ctx.routerParams = params
681+
}
682+
683+
// setRouterNode
684+
func (ctx *HttpContext) setRouterNode(node RouterNode) {
685+
ctx.routerNode = node
686+
}
687+
688+
// setHandler
689+
func (ctx *HttpContext) setHandler(handler HttpHandle) {
690+
ctx.handler = handler
691+
}
692+
693+
// getCancel return context.CancelFunc
694+
func (ctx *HttpContext) getCancel() context.CancelFunc {
695+
return ctx.cancel
696+
}
697+
698+
// setCancel
699+
func (ctx *HttpContext) setCancel(cancel context.CancelFunc) {
700+
ctx.cancel = cancel
701+
}
702+
703+
//************* WebSocket public func **********************
704+
642705
// Request get http request
643706
func (ws *WebSocket) Request() *http.Request {
644707
return ws.Conn.Request()
@@ -656,6 +719,8 @@ func (ws *WebSocket) ReadMessage() (string, error) {
656719
return str, err
657720
}
658721

722+
//************* HijackConn public func **********************
723+
659724
// WriteString hjiack conn write string
660725
func (hj *HijackConn) WriteString(content string) (int, error) {
661726
n, err := hj.ReadWriter.WriteString(hj.header + "\r\n" + content)

example/main.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ func main() {
3737
app.SetDevelopmentMode()
3838
app.SetProductionMode()
3939

40+
//设置自定义Context
41+
app.HttpServer.SetContextCreater(testContextCreater)
42+
4043
//设置gzip开关
4144
//app.HttpServer.SetEnabledGzip(true)
4245

@@ -99,7 +102,7 @@ func main() {
99102

100103
func Index(ctx dotweb.Context) error {
101104
ctx.Response().Header().Set("Content-Type", "text/html; charset=utf-8")
102-
ctx.Write(200, []byte(ctx.Request().RemoteIP()))
105+
ctx.Write(200, []byte(ctx.Request().RemoteIP()+" "+ctx.(*testContext).TestInfo))
103106
//_, err := ctx.WriteStringC(201, "index => ", ctx.RemoteIP(), "我是首页")
104107
return nil
105108
}
@@ -118,6 +121,10 @@ func Time(ctx dotweb.Context) error {
118121
return nil
119122
}
120123

124+
func OutputTestInfo(ctx dotweb.Context) error {
125+
return ctx.WriteString(ctx.(*testContext).TestInfo)
126+
}
127+
121128
func IndexReg(ctx dotweb.Context) error {
122129
ctx.HttpServer().Logger().Info(dotweb.LogTarget_Default, "test log")
123130
ctx.Response().Header().Set("Content-Type", "text/html; charset=utf-8")
@@ -189,3 +196,12 @@ func InitRoute(server *dotweb.HttpServer) {
189196
server.GET("/pretty", IndexPretty)
190197
//server.Router().RegisterRoute(dotweb.RouteMethod_GET, "/index", IndexReg)
191198
}
199+
200+
type testContext struct {
201+
dotweb.HttpContext
202+
TestInfo string
203+
}
204+
205+
func testContextCreater() dotweb.Context {
206+
return &testContext{TestInfo: "Test"}
207+
}

example/middleware/main.go

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,32 @@ func Index(ctx dotweb.Context) error {
5252
return err
5353
}
5454

55+
func ShowMiddlewares(ctx dotweb.Context) error {
56+
err := ctx.WriteString("ShowMiddlewares => ", ctx.RouterNode().GroupMiddlewares())
57+
return err
58+
}
59+
5560
func InitRoute(server *dotweb.HttpServer) {
5661
server.Router().GET("/", Index)
5762
server.Router().GET("/index", Index)
5863
server.Router().GET("/v1/machines/queryIP/:IP", Index)
5964
server.Router().GET("/v1/machines/queryIP2", Index)
6065
server.Router().GET("/use", Index).Use(NewAccessFmtLog("Router-use"))
6166

62-
g := server.Group("/group").Use(NewAccessFmtLog("group")).Use(NewSimpleAuth("admin"))
67+
/*g := server.Group("/group").Use(NewAccessFmtLog("group")).Use(NewSimpleAuth("admin"))
6368
g.GET("/", Index)
64-
g.GET("/use", Index).Use(NewAccessFmtLog("group-use"))
69+
g.GET("/use", Index).Use(NewAccessFmtLog("group-use"))*/
70+
71+
g := server.Group("/A").Use(NewAGroup())
72+
g.GET("/", ShowMiddlewares)
73+
g1 := g.Group("/B").Use(NewBGroup())
74+
g1.GET("/", ShowMiddlewares)
75+
g2 := g.Group("/C").Use(NewCGroup())
76+
g2.GET("/", ShowMiddlewares)
77+
78+
g = server.Group("/B").Use(NewBGroup())
79+
g.GET("/", ShowMiddlewares)
80+
6581
}
6682

6783
func InitModule(dotserver *dotweb.HttpServer) {
@@ -122,3 +138,45 @@ func (m *SimpleAuth) Handle(ctx dotweb.Context) error {
122138
func NewSimpleAuth(exactToken string) *SimpleAuth {
123139
return &SimpleAuth{exactToken: exactToken}
124140
}
141+
142+
type AGroup struct {
143+
dotweb.BaseMiddleware
144+
}
145+
146+
func (m *AGroup) Handle(ctx dotweb.Context) error {
147+
fmt.Println(time.Now(), "[AGroup] request)")
148+
err := m.Next(ctx)
149+
return err
150+
}
151+
152+
func NewAGroup() *AGroup {
153+
return &AGroup{}
154+
}
155+
156+
type BGroup struct {
157+
dotweb.BaseMiddleware
158+
}
159+
160+
func (m *BGroup) Handle(ctx dotweb.Context) error {
161+
fmt.Println(time.Now(), "[BGroup] request)")
162+
err := m.Next(ctx)
163+
return err
164+
}
165+
166+
func NewBGroup() *BGroup {
167+
return &BGroup{}
168+
}
169+
170+
type CGroup struct {
171+
dotweb.BaseMiddleware
172+
}
173+
174+
func (m *CGroup) Handle(ctx dotweb.Context) error {
175+
fmt.Println(time.Now(), "[CGroup] request)")
176+
err := m.Next(ctx)
177+
return err
178+
}
179+
180+
func NewCGroup() *CGroup {
181+
return &CGroup{}
182+
}

group.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package dotweb
22

3+
import "reflect"
4+
35
type (
46
Group interface {
57
Use(m ...Middleware) Group
@@ -30,10 +32,18 @@ func NewGroup(prefix string, server *HttpServer) Group {
3032
}
3133

3234
// Use implements `Router#Use()` for sub-routes within the Group.
33-
func (g *xGroup) Use(m ...Middleware) Group {
34-
if len(m) <= 0 {
35+
func (g *xGroup) Use(ms ...Middleware) Group {
36+
if len(ms) <= 0 {
3537
return g
3638
}
39+
40+
// deepcopy middleware structs to avoid middleware chain misbehaving
41+
m := []Middleware{}
42+
for _, om := range ms {
43+
newM := reflect.New(reflect.ValueOf(om).Elem().Type()).Interface().(Middleware)
44+
newM.SetNext(nil)
45+
m = append(m, newM)
46+
}
3747
step := len(g.middlewares) - 1
3848
for i := range m {
3949
if m[i] != nil {

0 commit comments

Comments
 (0)