diff --git a/docs/tutorials.md b/docs/tutorials.md index 4b8c748..0fd8c19 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -146,7 +146,7 @@ type User struct { * 函数参数的类型限定为 `mir.(Get/Put/Post/Delete/Head/Patch/Trace/Connect/Options/Any/Chain)`类型、Go `struct`类型; * Go `struct`类型作为函数参数只能放置在最后一个参数位置,表示接口需要这个`struct`类型表示的参数类型的从http request中Binding后的结果对象作为请求参数; * 函数参数中的非最后一个参数,可以有多个,类型限定为`mir.(Get/Put/Post/Delete/Head/Patch/Trace/Connect/Options/Any)`类型;表示的意思是这个接口将注册为相应的HTTP Method handler,比如`mir.Post`表示将这个接口注册为 HTTP Method 为`POST` 的handler `router.Handle("POST", "/login/", func(...){...})`; `mir.Any` 表示将这个接口注册为所有HTTP Method handler; - * 函数参数中如果有`Chain`表示这个接口有自定义的HTTP引擎中间件的方法,比如gin引擎的`gin.HandlersChain`,会与接口一起注册,目前仅支持`Gin`/`Chi`/`Echo`/`Hertz`引擎; + * 函数参数中如果有`Chain`表示这个接口有自定义的HTTP引擎中间件的方法,比如gin引擎的`gin.HandlersChain`,会与接口一起注册,目前仅支持`Gin`/`Chi`/`Echo`/`Hertz`/`Iris`引擎; * 函数返回值至多只有一个,可以没有,也可以有一个,限定类型为Go `struct`类型; * 函数中的最后一个参数和返回值,如果有的话,限定类型为Go `struct`类型,并且可以说与接口定义的同一个包中的结构体,也可以是其他包中的结构体; diff --git a/internal/generator/templates/iris_iface.tmpl b/internal/generator/templates/iris_iface.tmpl index 701ee02..e2081b5 100644 --- a/internal/generator/templates/iris_iface.tmpl +++ b/internal/generator/templates/iris_iface.tmpl @@ -33,6 +33,14 @@ type {{.TypeName}}Binding interface { mustEmbedUnimplemented{{.TypeName}}Binding() } {{end}} +{{if .IsUseFieldChain }} +type {{.TypeName}}Chain interface { +{{range .ChainFields }} Chain{{.MethodName}}() context.Handlers +{{end}} + + mustEmbedUnimplemented{{.TypeName}}Chain() +} +{{end}} type {{.TypeName}}Render interface { {{range .Fields}} {{if notEmptyStr .OutName }}Render{{.MethodName}}(context.Context, *{{ .OutName }}, mir.Error){{else}}Render{{.MethodName}}(context.Context, mir.Error){{end}} @@ -42,14 +50,14 @@ type {{.TypeName}}Render interface { } // Register{{.TypeName}}Servant register {{.TypeName}} servant to iris -func Register{{.TypeName}}Servant(app *iris.Application, s {{.TypeName}}{{if .IsUseBinding }}, b {{.TypeName}}Binding{{end}}, r {{.TypeName}}Render ) { +func Register{{.TypeName}}Servant(app *iris.Application, s {{.TypeName}}{{if .IsUseBinding }}, b {{.TypeName}}Binding{{end}}, r {{.TypeName}}Render{{if .IsUseFieldChain }}, c {{.TypeName}}Chain{{end}}) { {{if notEmptyStr .Group }} router := app.Party("{{.Group}}"){{else}} router := app{{end}} {{if notEmptyStr .Chain }} // use chain for party middlewares := s.{{.Chain}}() router.Use(middlewares...) {{end}} // register routes info to router -{{range .Fields}}{{if .NotHttpAny }} router.Handle("{{.HttpMethod}}", "{{.Path}}", func(c context.Context) {{if $.WatchCtxDone }}{ +{{range .Fields}}{{if .NotHttpAny }} router.Handle("{{.HttpMethod}}", "{{.Path}}", {{if .IsFieldChain }}append(c.Chain{{.MethodName}}(), {{end}}func(c context.Context) {{if $.WatchCtxDone }}{ select { case <- c.Request().Context().Done(): return @@ -64,8 +72,8 @@ func Register{{.TypeName}}Servant(app *iris.Application, s {{.TypeName}}{{if .Is {{if notEmptyStr .OutName}}resp, err := s.{{.MethodName}}(req) r.Render{{.MethodName}}(c, resp, err){{else}}r.Render{{.MethodName}}(c, s.{{.MethodName}}(req)){{end}}{{else}}{{if notEmptyStr .OutName}}resp, err := s.{{.MethodName}}() r.Render{{.MethodName}}(c, resp, err){{else}}r.Render{{.MethodName}}(c, s.{{.MethodName}}()){{end}}{{end}} - }) - {{else if .JustHttpAny}} router.Any("{{.Path}}", func(c context.Context) {{if $.WatchCtxDone }}{ + }{{if .IsFieldChain }})...{{end}}) + {{else if .JustHttpAny}} router.Any("{{.Path}}", {{if .IsFieldChain }}append(c.Chain{{.MethodName}}(), {{end}}func(c context.Context) {{if $.WatchCtxDone }}{ select { case <- c.Request().Context().Done(): return @@ -80,9 +88,9 @@ func Register{{.TypeName}}Servant(app *iris.Application, s {{.TypeName}}{{if .Is {{if notEmptyStr .OutName}}resp, err := s.{{.MethodName}}(req) r.Render{{.MethodName}}(c, resp, err){{else}}r.Render{{.MethodName}}(c, s.{{.MethodName}}(req)){{end}}{{else}}{{if notEmptyStr .OutName}}resp, err := s.{{.MethodName}}() r.Render{{.MethodName}}(c, resp, err){{else}}r.Render{{.MethodName}}(c, s.{{.MethodName}}()){{end}}{{end}} - }) + }{{if .IsFieldChain }})...{{end}}) {{else}}{{$field := .}} { - h := func(c context.Context) {{if $.WatchCtxDone }}{ + h := {{if .IsFieldChain }}append(c.Chain{{.MethodName}}(), {{end}}func(c context.Context) {{if $.WatchCtxDone }}{ select { case <- c.Request().Context().Done(): return @@ -97,8 +105,8 @@ func Register{{.TypeName}}Servant(app *iris.Application, s {{.TypeName}}{{if .Is {{if notEmptyStr .OutName}}resp, err := s.{{.MethodName}}(req) r.Render{{.MethodName}}(c, resp, err){{else}}r.Render{{.MethodName}}(c, s.{{.MethodName}}(req)){{end}}{{else}}{{if notEmptyStr .OutName}}resp, err := s.{{.MethodName}}() r.Render{{.MethodName}}(c, resp, err){{else}}r.Render{{.MethodName}}(c, s.{{.MethodName}}()){{end}}{{end}} - } - {{range .AnyHttpMethods}} router.Handle("{{.}}", "{{$field.Path}}", h) + }{{if .IsFieldChain }}){{end}} + {{range .AnyHttpMethods}} router.Handle("{{.}}", "{{$field.Path}}", h{{if $field.IsFieldChain }}...{{end}}) {{end}} } {{end}} {{end}}} @@ -151,3 +159,16 @@ type {{$unimplementedBinding}} struct { {{end}} func (b *{{$unimplementedBinding}})mustEmbedUnimplemented{{.TypeName}}Binding() {} {{end}} +{{if .IsUseFieldChain }} +{{ $unimplementedChain := print "Unimplemented" .TypeName "Chain" }} +// {{$unimplementedChain}} can be embedded to have forward compatible implementations. +type {{$unimplementedChain}} struct { +} + +{{range .Fields}}{{if .IsFieldChain }}func (b *{{$unimplementedChain}}) Chain{{.MethodName}}() context.Handlers { + return nil +} +{{end}} +{{end}} +func (b *{{$unimplementedChain}})mustEmbedUnimplemented{{.TypeName}}Chain() {} +{{end}}