From b777fba349e28cd7adef41a16b1ca481e5db0c8f Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 9 Feb 2024 21:03:01 +0800 Subject: [PATCH] add engine support for option for generate interface method code that contain HTTP Request Context. --- CHANGELOG.md | 2 +- core/core.go | 26 ++++++-- core/descriptor.go | 48 ++++++++----- examples/go.mod | 4 +- examples/mirc/auto/api/site.go | 45 +++++++------ examples/mirc/auto/api/v1/admin.go | 27 ++++---- examples/mirc/auto/api/v1/site.go | 27 ++++---- examples/mirc/auto/api/v2/site.go | 39 +++++------ examples/mirc/auto/api/v3/site.go | 39 +++++------ examples/mirc/gen.go | 1 + internal/generator/templates/gin_iface.tmpl | 17 ++--- internal/parser/parser.go | 14 ++-- internal/reflex/reflex.go | 74 +++++++++++---------- 13 files changed, 202 insertions(+), 161 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ba99ab..7373406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to paopao-ce are documented in this file. ## 4.2.0 ([`dev`](https://github.com/alimy/mir)) -TODO; +- add `gin` engine support for `UseRequstContext` option for generate interface method code that contain HTTP Request Context. ## 4.1.0 ### Added diff --git a/core/core.go b/core/core.go index 0bc8885..871c025 100644 --- a/core/core.go +++ b/core/core.go @@ -57,16 +57,18 @@ type InitOpts struct { EnginePkgName string EngineImportAlias string WatchCtxDone bool + UseRequestCtx bool NoneQuery bool Cleanup bool } // ParserOpts used for initial parser type ParserOpts struct { - EngineInfo *EngineInfo - DefaultTag string - WatchCtxDone bool - NoneQuery bool + EngineInfo *EngineInfo + DefaultTag string + WatchCtxDone bool + UseRequestCtx bool + NoneQuery bool } // GeneratorOpts used for initial generator @@ -95,9 +97,10 @@ func (opts Options) InitOpts() *InitOpts { // ParserOpts return a ParserOpts instance func (opts *InitOpts) ParserOpts() *ParserOpts { return &ParserOpts{ - DefaultTag: opts.DefaultTag, - WatchCtxDone: opts.WatchCtxDone, - NoneQuery: opts.NoneQuery, + DefaultTag: opts.DefaultTag, + WatchCtxDone: opts.WatchCtxDone, + UseRequestCtx: opts.UseRequestCtx, + NoneQuery: opts.NoneQuery, EngineInfo: &EngineInfo{ PkgName: opts.EnginePkgName, ImportAlias: opts.EngineImportAlias, @@ -292,6 +295,14 @@ func WatchCtxDone(enable bool) Option { }) } +// UseRequestContext use HTTP Request Context in generated interface method code. +// Default is disable use HTTP Request Context. +func UseRequestContext() Option { + return optFunc(func(opts *InitOpts) { + opts.UseRequestCtx = true + }) +} + // Cleanup set generator cleanup out first when re-generate code func Cleanup(enable bool) Option { return optFunc(func(opts *InitOpts) { @@ -399,6 +410,7 @@ func defaultInitOpts() *InitOpts { SinkPath: ".auto", DefaultTag: "mir", WatchCtxDone: true, + UseRequestCtx: false, Cleanup: true, } } diff --git a/core/descriptor.go b/core/descriptor.go index 9d6b99d..5b48e05 100644 --- a/core/descriptor.go +++ b/core/descriptor.go @@ -16,7 +16,7 @@ import ( var ( VerInfo = &VersionInfo{ - MirVer: "v4.1.0", + MirVer: "v4.2.0", } ) @@ -33,22 +33,23 @@ type VersionInfo struct { // FieldDescriptor field Descriptor info type FieldDescriptor struct { - Imports map[string]string - PkgPath string - Host string - Path string - Queries []string - HttpMethods []string - IsAnyMethod bool - IsFieldChain bool - IsUseContext bool - IsBindIn bool - IsRenderOut bool - In reflect.Type - Out reflect.Type - InOuts []reflect.Type - MethodName string - Comment string // not support now so always empty + Imports map[string]string + PkgPath string + Host string + Path string + Queries []string + HttpMethods []string + IsAnyMethod bool + IsFieldChain bool + IsUseContext bool + IsUseRequestContext bool + IsBindIn bool + IsRenderOut bool + In reflect.Type + Out reflect.Type + InOuts []reflect.Type + MethodName string + Comment string // not support now so always empty } // IfaceDescriptor interface Descriptor info @@ -65,6 +66,7 @@ type IfaceDescriptor struct { EngineInfo *EngineInfo VerInfo *VersionInfo WatchCtxDone bool + UseRequestCtx bool DeclareCoreInterface bool // whether need to declare core interface, default is false } @@ -238,6 +240,18 @@ func (d *IfaceDescriptor) IsUseBinding() bool { return false } +func (d *IfaceDescriptor) IsUseRequestContext() bool { + if !d.UseRequestCtx { + return false + } + for _, f := range d.Fields { + if f.IsUseRequestContext { + return true + } + } + return false +} + // BindingFields return Binding's fields func (d *IfaceDescriptor) BindingFields() (fields []*FieldDescriptor) { for _, f := range d.Fields { diff --git a/examples/go.mod b/examples/go.mod index 7a7b16e..d23f0d5 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -3,7 +3,7 @@ module github.com/alimy/mir-example/v4 go 1.19 require ( - github.com/alimy/mir/v4 v4.1.0 + github.com/alimy/mir/v4 v4.2.0 github.com/gin-gonic/gin v1.9.1 ) @@ -35,3 +35,5 @@ require ( gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/alimy/mir/v4 => ../ diff --git a/examples/mirc/auto/api/site.go b/examples/mirc/auto/api/site.go index 57b0a29..7fe88b6 100644 --- a/examples/mirc/auto/api/site.go +++ b/examples/mirc/auto/api/site.go @@ -1,10 +1,11 @@ // Code generated by go-mir. DO NOT EDIT. // versions: -// - mir v4.1.0 +// - mir v4.2.0 package api import ( + "context" "net/http" "github.com/alimy/mir/v4" @@ -82,13 +83,13 @@ type Site interface { SimpleUpload(*gin.Context, *LoginReq) (*LoginResp, mir.Error) FileUpload(*gin.Context) ImageUpload(*gin.Context) - Logout(*LogoutReq) mir.Error - Login(*LoginReq) (*LoginResp, mir.Error) - PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) - NextTweets(*TweetsReq) (*TweetsResp, mir.Error) - AnyTopics() mir.Error - Articles() mir.Error - Index() mir.Error + Logout(context.Context, *LogoutReq) mir.Error + Login(context.Context, *LoginReq) (*LoginResp, mir.Error) + PrevTweets(context.Context, *TweetsReq) (*TweetsResp, mir.Error) + NextTweets(context.Context, *TweetsReq) (*TweetsResp, mir.Error) + AnyTopics(context.Context) mir.Error + Articles(context.Context) mir.Error + Index(context.Context) mir.Error mustEmbedUnimplementedSiteServant() } @@ -170,7 +171,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - s.Render(c, nil, s.Logout(req)) + s.Render(c, nil, s.Logout(c.Request.Context(), req)) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { select { @@ -183,7 +184,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.Login(req) + resp, err := s.Login(c.Request.Context(), req) s.Render(c, resp, err) }) { @@ -198,7 +199,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.PrevTweets(req) + resp, err := s.PrevTweets(c.Request.Context(), req) s.Render(c, resp, err) } router.Handle("GET", "/tweets/prev/", h) @@ -216,7 +217,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.NextTweets(req) + resp, err := s.NextTweets(c.Request.Context(), req) s.Render(c, resp, err) }) router.Any("/topics/", func(c *gin.Context) { @@ -226,7 +227,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.AnyTopics()) + s.Render(c, nil, s.AnyTopics(c.Request.Context())) }) router.Handle("GET", "/articles/:category/", func(c *gin.Context) { select { @@ -235,7 +236,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Articles()) + s.Render(c, nil, s.Articles(c.Request.Context())) }) router.Handle("GET", "/index/", append(cc.ChainIndex(), func(c *gin.Context) { select { @@ -244,7 +245,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Index()) + s.Render(c, nil, s.Index(c.Request.Context())) })...) } @@ -287,31 +288,31 @@ func (UnimplementedSiteServant) ImageUpload(c *gin.Context) { c.String(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { +func (UnimplementedSiteServant) Logout(c context.Context, req *LogoutReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { +func (UnimplementedSiteServant) Login(c context.Context, req *LoginReq) (*LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { +func (UnimplementedSiteServant) PrevTweets(c context.Context, req *TweetsReq) (*TweetsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { +func (UnimplementedSiteServant) NextTweets(c context.Context, req *TweetsReq) (*TweetsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) AnyTopics() mir.Error { +func (UnimplementedSiteServant) AnyTopics(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Articles() mir.Error { +func (UnimplementedSiteServant) Articles(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Index() mir.Error { +func (UnimplementedSiteServant) Index(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/examples/mirc/auto/api/v1/admin.go b/examples/mirc/auto/api/v1/admin.go index 732cc71..0608ebd 100644 --- a/examples/mirc/auto/api/v1/admin.go +++ b/examples/mirc/auto/api/v1/admin.go @@ -1,10 +1,11 @@ // Code generated by go-mir. DO NOT EDIT. // versions: -// - mir v4.1.0 +// - mir v4.2.0 package v1 import ( + "context" "net/http" "github.com/alimy/mir/v4" @@ -30,10 +31,10 @@ type Admin interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Quit() mir.Error - Teams() mir.Error - DelUser() mir.Error - User() mir.Error + Quit(context.Context) mir.Error + Teams(context.Context) mir.Error + DelUser(context.Context) mir.Error + User(context.Context) mir.Error mustEmbedUnimplementedAdminServant() } @@ -67,7 +68,7 @@ func RegisterAdminServant(e *gin.Engine, s Admin, m ...AdminChain) { default: } - s.Render(c, nil, s.Quit()) + s.Render(c, nil, s.Quit(c.Request.Context())) }) { h := append(cc.ChainTeams(), func(c *gin.Context) { @@ -77,7 +78,7 @@ func RegisterAdminServant(e *gin.Engine, s Admin, m ...AdminChain) { default: } - s.Render(c, nil, s.Teams()) + s.Render(c, nil, s.Teams(c.Request.Context())) }) router.Handle("GET", "/teams/:category/", h...) router.Handle("HEAD", "/teams/:category/", h...) @@ -90,7 +91,7 @@ func RegisterAdminServant(e *gin.Engine, s Admin, m ...AdminChain) { default: } - s.Render(c, nil, s.DelUser()) + s.Render(c, nil, s.DelUser(c.Request.Context())) })...) router.Handle("GET", "/user/", append(cc.ChainUser(), func(c *gin.Context) { select { @@ -99,7 +100,7 @@ func RegisterAdminServant(e *gin.Engine, s Admin, m ...AdminChain) { default: } - s.Render(c, nil, s.User()) + s.Render(c, nil, s.User(c.Request.Context())) })...) } @@ -110,19 +111,19 @@ func (UnimplementedAdminServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedAdminServant) Quit() mir.Error { +func (UnimplementedAdminServant) Quit(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedAdminServant) Teams() mir.Error { +func (UnimplementedAdminServant) Teams(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedAdminServant) DelUser() mir.Error { +func (UnimplementedAdminServant) DelUser(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedAdminServant) User() mir.Error { +func (UnimplementedAdminServant) User(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/examples/mirc/auto/api/v1/site.go b/examples/mirc/auto/api/v1/site.go index e124812..f71e7e9 100644 --- a/examples/mirc/auto/api/v1/site.go +++ b/examples/mirc/auto/api/v1/site.go @@ -1,10 +1,11 @@ // Code generated by go-mir. DO NOT EDIT. // versions: -// - mir v4.1.0 +// - mir v4.2.0 package v1 import ( + "context" "net/http" "github.com/alimy/mir/v4" @@ -21,10 +22,10 @@ type Site interface { ManyResources(*gin.Context) AnyStaticks(*gin.Context) Assets(*gin.Context) - Logout() mir.Error - Articles() mir.Error - AnyTopics() mir.Error - Index() mir.Error + Logout(context.Context) mir.Error + Articles(context.Context) mir.Error + AnyTopics(context.Context) mir.Error + Index(context.Context) mir.Error mustEmbedUnimplementedSiteServant() } @@ -73,7 +74,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Logout()) + s.Render(c, nil, s.Logout(c.Request.Context())) }) { h := append(cc.ChainArticles(), func(c *gin.Context) { @@ -83,7 +84,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Articles()) + s.Render(c, nil, s.Articles(c.Request.Context())) }) router.Handle("GET", "/articles/:category/", h...) router.Handle("HEAD", "/articles/:category/", h...) @@ -96,7 +97,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.AnyTopics()) + s.Render(c, nil, s.AnyTopics(c.Request.Context())) })...) router.Handle("GET", "/index/", append(cc.ChainIndex(), func(c *gin.Context) { select { @@ -105,7 +106,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Index()) + s.Render(c, nil, s.Index(c.Request.Context())) })...) } @@ -132,19 +133,19 @@ func (UnimplementedSiteServant) Assets(c *gin.Context) { c.String(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Logout() mir.Error { +func (UnimplementedSiteServant) Logout(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Articles() mir.Error { +func (UnimplementedSiteServant) Articles(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) AnyTopics() mir.Error { +func (UnimplementedSiteServant) AnyTopics(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Index() mir.Error { +func (UnimplementedSiteServant) Index(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/examples/mirc/auto/api/v2/site.go b/examples/mirc/auto/api/v2/site.go index 5c06307..bbd570f 100644 --- a/examples/mirc/auto/api/v2/site.go +++ b/examples/mirc/auto/api/v2/site.go @@ -1,10 +1,11 @@ // Code generated by go-mir. DO NOT EDIT. // versions: -// - mir v4.1.0 +// - mir v4.2.0 package v2 import ( + "context" "net/http" "github.com/alimy/mir/v4" @@ -73,12 +74,12 @@ type Site interface { SimpleUpload(*gin.Context, *LoginReq) (*LoginResp, mir.Error) FileUpload(*gin.Context) ImageUpload(*gin.Context) - Logout() mir.Error - Login(*LoginReq) (*LoginResp, mir.Error) - PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) - NextTweets(*TweetsReq) (*TweetsResp, mir.Error) - Articles() mir.Error - Index() mir.Error + Logout(context.Context) mir.Error + Login(context.Context, *LoginReq) (*LoginResp, mir.Error) + PrevTweets(context.Context, *TweetsReq) (*TweetsResp, mir.Error) + NextTweets(context.Context, *TweetsReq) (*TweetsResp, mir.Error) + Articles(context.Context) mir.Error + Index(context.Context) mir.Error mustEmbedUnimplementedSiteServant() } @@ -152,7 +153,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Logout()) + s.Render(c, nil, s.Logout(c.Request.Context())) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { select { @@ -165,7 +166,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.Login(req) + resp, err := s.Login(c.Request.Context(), req) s.Render(c, resp, err) }) { @@ -180,7 +181,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.PrevTweets(req) + resp, err := s.PrevTweets(c.Request.Context(), req) s.Render(c, resp, err) } router.Handle("GET", "/tweets/prev/", h) @@ -198,7 +199,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.NextTweets(req) + resp, err := s.NextTweets(c.Request.Context(), req) s.Render(c, resp, err) }) router.Handle("GET", "/articles/:category/", func(c *gin.Context) { @@ -208,7 +209,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Articles()) + s.Render(c, nil, s.Articles(c.Request.Context())) }) router.Handle("GET", "/index/", append(cc.ChainIndex(), func(c *gin.Context) { select { @@ -217,7 +218,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Index()) + s.Render(c, nil, s.Index(c.Request.Context())) })...) } @@ -252,27 +253,27 @@ func (UnimplementedSiteServant) ImageUpload(c *gin.Context) { c.String(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Logout() mir.Error { +func (UnimplementedSiteServant) Logout(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { +func (UnimplementedSiteServant) Login(c context.Context, req *LoginReq) (*LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { +func (UnimplementedSiteServant) PrevTweets(c context.Context, req *TweetsReq) (*TweetsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { +func (UnimplementedSiteServant) NextTweets(c context.Context, req *TweetsReq) (*TweetsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Articles() mir.Error { +func (UnimplementedSiteServant) Articles(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Index() mir.Error { +func (UnimplementedSiteServant) Index(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/examples/mirc/auto/api/v3/site.go b/examples/mirc/auto/api/v3/site.go index 39eed9c..62bad4d 100644 --- a/examples/mirc/auto/api/v3/site.go +++ b/examples/mirc/auto/api/v3/site.go @@ -1,10 +1,11 @@ // Code generated by go-mir. DO NOT EDIT. // versions: -// - mir v4.1.0 +// - mir v4.2.0 package v3 import ( + "context" "net/http" "github.com/alimy/mir-example/v4/model" @@ -33,12 +34,12 @@ type Site interface { AnyStaticks(*gin.Context) Statics(*gin.Context, *model.LoginReq) mir.Error Assets(*gin.Context) - Logout() mir.Error - Login(*model.LoginReq) (*model.LoginResp, mir.Error) - PrevTweets(*model.TweetsReq) (*model.TweetsResp, mir.Error) - NextTweets(*model.TweetsReq) (*model.TweetsResp, mir.Error) - Articles() mir.Error - Index() mir.Error + Logout(context.Context) mir.Error + Login(context.Context, *model.LoginReq) (*model.LoginResp, mir.Error) + PrevTweets(context.Context, *model.TweetsReq) (*model.TweetsResp, mir.Error) + NextTweets(context.Context, *model.TweetsReq) (*model.TweetsResp, mir.Error) + Articles(context.Context) mir.Error + Index(context.Context) mir.Error mustEmbedUnimplementedSiteServant() } @@ -95,7 +96,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Logout()) + s.Render(c, nil, s.Logout(c.Request.Context())) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { select { @@ -109,7 +110,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.Login(req) + resp, err := s.Login(c.Request.Context(), req) if err != nil { s.Render(c, nil, err) return @@ -129,7 +130,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.PrevTweets(req) + resp, err := s.PrevTweets(c.Request.Context(), req) s.Render(c, resp, err) } router.Handle("GET", "/tweets/prev/", h) @@ -147,7 +148,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { s.Render(c, nil, err) return } - resp, err := s.NextTweets(req) + resp, err := s.NextTweets(c.Request.Context(), req) s.Render(c, resp, err) }) router.Handle("GET", "/articles/:category/", func(c *gin.Context) { @@ -157,7 +158,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Articles()) + s.Render(c, nil, s.Articles(c.Request.Context())) }) router.Handle("GET", "/index/", func(c *gin.Context) { select { @@ -166,7 +167,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } - s.Render(c, nil, s.Index()) + s.Render(c, nil, s.Index(c.Request.Context())) }) } @@ -193,27 +194,27 @@ func (UnimplementedSiteServant) Assets(c *gin.Context) { c.String(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Logout() mir.Error { +func (UnimplementedSiteServant) Logout(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Login(req *model.LoginReq) (*model.LoginResp, mir.Error) { +func (UnimplementedSiteServant) Login(c context.Context, req *model.LoginReq) (*model.LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) PrevTweets(req *model.TweetsReq) (*model.TweetsResp, mir.Error) { +func (UnimplementedSiteServant) PrevTweets(c context.Context, req *model.TweetsReq) (*model.TweetsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) NextTweets(req *model.TweetsReq) (*model.TweetsResp, mir.Error) { +func (UnimplementedSiteServant) NextTweets(c context.Context, req *model.TweetsReq) (*model.TweetsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Articles() mir.Error { +func (UnimplementedSiteServant) Articles(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedSiteServant) Index() mir.Error { +func (UnimplementedSiteServant) Index(c context.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/examples/mirc/gen.go b/examples/mirc/gen.go index 04d6890..12ca73f 100644 --- a/examples/mirc/gen.go +++ b/examples/mirc/gen.go @@ -25,6 +25,7 @@ func main() { log.Println("generate code start") opts := Options{ UseGin(), + UseRequestContext(), SinkPath("auto"), WatchCtxDone(true), RunMode(InSerialMode), diff --git a/internal/generator/templates/gin_iface.tmpl b/internal/generator/templates/gin_iface.tmpl index 296cea5..7dea648 100644 --- a/internal/generator/templates/gin_iface.tmpl +++ b/internal/generator/templates/gin_iface.tmpl @@ -5,6 +5,7 @@ package {{ .PkgName }} import ( + {{if .IsUseRequestContext }}"context"{{end}} "net/http" "github.com/alimy/mir/v4" @@ -35,7 +36,7 @@ type {{.TypeName}} interface { {{if notEmptyStr .Chain }}// Chain provide handlers chain for gin {{.Chain}}() gin.HandlersChain {{end}} -{{range .Fields}} {{if .JustUseContext }}{{ .MethodName}}(*gin.Context){{else}}{{.MethodName}}({{if .IsUseContext }}*gin.Context{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName }}*{{ .InName }}{{end}}) {{if notEmptyStr .OutName }}(*{{ .OutName}}, mir.Error){{else}}mir.Error{{end}}{{end}} +{{range .Fields}} {{if .JustUseContext }}{{ .MethodName}}(*gin.Context){{else}}{{.MethodName}}({{if .IsUseRequestContext }}context.Context{{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}*gin.Context{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName }}*{{ .InName }}{{end}}) {{if notEmptyStr .OutName }}(*{{ .OutName}}, mir.Error){{else}}mir.Error{{end}}{{end}} {{end}} mustEmbedUnimplemented{{.TypeName}}Servant() @@ -86,7 +87,7 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField } {{- end }} {{if notEmptyStr .OutName -}} - resp, err := s.{{ .MethodName}}({{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName }}req{{end}}) + resp, err := s.{{ .MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName }}req{{end}}) {{if .IsRenderOut -}} if err != nil { s.Render(c, nil, err) @@ -98,7 +99,7 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField s.Render(c, resp, err) {{- end }} {{- else -}} - s.Render(c, nil, s.{{.MethodName}}({{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) + s.Render(c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) {{- end }} }{{end}}{{if .IsFieldChain }})...{{end}}) {{else if .JustHttpAny}} router.Any("{{.Path}}", {{if .IsFieldChain }}append(cc.Chain{{.MethodName}}(), {{end}}{{if .JustUseContext}}s.{{ .MethodName}}{{else}}func(c *gin.Context) { @@ -122,7 +123,7 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField } {{- end }} {{if notEmptyStr .OutName -}} - resp, err := s.{{ .MethodName}}({{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}}) + resp, err := s.{{ .MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}}) {{if .IsRenderOut -}} if err != nil { s.Render(c, nil, err) @@ -134,7 +135,7 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField s.Render(c, resp, err) {{- end }} {{- else -}} - s.Render(c, nil, s.{{.MethodName}}({{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) + s.Render(c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) {{- end }} }{{end}}{{if .IsFieldChain }})...{{end}}) {{else}}{{$field := .}} { @@ -159,7 +160,7 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField } {{- end }} {{if notEmptyStr .OutName -}} - resp, err := s.{{ .MethodName}}({{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}}) + resp, err := s.{{ .MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}}) {{if .IsRenderOut -}} if err != nil { s.Render(c, nil, err) @@ -171,7 +172,7 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField s.Render(c, resp, err) {{- end }} {{- else -}} - s.Render(c, nil, s.{{.MethodName}}({{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) + s.Render(c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) {{- end }} }{{end}}{{if .IsFieldChain }}){{end}} {{range .AnyHttpMethods}} router.Handle("{{.}}", "{{$field.Path}}", h{{if $field.IsFieldChain }}...{{end}}) @@ -191,7 +192,7 @@ func ({{$unimplementedServant}}){{.Chain}}() gin.HandlersChain { {{end}} {{range .Fields}} -func ({{$unimplementedServant}}){{if .JustUseContext}}{{ .MethodName}}(c *gin.Context){{else}}{{.MethodName}}({{if .IsUseContext }}c *gin.Context{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName }}req *{{ .InName }}{{end}}) {{if notEmptyStr .OutName }}(*{{ .OutName}}, mir.Error){{else}}mir.Error{{end}}{{end}} { +func ({{$unimplementedServant}}){{if .JustUseContext}}{{ .MethodName}}(c *gin.Context){{else}}{{.MethodName}}({{if .IsUseRequestContext }}c context.Context{{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c *gin.Context{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName }}req *{{ .InName }}{{end}}) {{if notEmptyStr .OutName }}(*{{ .OutName}}, mir.Error){{else}}mir.Error{{end}}{{end}} { {{if .JustUseContext -}} c.String(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) {{else -}} diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 72fa942..b4fb1cf 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -28,10 +28,11 @@ func init() { // mirParser parse for struct tag type mirParser struct { - engineInfo *core.EngineInfo - tagName string - watchCtxDone bool - noneQuery bool + engineInfo *core.EngineInfo + tagName string + watchCtxDone bool + useRequestCtx bool + noneQuery bool } // Name name of parser @@ -49,6 +50,7 @@ func (p *mirParser) Init(opts *core.ParserOpts) error { } p.tagName = opts.DefaultTag p.watchCtxDone = opts.WatchCtxDone + p.useRequestCtx = opts.UseRequestCtx p.noneQuery = opts.NoneQuery if p.tagName == "" { p.tagName = defaultTag @@ -61,7 +63,7 @@ func (p *mirParser) Parse(entries []any) (core.Descriptors, error) { if len(entries) == 0 { return nil, errors.New("entries is empty") } - r := reflex.NewReflex(p.engineInfo, p.tagName, p.watchCtxDone, p.noneQuery) + r := reflex.NewReflex(p.engineInfo, p.tagName, p.watchCtxDone, p.useRequestCtx, p.noneQuery) return r.Parse(entries) } @@ -76,7 +78,7 @@ func (p *mirParser) ParseContext(ctx core.MirCtx, entries []any) { go func(ctx core.MirCtx, wg *sync.WaitGroup, ifaceSink chan<- *core.IfaceDescriptor, entry any) { defer wg.Done() - r := reflex.NewReflex(p.engineInfo, p.tagName, p.watchCtxDone, p.noneQuery) + r := reflex.NewReflex(p.engineInfo, p.tagName, p.watchCtxDone, p.useRequestCtx, p.noneQuery) iface, err := r.IfaceFrom(entry) if err != nil { core.Logus("ifaceFrom error: %s", err) diff --git a/internal/reflex/reflex.go b/internal/reflex/reflex.go index 9de71ff..05f0bd9 100644 --- a/internal/reflex/reflex.go +++ b/internal/reflex/reflex.go @@ -14,11 +14,12 @@ import ( // reflex real parser type reflex struct { - engineInfo *core.EngineInfo - ns naming.NamingStrategy - tagName string - watchCtxDone bool - noneQuery bool + engineInfo *core.EngineInfo + ns naming.NamingStrategy + tagName string + watchCtxDone bool + useRequestCtx bool + noneQuery bool } // Parse get Descriptors from parse entries @@ -74,14 +75,15 @@ func (r *reflex) IfaceFrom(entry any) (*core.IfaceDescriptor, error) { pkgPath := entryType.PkgPath() // get IfaceDescriptor from entryType and entryPtrType iface := &core.IfaceDescriptor{ - Imports: make(map[string]string), - EngineInfo: r.engineInfo, - VerInfo: core.VerInfo, - TypeName: entryType.Name(), - PkgPath: pkgPath, - PkgName: "api", // set default pkg name - Fields: make([]*core.FieldDescriptor, 0), - WatchCtxDone: r.watchCtxDone, + Imports: make(map[string]string), + EngineInfo: r.engineInfo, + VerInfo: core.VerInfo, + TypeName: entryType.Name(), + PkgPath: pkgPath, + PkgName: "api", // set default pkg name + Fields: make([]*core.FieldDescriptor, 0), + WatchCtxDone: r.watchCtxDone, + UseRequestCtx: r.useRequestCtx, } for i := entryType.NumField() - 1; i >= 0; i-- { field := entryType.Field(i) @@ -107,7 +109,7 @@ func (r *reflex) IfaceFrom(entry any) (*core.IfaceDescriptor, error) { return nil, errMultChainInfo } } - iface.Fields = append(iface.Fields, r.fieldFrom(tagInfo, pkgPath)) + iface.Fields = append(iface.Fields, r.fieldFrom(tagInfo, iface.UseRequestCtx, pkgPath)) case errNotExist: // normal field but had no mir tag info so just break to continue process next field default: @@ -129,31 +131,33 @@ func (r *reflex) inflateGroupInfo(d *core.IfaceDescriptor, v reflect.Value, t *t } // fieldFrom build tagField from entry and tagInfo -func (r *reflex) fieldFrom(t *tagInfo, pkgPath string) *core.FieldDescriptor { +func (r *reflex) fieldFrom(t *tagInfo, isUseReuestCtx bool, pkgPath string) *core.FieldDescriptor { return &core.FieldDescriptor{ - PkgPath: pkgPath, - IsAnyMethod: t.isAnyMethod, - IsFieldChain: t.isFieldChain, - IsUseContext: t.isUseContext, - HttpMethods: t.methods.List(), - IsBindIn: t.isBindIn, - IsRenderOut: t.isRenderOut, - In: t.in, - Out: t.out, - InOuts: t.inOuts, - Host: t.host, - Path: t.path, - Queries: t.queries, - MethodName: t.fieldName, + PkgPath: pkgPath, + IsAnyMethod: t.isAnyMethod, + IsFieldChain: t.isFieldChain, + IsUseContext: t.isUseContext, + IsUseRequestContext: isUseReuestCtx && !t.isUseContext, + HttpMethods: t.methods.List(), + IsBindIn: t.isBindIn, + IsRenderOut: t.isRenderOut, + In: t.in, + Out: t.out, + InOuts: t.inOuts, + Host: t.host, + Path: t.path, + Queries: t.queries, + MethodName: t.fieldName, } } -func NewReflex(info *core.EngineInfo, tagName string, watchCtxDone bool, noneQuery bool) *reflex { +func NewReflex(info *core.EngineInfo, tagName string, watchCtxDone bool, useRequestCtx bool, noneQuery bool) *reflex { return &reflex{ - engineInfo: info, - ns: naming.NewSnakeNamingStrategy(), - tagName: tagName, - watchCtxDone: watchCtxDone, - noneQuery: noneQuery, + engineInfo: info, + ns: naming.NewSnakeNamingStrategy(), + tagName: tagName, + watchCtxDone: watchCtxDone, + useRequestCtx: useRequestCtx, + noneQuery: noneQuery, } }