diff --git a/.gitignore b/.gitignore index 75010477..7e3dc02d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,7 @@ .idea +.vscode + go.sum __debug_bin diff --git a/Framework/ApplicationEventPublisher.go b/Abstractions/ApplicationEventPublisher.go similarity index 98% rename from Framework/ApplicationEventPublisher.go rename to Abstractions/ApplicationEventPublisher.go index 06f611f9..8530fb88 100644 --- a/Framework/ApplicationEventPublisher.go +++ b/Abstractions/ApplicationEventPublisher.go @@ -1,4 +1,4 @@ -package YoyoGo +package Abstractions import "sync" diff --git a/Framework/ApplicationLife.go b/Abstractions/ApplicationLife.go similarity index 97% rename from Framework/ApplicationLife.go rename to Abstractions/ApplicationLife.go index c6cb1643..b95292ee 100644 --- a/Framework/ApplicationLife.go +++ b/Abstractions/ApplicationLife.go @@ -1,4 +1,4 @@ -package YoyoGo +package Abstractions const ( APPLICATION_LIFE_START = "APPLICATION_LIFE_START" diff --git a/Framework/Configuration.go b/Abstractions/Configuration.go similarity index 89% rename from Framework/Configuration.go rename to Abstractions/Configuration.go index 76be65d3..263ab548 100644 --- a/Framework/Configuration.go +++ b/Abstractions/Configuration.go @@ -1,6 +1,8 @@ -package YoyoGo +package Abstractions -import "github.com/spf13/viper" +import ( + "github.com/spf13/viper" +) type Configuration struct { context *ConfigurationContext diff --git a/Framework/ConfigurationBuilder.go b/Abstractions/ConfigurationBuilder.go similarity index 97% rename from Framework/ConfigurationBuilder.go rename to Abstractions/ConfigurationBuilder.go index 1cd063bc..02d45c22 100644 --- a/Framework/ConfigurationBuilder.go +++ b/Abstractions/ConfigurationBuilder.go @@ -1,4 +1,4 @@ -package YoyoGo +package Abstractions type ConfigurationContext struct { enableFlag bool diff --git a/Abstractions/HostBuildContext.go b/Abstractions/HostBuildContext.go new file mode 100644 index 00000000..9c562b7f --- /dev/null +++ b/Abstractions/HostBuildContext.go @@ -0,0 +1,14 @@ +package Abstractions + +import ( + "github.com/maxzhang1985/yoyogo/DependencyInjection" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" +) + +type HostBuildContext struct { + RequestDelegate interface{} + ApplicationCycle *ApplicationLife + HostingEnvironment *Context.HostEnvironment + ApplicationServicesDef *DependencyInjection.ServiceCollection + ApplicationServices DependencyInjection.IServiceProvider +} diff --git a/Abstractions/HostBuilder.go b/Abstractions/HostBuilder.go new file mode 100644 index 00000000..6d9233ae --- /dev/null +++ b/Abstractions/HostBuilder.go @@ -0,0 +1,118 @@ +package Abstractions + +import ( + "fmt" + "github.com/maxzhang1985/yoyogo" + "github.com/maxzhang1985/yoyogo/DependencyInjection" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "net" + "os" +) + +// host builder +type HostBuilder struct { + Server IServer // Server + Context *HostBuildContext // context of Host builder + Decorator IHostBuilderDecorator // host builder decorator or extension + configures []interface{} // []func(IApplicationBuilder), configure function by application builder. + servicesConfigures []func(*DependencyInjection.ServiceCollection) // configure function by ServiceCollection of DI. + lifeConfigure func(*ApplicationLife) // on application life event +} + +// Configure function func(IApplicationBuilder) +func (host *HostBuilder) Configure(configure interface{}) *HostBuilder { + host.configures = append(host.configures, configure) + return host +} + +// ConfigureServices configure function by ServiceCollection of DI. +func (host *HostBuilder) ConfigureServices(configure func(*DependencyInjection.ServiceCollection)) *HostBuilder { + host.servicesConfigures = append(host.servicesConfigures, configure) + return host +} + +// OnApplicationLifeEvent on application life event +func (host *HostBuilder) OnApplicationLifeEvent(lifeConfigure func(*ApplicationLife)) *HostBuilder { + host.lifeConfigure = lifeConfigure + return host +} + +// UseServer set IServer to host builder +func (host *HostBuilder) UseServer(server IServer) *HostBuilder { + host.Server = server + return host +} + +// getLocalIP get localhost ip +func getLocalIP() string { + var localIp string + addrs, err := net.InterfaceAddrs() + if err != nil { + fmt.Println(err) + } + for _, address := range addrs { + // 检查ip地址判断是否回环地址 + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + localIp = ipnet.IP.String() + break + } + } + } + return localIp +} + +// RunningHostEnvironmentSetting ,get running env setting. +func RunningHostEnvironmentSetting(hostEnv *Context.HostEnvironment) { + hostEnv.Host = getLocalIP() + hostEnv.Port = DetectAddress(hostEnv.Addr) + hostEnv.PID = os.Getpid() +} + +//buildingHostEnvironmentSetting build each configuration by init , such as file or env or args ... +func buildingHostEnvironmentSetting(hostEnv *Context.HostEnvironment) { + hostEnv.ApplicationName = "app" + hostEnv.Version = YoyoGo.Version + hostEnv.Addr = ":8080" + + hostEnv.Args = os.Args + + if hostEnv.Profile == "" { + hostEnv.Profile = Context.Dev + } + +} + +// Build host +func (host *HostBuilder) Build() IServiceHost { + services := DependencyInjection.NewServiceCollection() + + buildingHostEnvironmentSetting(host.Context.HostingEnvironment) + host.Context.ApplicationCycle = NewApplicationLife() + + innerConfigures(host.Context, services) + for _, configure := range host.servicesConfigures { + configure(services) + } + + applicationBuilder := host.Decorator.OverrideNewApplicationBuilder() + + for _, configure := range host.configures { + //configure(applicationBuilder) + host.Decorator.OverrideConfigure(configure, applicationBuilder) + } + + host.Context.ApplicationServicesDef = services + applicationBuilder.SetHostBuildContext(host.Context) + host.Context.RequestDelegate = applicationBuilder.Build() // ServeHTTP(w http.ResponseWriter, r *http.Request) + host.Context.ApplicationServices = services.Build() //serviceProvider + + go host.lifeConfigure(host.Context.ApplicationCycle) + return host.Decorator.OverrideNewHost(host.Server, host.Context) +} + +// inner configures function for DI. +func innerConfigures(hostContext *HostBuildContext, serviceCollection *DependencyInjection.ServiceCollection) { + serviceCollection.AddSingleton(func() *ApplicationLife { return hostContext.ApplicationCycle }) + serviceCollection.AddSingleton(func() *Context.HostEnvironment { return hostContext.HostingEnvironment }) +} diff --git a/Abstractions/IApplicationBuilder.go b/Abstractions/IApplicationBuilder.go new file mode 100644 index 00000000..a71cf045 --- /dev/null +++ b/Abstractions/IApplicationBuilder.go @@ -0,0 +1,6 @@ +package Abstractions + +type IApplicationBuilder interface { + Build() interface{} + SetHostBuildContext(*HostBuildContext) +} diff --git a/Framework/IConfiguration.go b/Abstractions/IConfiguration.go similarity index 62% rename from Framework/IConfiguration.go rename to Abstractions/IConfiguration.go index 2024b9d5..a84ea314 100644 --- a/Framework/IConfiguration.go +++ b/Abstractions/IConfiguration.go @@ -1,4 +1,4 @@ -package YoyoGo +package Abstractions type IConfiguration interface { } diff --git a/Abstractions/IHostBuilderDecorator.go b/Abstractions/IHostBuilderDecorator.go new file mode 100644 index 00000000..330433e9 --- /dev/null +++ b/Abstractions/IHostBuilderDecorator.go @@ -0,0 +1,12 @@ +package Abstractions + +// IHostBuilderDecorator Host Builder decorator or extension +type IHostBuilderDecorator interface { + + // OverrideConfigure is configure function by application builder. + OverrideConfigure(configureFunc interface{}, builder IApplicationBuilder) + // OverrideNewApplicationBuilder create application builder. + OverrideNewApplicationBuilder() IApplicationBuilder + // OverrideNewHost Create IServiceHost. + OverrideNewHost(server IServer, context *HostBuildContext) IServiceHost +} diff --git a/Framework/IRequestDelegate.go b/Abstractions/IRequestDelegate.go similarity index 83% rename from Framework/IRequestDelegate.go rename to Abstractions/IRequestDelegate.go index 33159036..8a438c9b 100644 --- a/Framework/IRequestDelegate.go +++ b/Abstractions/IRequestDelegate.go @@ -1,4 +1,4 @@ -package YoyoGo +package Abstractions import "net/http" diff --git a/Framework/IServer.go b/Abstractions/IServer.go similarity index 57% rename from Framework/IServer.go rename to Abstractions/IServer.go index a8c2478d..85dbc3c1 100644 --- a/Framework/IServer.go +++ b/Abstractions/IServer.go @@ -1,6 +1,13 @@ -package YoyoGo +package Abstractions -import "os" +import ( + "os" +) + +const ( + // DefaultAddress is used if no other is specified. + DefaultAddress = ":8080" +) type IServer interface { GetAddr() string @@ -8,7 +15,7 @@ type IServer interface { Shutdown() } -func detectAddress(addr ...string) string { +func DetectAddress(addr ...string) string { if len(addr) > 0 { return addr[0] } diff --git a/Abstractions/IServiceHost.go b/Abstractions/IServiceHost.go new file mode 100644 index 00000000..5322b6ca --- /dev/null +++ b/Abstractions/IServiceHost.go @@ -0,0 +1,8 @@ +package Abstractions + +type IServiceHost interface { + Run() + Shutdown() + StopApplicationNotify() + SetAppMode(mode string) +} diff --git a/Abstractions/Platform/exitsignal_darwin.go b/Abstractions/Platform/exitsignal_darwin.go new file mode 100644 index 00000000..ecfb89fd --- /dev/null +++ b/Abstractions/Platform/exitsignal_darwin.go @@ -0,0 +1,48 @@ +package Platform + +import ( + "fmt" + "os" + "os/signal" + "syscall" + "time" +) + +func HookSignals(host Abstract.IServiceHost) { + quitSig := make(chan os.Signal) + signal.Notify( + quitSig, + syscall.SIGHUP, + syscall.SIGINT, + syscall.SIGTERM, + syscall.SIGQUIT, + syscall.SIGSTOP, + syscall.SIGUSR1, + syscall.SIGUSR2, + syscall.SIGKILL, + ) + + go func() { + var sig os.Signal + for { + sig = <-quitSig + fmt.Println() + switch sig { + case syscall.SIGQUIT: + host.StopApplicationNotify() + host.Shutdown() + os.Exit(0) + // graceful stop + case syscall.SIGHUP: + host.StopApplicationNotify() + host.Shutdown() + case syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM: + host.StopApplicationNotify() + host.Shutdown() + os.Exit(0) + // terminate now + } + time.Sleep(time.Second * 3) + } + }() +} diff --git a/Abstractions/Platform/exitsignal_linux.go b/Abstractions/Platform/exitsignal_linux.go new file mode 100644 index 00000000..ecfb89fd --- /dev/null +++ b/Abstractions/Platform/exitsignal_linux.go @@ -0,0 +1,48 @@ +package Platform + +import ( + "fmt" + "os" + "os/signal" + "syscall" + "time" +) + +func HookSignals(host Abstract.IServiceHost) { + quitSig := make(chan os.Signal) + signal.Notify( + quitSig, + syscall.SIGHUP, + syscall.SIGINT, + syscall.SIGTERM, + syscall.SIGQUIT, + syscall.SIGSTOP, + syscall.SIGUSR1, + syscall.SIGUSR2, + syscall.SIGKILL, + ) + + go func() { + var sig os.Signal + for { + sig = <-quitSig + fmt.Println() + switch sig { + case syscall.SIGQUIT: + host.StopApplicationNotify() + host.Shutdown() + os.Exit(0) + // graceful stop + case syscall.SIGHUP: + host.StopApplicationNotify() + host.Shutdown() + case syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM: + host.StopApplicationNotify() + host.Shutdown() + os.Exit(0) + // terminate now + } + time.Sleep(time.Second * 3) + } + }() +} diff --git a/Abstractions/Platform/exitsignal_windows.go b/Abstractions/Platform/exitsignal_windows.go new file mode 100644 index 00000000..cda57c3c --- /dev/null +++ b/Abstractions/Platform/exitsignal_windows.go @@ -0,0 +1,46 @@ +package Platform + +import ( + "fmt" + "github.com/maxzhang1985/yoyogo/Abstractions" + "os" + "os/signal" + "syscall" + "time" +) + +func HookSignals(host Abstractions.IServiceHost) { + quitSig := make(chan os.Signal) + signal.Notify( + quitSig, + syscall.SIGHUP, + syscall.SIGINT, + syscall.SIGTERM, + syscall.SIGQUIT, + syscall.SIGKILL, + ) + + go func() { + var sig os.Signal + for { + sig = <-quitSig + fmt.Println() + switch sig { + case syscall.SIGQUIT: + host.StopApplicationNotify() + host.Shutdown() + os.Exit(0) + // graceful stop + case syscall.SIGHUP: + host.StopApplicationNotify() + host.Shutdown() + case syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM: + host.StopApplicationNotify() + host.Shutdown() + os.Exit(0) + // terminate now + } + time.Sleep(time.Second * 3) + } + }() +} diff --git a/Cli.go b/Cli.go new file mode 100644 index 00000000..64c92aa7 --- /dev/null +++ b/Cli.go @@ -0,0 +1,5 @@ +package YoyoGo + +func main() { + println("hello Yoyo") +} diff --git a/Controller/ControllerBuilder.go b/Controller/ControllerBuilder.go deleted file mode 100644 index 7ec5cc32..00000000 --- a/Controller/ControllerBuilder.go +++ /dev/null @@ -1,21 +0,0 @@ -package Controller - -import ( - "github.com/maxzhang1985/yoyogo/DependencyInjection" - "github.com/maxzhang1985/yoyogo/Utils" - "strings" -) - -type ControllerBuilder struct { - services *DependencyInjection.ServiceCollection -} - -func NewControllerBuilder(sc *DependencyInjection.ServiceCollection) *ControllerBuilder { - return &ControllerBuilder{services: sc} -} - -func (builder *ControllerBuilder) AddController(controllerCtor interface{}) { - controllerName := Utils.GetCtorFuncName(controllerCtor) - controllerName = strings.ToLower(controllerName) - builder.services.AddSingletonByNameAndImplements(controllerName, controllerCtor, new(IController)) -} diff --git a/Examples/SimpleWeb/contollers/usercontroller.go b/Examples/SimpleWeb/contollers/usercontroller.go index b3e8fb31..9b57edc6 100644 --- a/Examples/SimpleWeb/contollers/usercontroller.go +++ b/Examples/SimpleWeb/contollers/usercontroller.go @@ -1,14 +1,14 @@ package contollers import ( - "github.com/maxzhang1985/yoyogo/ActionResult" - "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/Controller" "github.com/maxzhang1985/yoyogo/Examples/SimpleWeb/models" + "github.com/maxzhang1985/yoyogo/WebFramework/ActionResult" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Mvc" ) type UserController struct { - *Controller.ApiController + *Mvc.ApiController userAction models.IUserAction } @@ -17,18 +17,18 @@ func NewUserController(userAction models.IUserAction) *UserController { } type RegiserRequest struct { - Controller.RequestBody + Mvc.RequestBody UserName string `param:"username"` Password string `param:"password"` } func (this *UserController) Register(ctx *Context.HttpContext, request *RegiserRequest) ActionResult.IActionResult { - result := Controller.ApiResult{Success: true, Message: "ok", Data: request} + result := Mvc.ApiResult{Success: true, Message: "ok", Data: request} return ActionResult.Json{Data: result} } -func (this *UserController) GetInfo() Controller.ApiResult { +func (this *UserController) GetInfo() Mvc.ApiResult { return this.OK(this.userAction.Login("zhang")) } diff --git a/Examples/SimpleWeb/main.go b/Examples/SimpleWeb/main.go index 5be38730..32d761f0 100644 --- a/Examples/SimpleWeb/main.go +++ b/Examples/SimpleWeb/main.go @@ -2,13 +2,14 @@ package main import ( "fmt" - "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/Controller" + "github.com/maxzhang1985/yoyogo/Abstractions" "github.com/maxzhang1985/yoyogo/DependencyInjection" "github.com/maxzhang1985/yoyogo/Examples/SimpleWeb/contollers" "github.com/maxzhang1985/yoyogo/Examples/SimpleWeb/models" - "github.com/maxzhang1985/yoyogo/Framework" - "github.com/maxzhang1985/yoyogo/Router" + "github.com/maxzhang1985/yoyogo/WebFramework" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Mvc" + "github.com/maxzhang1985/yoyogo/WebFramework/Router" ) func main() { @@ -19,20 +20,20 @@ func main() { } //* Create the builder of Web host -func CreateCustomBuilder() *YoyoGo.HostBuilder { +func CreateCustomBuilder() *Abstractions.HostBuilder { return YoyoGo.NewWebHostBuilder(). //UseHttp(). UseFastHttp(). //UseServer(YoyoGo.DefaultHttps(":8080", "./Certificate/server.pem", "./Certificate/server.key")). - Configure(func(app *YoyoGo.ApplicationBuilder) { + Configure(func(app *YoyoGo.WebApplicationBuilder) { app.SetEnvironment(Context.Dev) app.UseStatic("Static") app.UseEndpoints(registerEndpointRouterConfig) - app.UseMvc() - app.ConfigureMvcParts(func(builder *Controller.ControllerBuilder) { + app.UseMvc(func(builder *Mvc.ControllerBuilder) { builder.AddController(contollers.NewUserController) }) + }). ConfigureServices(func(serviceCollection *DependencyInjection.ServiceCollection) { serviceCollection.AddTransientByImplements(models.NewUserAction, new(models.IUserAction)) @@ -93,8 +94,8 @@ func PostInfo(ctx *Context.HttpContext) { ctx.JSON(200, Context.M{"info": "hello world", "result": strResult}) } -func getApplicationLifeEvent(life *YoyoGo.ApplicationLife) { - printDataEvent := func(event YoyoGo.ApplicationEvent) { +func getApplicationLifeEvent(life *Abstractions.ApplicationLife) { + printDataEvent := func(event Abstractions.ApplicationEvent) { fmt.Printf("[yoyogo] Topic: %s; Event: %v\n", event.Topic, event.Data) } diff --git a/Framework/ApplicationBuilder.go b/Framework/ApplicationBuilder.go deleted file mode 100644 index 68ee3877..00000000 --- a/Framework/ApplicationBuilder.go +++ /dev/null @@ -1,148 +0,0 @@ -package YoyoGo - -import ( - "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/Controller" - "github.com/maxzhang1985/yoyogo/DependencyInjection" - "github.com/maxzhang1985/yoyogo/Middleware" - "github.com/maxzhang1985/yoyogo/Router" - "net/http" -) - -// HTTP methods -const ( - // DefaultAddress is used if no other is specified. - DefaultAddress = ":8080" -) - -//application builder struct -type ApplicationBuilder struct { - hostContext *HostBuildContext - routerBuilder Router.IRouterBuilder - middleware middleware - handlers []Handler - Profile string - routeConfigures []func(Router.IRouterBuilder) - mvcConfigures []func(builder *Controller.ControllerBuilder) -} - -// create classic application builder -func UseClassic() *ApplicationBuilder { - return &ApplicationBuilder{} -} - -//region Create the builder of Web host -func CreateDefaultBuilder(routerConfig func(router Router.IRouterBuilder)) *HostBuilder { - return NewWebHostBuilder(). - UseServer(DefaultHttpServer(DefaultAddress)). - Configure(func(app *ApplicationBuilder) { - app.UseStatic("Static") - app.UseEndpoints(routerConfig) - }) -} - -// create application builder when combo all handlers to middleware -func New(handlers ...Handler) *ApplicationBuilder { - return &ApplicationBuilder{ - handlers: handlers, - middleware: build(handlers), - } -} - -// create new application builder -func NewApplicationBuilder() *ApplicationBuilder { - routerBuilder := Router.NewRouterBuilder() - recovery := Middleware.NewRecovery() - logger := Middleware.NewLogger() - router := Middleware.NewRouter(routerBuilder) - self := New(logger, recovery, router) - self.routerBuilder = routerBuilder - return self -} - -// after create builder , apply router and logger and recovery middleware -func (self *ApplicationBuilder) UseMvc() *ApplicationBuilder { - self.routerBuilder.(*Router.DefaultRouterBuilder).UseMvc(true) - return self -} - -func (self *ApplicationBuilder) UseEndpoints(configure func(Router.IRouterBuilder)) *ApplicationBuilder { - self.routeConfigures = append(self.routeConfigures, configure) - return self -} - -func (this *ApplicationBuilder) ConfigureMvcParts(configure func(builder *Controller.ControllerBuilder)) *ApplicationBuilder { - this.mvcConfigures = append(this.mvcConfigures, configure) - return this -} - -func (this *ApplicationBuilder) buildEndPoints() { - for _, configure := range this.routeConfigures { - configure(this.routerBuilder) - } -} - -func (this *ApplicationBuilder) buildMvc(services *DependencyInjection.ServiceCollection) { - if this.routerBuilder.IsMvc() { - controllerBuilder := Controller.NewControllerBuilder(services) - for _, configure := range this.mvcConfigures { - configure(controllerBuilder) - } - } -} - -// build and combo all middleware to request delegate (ServeHTTP(w http.ResponseWriter, r *http.Request)) -func (this *ApplicationBuilder) Build() IRequestDelegate { - if this.hostContext == nil { - panic("hostContext is nil! please set.") - } - - this.hostContext.hostingEnvironment.Profile = this.Profile - this.middleware = build(this.handlers) - this.buildEndPoints() - this.buildMvc(this.hostContext.applicationServicesDef) - return this -} - -func (this *ApplicationBuilder) SetHostBuildContext(context *HostBuildContext) { - this.hostContext = context -} - -func (app *ApplicationBuilder) SetEnvironment(mode string) { - app.Profile = mode -} - -// apply middleware in builder -func (app *ApplicationBuilder) UseMiddleware(handler Handler) { - if handler == nil { - panic("handler cannot be nil") - } - app.handlers = append(app.handlers, handler) -} - -// apply static middleware in builder -func (app *ApplicationBuilder) UseStatic(path string) { - app.UseMiddleware(Middleware.NewStatic("Static")) -} - -// apply handler middleware in builder -func (app *ApplicationBuilder) UseHandler(handler http.Handler) { - app.UseMiddleware(wrap(handler)) -} - -// apply handler func middleware in builder -func (app *ApplicationBuilder) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { - app.UseMiddleware(wrapFunc(handlerFunc)) -} - -// apply handler func middleware in builder -func (app *ApplicationBuilder) UseFunc(handlerFunc HandlerFunc) { - app.UseMiddleware(handlerFunc) -} - -/* -Middleware of Server Handler , request port. -*/ -func (app *ApplicationBuilder) ServeHTTP(w http.ResponseWriter, r *http.Request) { - app.middleware.Invoke(Context.NewContext(w, r, app.hostContext.applicationServices)) -} diff --git a/Framework/HostBuildContext.go b/Framework/HostBuildContext.go deleted file mode 100644 index 1ffe8b68..00000000 --- a/Framework/HostBuildContext.go +++ /dev/null @@ -1,14 +0,0 @@ -package YoyoGo - -import ( - "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/DependencyInjection" -) - -type HostBuildContext struct { - RequestDelegate IRequestDelegate - ApplicationCycle *ApplicationLife - hostingEnvironment *Context.HostEnvironment - applicationServicesDef *DependencyInjection.ServiceCollection - applicationServices DependencyInjection.IServiceProvider -} diff --git a/Framework/HostBuilder.go b/Framework/HostBuilder.go deleted file mode 100644 index 7af254d5..00000000 --- a/Framework/HostBuilder.go +++ /dev/null @@ -1,110 +0,0 @@ -package YoyoGo - -import ( - "fmt" - "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/DependencyInjection" - "net" - "os" -) - -type HostBuilder struct { - server IServer - context *HostBuildContext - configures []func(*ApplicationBuilder) - servicesConfigures []func(*DependencyInjection.ServiceCollection) - lifeConfigure func(*ApplicationLife) -} - -func (self *HostBuilder) Configure(configure func(*ApplicationBuilder)) *HostBuilder { - self.configures = append(self.configures, configure) - return self -} - -func (self *HostBuilder) ConfigureServices(configure func(*DependencyInjection.ServiceCollection)) *HostBuilder { - self.servicesConfigures = append(self.servicesConfigures, configure) - return self -} - -func (self *HostBuilder) OnApplicationLifeEvent(lifeConfigure func(*ApplicationLife)) *HostBuilder { - self.lifeConfigure = lifeConfigure - return self -} - -func (self *HostBuilder) UseServer(server IServer) *HostBuilder { - self.server = server - return self -} - -func getLocalIP() string { - var localIp string - addrs, err := net.InterfaceAddrs() - if err != nil { - fmt.Println(err) - } - for _, address := range addrs { - // 检查ip地址判断是否回环地址 - if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { - if ipnet.IP.To4() != nil { - localIp = ipnet.IP.String() - break - } - } - } - return localIp -} - -func runningHostEnvironmentSetting(hostEnv *Context.HostEnvironment) { - hostEnv.Host = getLocalIP() - hostEnv.Port = detectAddress(hostEnv.Addr) - hostEnv.PID = os.Getpid() -} - -func buildingHostEnvironmentSetting(hostEnv *Context.HostEnvironment) { - // build each configuration by init , such as file or env or args ... - hostEnv.ApplicationName = "app" - hostEnv.Version = Version - hostEnv.Addr = ":8080" - - hostEnv.Args = os.Args - - if hostEnv.Profile == "" { - hostEnv.Profile = Context.Dev - } - -} - -func (self *HostBuilder) Build() WebHost { - services := DependencyInjection.NewServiceCollection() - - buildingHostEnvironmentSetting(self.context.hostingEnvironment) - self.context.ApplicationCycle = NewApplicationLife() - - configures(self.context, services) - for _, configure := range self.servicesConfigures { - configure(services) - } - - applicationBuilder := NewApplicationBuilder() - - for _, configure := range self.configures { - configure(applicationBuilder) - } - - self.context.applicationServicesDef = services - applicationBuilder.SetHostBuildContext(self.context) - self.context.RequestDelegate = applicationBuilder.Build() // ServeHTTP(w http.ResponseWriter, r *http.Request) - self.context.applicationServices = services.Build() //serviceProvider - - go self.lifeConfigure(self.context.ApplicationCycle) - return NewWebHost(self.server, self.context) -} - -func configures(hostContext *HostBuildContext, serviceCollection *DependencyInjection.ServiceCollection) { - serviceCollection.AddSingleton(func() *ApplicationLife { return hostContext.ApplicationCycle }) - serviceCollection.AddSingleton(func() *Context.HostEnvironment { return hostContext.hostingEnvironment }) -} - -func NewWebHostBuilder() *HostBuilder { - return &HostBuilder{context: &HostBuildContext{hostingEnvironment: &Context.HostEnvironment{}}} -} diff --git a/Framework/IApplictionBuilder.go b/Framework/IApplictionBuilder.go deleted file mode 100644 index a3c6864f..00000000 --- a/Framework/IApplictionBuilder.go +++ /dev/null @@ -1,5 +0,0 @@ -package YoyoGo - -type IApplictionBuilder interface { - Build() interface{} -} diff --git a/Framework/Version.go b/Framework/Version.go deleted file mode 100644 index 127ade76..00000000 --- a/Framework/Version.go +++ /dev/null @@ -1,5 +0,0 @@ -package YoyoGo - -const ( - Version = "v1.4.9.3 pre-release" -) diff --git a/Framework/WebHostBuilderEx.go b/Framework/WebHostBuilderEx.go deleted file mode 100644 index c0ee1b9a..00000000 --- a/Framework/WebHostBuilderEx.go +++ /dev/null @@ -1,21 +0,0 @@ -package YoyoGo - -func (self *HostBuilder) UseFastHttpByAddr(addr string) *HostBuilder { - self.server = NewFastHttp(addr) - return self -} - -func (self *HostBuilder) UseFastHttp() *HostBuilder { - self.server = NewFastHttp("") - return self -} - -func (self *HostBuilder) UseHttpByAddr(addr string) *HostBuilder { - self.server = DefaultHttpServer(addr) - return self -} - -func (self *HostBuilder) UseHttp() *HostBuilder { - self.server = DefaultHttpServer("") - return self -} diff --git a/README-ZHCN.md b/README-ZHCN.md index 2aea7076..6fed4d47 100644 --- a/README-ZHCN.md +++ b/README-ZHCN.md @@ -3,10 +3,11 @@ YoyoGo 是一个用 Go 编写的简单,轻便,快速的 Web 框架。 ![Release](https://img.shields.io/github/v/tag/maxzhang1985/yoyogo.svg?color=24B898&label=release&logo=github&sort=semver) [![Build Status](https://img.shields.io/travis/maxzhang1985/yoyogo.svg)](https://travis-ci.org/maxzhang1985/yoyogo) -[![Report](https://goreportcard.com/badge/github.com/maxzhang1985/yoyogo)](https://goreportcard.com/report/github.com/maxzhang1985/yoyogo) -[![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg?color=24B898&logo=go&logoColor=ffffff)](https://godoc.org/github.com/maxzhang1985/yoyogo) +[![Goproxy](https://goproxy.cn/stats/github.com/maxzhang1985/yoyogo/badges/download-count.svg)](https://goproxy.cn/stats/github.com/maxzhang1985/yoyogo) ![GoVersion](https://img.shields.io/github/go-mod/go-version/maxzhang1985/yoyogo) ![DockerPull](https://img.shields.io/docker/pulls/maxzhang1985/yoyogo) +[![Report](https://goreportcard.com/badge/github.com/maxzhang1985/yoyogo)](https://goreportcard.com/report/github.com/maxzhang1985/yoyogo) +[![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg?color=24B898&logo=go&logoColor=ffffff)](https://godoc.org/github.com/maxzhang1985/yoyogo) ![Contributors](https://img.shields.io/github/contributors/maxzhang1985/yoyogo.svg) [![License](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) diff --git a/README.md b/README.md index a656b9f5..f2899139 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,11 @@ YoyoGo is a simple, light and fast Web framework written in Go. ![Release](https://img.shields.io/github/v/tag/maxzhang1985/yoyogo.svg?color=24B898&label=release&logo=github&sort=semver) [![Build Status](https://img.shields.io/travis/maxzhang1985/yoyogo.svg)](https://travis-ci.org/maxzhang1985/yoyogo) -[![Report](https://goreportcard.com/badge/github.com/maxzhang1985/yoyogo)](https://goreportcard.com/report/github.com/maxzhang1985/yoyogo) -[![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg?color=24B898&logo=go&logoColor=ffffff)](https://godoc.org/github.com/maxzhang1985/yoyogo) +[![Goproxy](https://goproxy.cn/stats/github.com/maxzhang1985/yoyogo/badges/download-count.svg)](https://goproxy.cn/stats/github.com/maxzhang1985/yoyogo) ![GoVersion](https://img.shields.io/github/go-mod/go-version/maxzhang1985/yoyogo) ![DockerPull](https://img.shields.io/docker/pulls/maxzhang1985/yoyogo) +[![Report](https://goreportcard.com/badge/github.com/maxzhang1985/yoyogo)](https://goreportcard.com/report/github.com/maxzhang1985/yoyogo) +[![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg?color=24B898&logo=go&logoColor=ffffff)](https://godoc.org/github.com/maxzhang1985/yoyogo) ![Contributors](https://img.shields.io/github/contributors/maxzhang1985/yoyogo.svg) [![License](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) diff --git a/Test/di_test.go b/Test/di_test.go index 40afc029..34bc541d 100644 --- a/Test/di_test.go +++ b/Test/di_test.go @@ -2,8 +2,8 @@ package Test import ( "github.com/magiconair/properties/assert" - "github.com/maxzhang1985/yoyogo/Context" "github.com/maxzhang1985/yoyogo/DependencyInjection" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "testing" ) diff --git a/Test/render_test.go b/Test/render_test.go index f143ad9a..07432ad1 100644 --- a/Test/render_test.go +++ b/Test/render_test.go @@ -5,8 +5,8 @@ import ( "encoding/xml" "errors" "github.com/golang/protobuf/proto" - "github.com/maxzhang1985/yoyogo/ActionResult" "github.com/maxzhang1985/yoyogo/Test/testdata/protoexample" + "github.com/maxzhang1985/yoyogo/WebFramework/ActionResult" "github.com/stretchr/testify/assert" "github.com/ugorji/go/codec" "html/template" diff --git a/Test/structtag_test.go b/Test/structtag_test.go index 5f95afac..2f509387 100644 --- a/Test/structtag_test.go +++ b/Test/structtag_test.go @@ -3,11 +3,11 @@ package Test import ( "fmt" "github.com/magiconair/properties/assert" - "github.com/maxzhang1985/yoyogo/Context" - _ "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/Controller" "github.com/maxzhang1985/yoyogo/Examples/SimpleWeb/contollers" "github.com/maxzhang1985/yoyogo/Utils" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + _ "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Mvc" "reflect" "testing" ) @@ -80,7 +80,7 @@ func Test_StructGetFieldTag(t *testing.T) { } func Test_RecCreateStruct(t *testing.T) { - yourtype := reflect.TypeOf(Controller.RequestBody{}) + yourtype := reflect.TypeOf(Mvc.RequestBody{}) dd := reflect.New(yourtype).Elem().Interface() _ = dd } diff --git a/Utils/ConsoleColor.go b/Utils/ConsoleColor.go new file mode 100644 index 00000000..36013897 --- /dev/null +++ b/Utils/ConsoleColor.go @@ -0,0 +1 @@ +package Utils diff --git a/Utils/ReflectHelper.go b/Utils/ReflectHelper.go index 6981ab6e..b8868555 100644 --- a/Utils/ReflectHelper.go +++ b/Utils/ReflectHelper.go @@ -12,7 +12,7 @@ func GetCtorFuncName(ctorFunc interface{}) string { } controllerType := ctorType.Out(0) if controllerType.Kind() != reflect.Ptr { - panic("Controller type must be Ptr ! ") + panic("Mvc type must be Ptr ! ") } controllerName := controllerType.Elem().Name() return controllerName diff --git a/Version.go b/Version.go new file mode 100644 index 00000000..4ee52fa6 --- /dev/null +++ b/Version.go @@ -0,0 +1,6 @@ +package YoyoGo + +const ( + Version = "v1.4.9.5" + //Version = "v1.4.9.5 pre-release" +) diff --git a/ActionResult/IActionResult.go b/WebFramework/ActionResult/IActionResult.go similarity index 100% rename from ActionResult/IActionResult.go rename to WebFramework/ActionResult/IActionResult.go diff --git a/ActionResult/data.go b/WebFramework/ActionResult/data.go similarity index 100% rename from ActionResult/data.go rename to WebFramework/ActionResult/data.go diff --git a/ActionResult/html.go b/WebFramework/ActionResult/html.go similarity index 100% rename from ActionResult/html.go rename to WebFramework/ActionResult/html.go diff --git a/ActionResult/json.go b/WebFramework/ActionResult/json.go similarity index 100% rename from ActionResult/json.go rename to WebFramework/ActionResult/json.go diff --git a/ActionResult/messagepack.go b/WebFramework/ActionResult/messagepack.go similarity index 100% rename from ActionResult/messagepack.go rename to WebFramework/ActionResult/messagepack.go diff --git a/ActionResult/protobuf.go b/WebFramework/ActionResult/protobuf.go similarity index 100% rename from ActionResult/protobuf.go rename to WebFramework/ActionResult/protobuf.go diff --git a/ActionResult/redirect.go b/WebFramework/ActionResult/redirect.go similarity index 100% rename from ActionResult/redirect.go rename to WebFramework/ActionResult/redirect.go diff --git a/ActionResult/text.go b/WebFramework/ActionResult/text.go similarity index 100% rename from ActionResult/text.go rename to WebFramework/ActionResult/text.go diff --git a/ActionResult/xml.go b/WebFramework/ActionResult/xml.go similarity index 100% rename from ActionResult/xml.go rename to WebFramework/ActionResult/xml.go diff --git a/ActionResult/yaml.go b/WebFramework/ActionResult/yaml.go similarity index 100% rename from ActionResult/yaml.go rename to WebFramework/ActionResult/yaml.go diff --git a/Context/DataBinding.go b/WebFramework/Context/DataBinding.go similarity index 100% rename from Context/DataBinding.go rename to WebFramework/Context/DataBinding.go diff --git a/Context/HostEnvironment.go b/WebFramework/Context/HostEnvironment.go similarity index 100% rename from Context/HostEnvironment.go rename to WebFramework/Context/HostEnvironment.go diff --git a/Context/HttpContext.go b/WebFramework/Context/HttpContext.go similarity index 99% rename from Context/HttpContext.go rename to WebFramework/Context/HttpContext.go index 3f66aa76..1d148138 100644 --- a/Context/HttpContext.go +++ b/WebFramework/Context/HttpContext.go @@ -6,9 +6,9 @@ import ( "encoding/xml" "errors" "fmt" - "github.com/maxzhang1985/yoyogo/ActionResult" "github.com/maxzhang1985/yoyogo/DependencyInjection" "github.com/maxzhang1985/yoyogo/Utils" + "github.com/maxzhang1985/yoyogo/WebFramework/ActionResult" "io" "io/ioutil" "mime/multipart" diff --git a/Context/consts.go b/WebFramework/Context/consts.go similarity index 100% rename from Context/consts.go rename to WebFramework/Context/consts.go diff --git a/Context/httpcontext_renderfunc.go b/WebFramework/Context/httpcontext_renderfunc.go similarity index 97% rename from Context/httpcontext_renderfunc.go rename to WebFramework/Context/httpcontext_renderfunc.go index 3b5dcf45..36be1f14 100644 --- a/Context/httpcontext_renderfunc.go +++ b/WebFramework/Context/httpcontext_renderfunc.go @@ -1,7 +1,7 @@ package Context import ( - "github.com/maxzhang1985/yoyogo/ActionResult" + "github.com/maxzhang1985/yoyogo/WebFramework/ActionResult" "net/http" ) diff --git a/Context/responseWriter.go b/WebFramework/Context/responseWriter.go similarity index 100% rename from Context/responseWriter.go rename to WebFramework/Context/responseWriter.go diff --git a/Framework/FastHttpServer.go b/WebFramework/FastHttpServer.go similarity index 73% rename from Framework/FastHttpServer.go rename to WebFramework/FastHttpServer.go index 430c3b80..2fe11980 100644 --- a/Framework/FastHttpServer.go +++ b/WebFramework/FastHttpServer.go @@ -1,12 +1,11 @@ package YoyoGo import ( + "github.com/maxzhang1985/yoyogo/Abstractions" "github.com/valyala/fasthttp" "github.com/valyala/fasthttp/fasthttpadaptor" "log" "net/http" - "os" - "os/signal" ) type FastHttpServer struct { @@ -23,30 +22,21 @@ func NewFastHttps(addr string, cert string, key string) FastHttpServer { return FastHttpServer{IsTLS: true, Addr: addr, CertFile: cert, KeyFile: key} } -func (server FastHttpServer) GetAddr() string { +func (server *FastHttpServer) GetAddr() string { return server.Addr } -func (server FastHttpServer) Run(context *HostBuildContext) (e error) { +func (server *FastHttpServer) Run(context *Abstractions.HostBuildContext) (e error) { - fastHttpHandler := fasthttpadaptor.NewFastHTTPHandler(context.RequestDelegate) + fastHttpHandler := fasthttpadaptor.NewFastHTTPHandler(context.RequestDelegate.(Abstractions.IRequestDelegate)) server.webserver = &fasthttp.Server{ Handler: fastHttpHandler, } - // 创建系统信号接收器 - quit := make(chan os.Signal) - signal.Notify(quit, os.Interrupt, os.Kill) - go func() { - <-quit - context.ApplicationCycle.StopApplication() - server.Shutdown() - }() - addr := server.Addr if server.Addr == "" { - addr = context.hostingEnvironment.Addr + addr = context.HostingEnvironment.Addr } context.ApplicationCycle.StartApplication() if server.IsTLS { @@ -65,7 +55,7 @@ func (server FastHttpServer) Run(context *HostBuildContext) (e error) { return e } -func (server FastHttpServer) Shutdown() { +func (server *FastHttpServer) Shutdown() { log.Println("Shutdown HTTP server...") if err := server.webserver.Shutdown(); err != nil { log.Fatal("Shutdown server:", err) diff --git a/Framework/HttpServer.go b/WebFramework/HttpServer.go similarity index 55% rename from Framework/HttpServer.go rename to WebFramework/HttpServer.go index 80cb9a79..af86c2ed 100644 --- a/Framework/HttpServer.go +++ b/WebFramework/HttpServer.go @@ -1,11 +1,10 @@ package YoyoGo import ( + "github.com/maxzhang1985/yoyogo/Abstractions" "golang.org/x/net/context" "log" "net/http" - "os" - "os/signal" ) type HttpServer struct { @@ -14,36 +13,28 @@ type HttpServer struct { webserver *http.Server } -func DefaultHttpServer(addr string) HttpServer { - return HttpServer{IsTLS: false, Addr: addr} +func DefaultHttpServer(addr string) *HttpServer { + return &HttpServer{IsTLS: false, Addr: addr} } -func DefaultHttps(addr string, cert string, key string) HttpServer { - return HttpServer{IsTLS: true, Addr: addr, CertFile: cert, KeyFile: key} +func DefaultHttps(addr string, cert string, key string) *HttpServer { + return &HttpServer{IsTLS: true, Addr: addr, CertFile: cert, KeyFile: key} } -func (server HttpServer) GetAddr() string { +func (server *HttpServer) GetAddr() string { return server.Addr } -func (server HttpServer) Run(context *HostBuildContext) (e error) { +func (server *HttpServer) Run(context *Abstractions.HostBuildContext) (e error) { addr := server.Addr if server.Addr == "" { - addr = context.hostingEnvironment.Addr + addr = context.HostingEnvironment.Addr } server.webserver = &http.Server{ Addr: addr, - Handler: context.RequestDelegate, + Handler: context.RequestDelegate.(Abstractions.IRequestDelegate), } - // 创建系统信号接收器 - quit := make(chan os.Signal) - signal.Notify(quit, os.Interrupt, os.Kill) - go func() { - <-quit - context.ApplicationCycle.StopApplication() - server.Shutdown() - }() context.ApplicationCycle.StartApplication() @@ -63,7 +54,7 @@ func (server HttpServer) Run(context *HostBuildContext) (e error) { return nil } -func (server HttpServer) Shutdown() { +func (server *HttpServer) Shutdown() { if err := server.webserver.Shutdown(context.Background()); err != nil { log.Fatal("Shutdown server:", err) } diff --git a/Framework/Middleware.go b/WebFramework/Middleware.go similarity index 96% rename from Framework/Middleware.go rename to WebFramework/Middleware.go index 749d4032..7b9e69e5 100644 --- a/Framework/Middleware.go +++ b/WebFramework/Middleware.go @@ -1,7 +1,7 @@ package YoyoGo import ( - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "net/http" ) diff --git a/Middleware/LoggerMiddleware.go b/WebFramework/Middleware/LoggerMiddleware.go similarity index 98% rename from Middleware/LoggerMiddleware.go rename to WebFramework/Middleware/LoggerMiddleware.go index d9d5d031..813461e8 100644 --- a/Middleware/LoggerMiddleware.go +++ b/WebFramework/Middleware/LoggerMiddleware.go @@ -2,7 +2,7 @@ package Middleware import ( "fmt" - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "html/template" "io/ioutil" "log" diff --git a/Middleware/RecoveryMiddleware.go b/WebFramework/Middleware/RecoveryMiddleware.go similarity index 99% rename from Middleware/RecoveryMiddleware.go rename to WebFramework/Middleware/RecoveryMiddleware.go index 462ede6b..328b54c6 100644 --- a/Middleware/RecoveryMiddleware.go +++ b/WebFramework/Middleware/RecoveryMiddleware.go @@ -2,7 +2,7 @@ package Middleware import ( "fmt" - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "html/template" "log" "net/http" diff --git a/Middleware/RouterMiddleware.go b/WebFramework/Middleware/RouterMiddleware.go similarity index 84% rename from Middleware/RouterMiddleware.go rename to WebFramework/Middleware/RouterMiddleware.go index 0f9721ab..be260b44 100644 --- a/Middleware/RouterMiddleware.go +++ b/WebFramework/Middleware/RouterMiddleware.go @@ -1,8 +1,8 @@ package Middleware import ( - "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/Router" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Router" "strings" ) diff --git a/Middleware/StaticMiddleware.go b/WebFramework/Middleware/StaticMiddleware.go similarity index 95% rename from Middleware/StaticMiddleware.go rename to WebFramework/Middleware/StaticMiddleware.go index f756c157..a6a0f474 100644 --- a/Middleware/StaticMiddleware.go +++ b/WebFramework/Middleware/StaticMiddleware.go @@ -1,7 +1,7 @@ package Middleware import ( - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "net/http" "os" "strings" diff --git a/WebFramework/Mvc/ActionDescriptor.go b/WebFramework/Mvc/ActionDescriptor.go new file mode 100644 index 00000000..0afa31e8 --- /dev/null +++ b/WebFramework/Mvc/ActionDescriptor.go @@ -0,0 +1,6 @@ +package Mvc + +type ActionDescriptor struct { + ActionName string + MethodInfo interface{} +} diff --git a/Controller/ActionExecutorContext.go b/WebFramework/Mvc/ActionExecutorContext.go similarity index 83% rename from Controller/ActionExecutorContext.go rename to WebFramework/Mvc/ActionExecutorContext.go index b7c220a3..363191de 100644 --- a/Controller/ActionExecutorContext.go +++ b/WebFramework/Mvc/ActionExecutorContext.go @@ -1,8 +1,8 @@ -package Controller +package Mvc import ( - "github.com/maxzhang1985/yoyogo/Context" "github.com/maxzhang1985/yoyogo/Utils" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "reflect" ) diff --git a/Controller/ActionMethodExecutor.go b/WebFramework/Mvc/ActionMethodExecutor.go similarity index 96% rename from Controller/ActionMethodExecutor.go rename to WebFramework/Mvc/ActionMethodExecutor.go index 9b38cdf4..eeca4a21 100644 --- a/Controller/ActionMethodExecutor.go +++ b/WebFramework/Mvc/ActionMethodExecutor.go @@ -1,8 +1,8 @@ -package Controller +package Mvc import ( - "github.com/maxzhang1985/yoyogo/Context" "github.com/maxzhang1985/yoyogo/Utils" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "net/http" "reflect" ) diff --git a/Controller/ApiController.go b/WebFramework/Mvc/ApiController.go similarity index 95% rename from Controller/ApiController.go rename to WebFramework/Mvc/ApiController.go index cf081f4f..05cf7853 100644 --- a/Controller/ApiController.go +++ b/WebFramework/Mvc/ApiController.go @@ -1,4 +1,4 @@ -package Controller +package Mvc type ApiController struct { } diff --git a/Controller/ApiResult.go b/WebFramework/Mvc/ApiResult.go similarity index 95% rename from Controller/ApiResult.go rename to WebFramework/Mvc/ApiResult.go index bce421c3..f78dfb84 100644 --- a/Controller/ApiResult.go +++ b/WebFramework/Mvc/ApiResult.go @@ -1,4 +1,4 @@ -package Controller +package Mvc import ( "encoding/json" diff --git a/Controller/ControllerActivator.go b/WebFramework/Mvc/ControllerActivator.go similarity index 94% rename from Controller/ControllerActivator.go rename to WebFramework/Mvc/ControllerActivator.go index b0e57544..cf1470c0 100644 --- a/Controller/ControllerActivator.go +++ b/WebFramework/Mvc/ControllerActivator.go @@ -1,4 +1,4 @@ -package Controller +package Mvc import "github.com/maxzhang1985/yoyogo/DependencyInjection" diff --git a/WebFramework/Mvc/ControllerBuilder.go b/WebFramework/Mvc/ControllerBuilder.go new file mode 100644 index 00000000..31f168ca --- /dev/null +++ b/WebFramework/Mvc/ControllerBuilder.go @@ -0,0 +1,43 @@ +package Mvc + +import ( + "github.com/maxzhang1985/yoyogo/Utils" + "strings" +) + +type ControllerBuilder struct { + controllerDescriptors []ControllerDescriptor + mvcRouterHandler *RouterHandler + Options MvcOptions +} + +// NewControllerBuilder new controller builder +func NewControllerBuilder() *ControllerBuilder { + return &ControllerBuilder{ + Options: MvcOptions{}, + mvcRouterHandler: &RouterHandler{}, + } +} + +// SetupOptions , setup mvc builder options +func (builder *ControllerBuilder) SetupOptions() { + +} + +// AddController add controller (ctor) to ioc. +func (builder *ControllerBuilder) AddController(controllerCtor interface{}) { + controllerName := Utils.GetCtorFuncName(controllerCtor) + controllerName = strings.ToLower(controllerName) + descriptor := NewControllerDescriptor(controllerName, controllerCtor) + builder.controllerDescriptors = append(builder.controllerDescriptors, descriptor) +} + +// GetControllerDescriptorList is get controller descriptor array +func (builder *ControllerBuilder) GetControllerDescriptorList() []ControllerDescriptor { + return builder.controllerDescriptors +} + +// GetRouterHandler is get mvc router handler. +func (builder *ControllerBuilder) GetRouterHandler() *RouterHandler { + return builder.mvcRouterHandler +} diff --git a/WebFramework/Mvc/ControllerDescriptor.go b/WebFramework/Mvc/ControllerDescriptor.go new file mode 100644 index 00000000..86ac7528 --- /dev/null +++ b/WebFramework/Mvc/ControllerDescriptor.go @@ -0,0 +1,10 @@ +package Mvc + +type ControllerDescriptor struct { + ControllerName string + ControllerType interface{} // ctor func of controller +} + +func NewControllerDescriptor(name string, controllerType interface{}) ControllerDescriptor { + return ControllerDescriptor{name, controllerType} +} diff --git a/Controller/IActionFilter.go b/WebFramework/Mvc/IActionFilter.go similarity index 87% rename from Controller/IActionFilter.go rename to WebFramework/Mvc/IActionFilter.go index 70580ef8..7118e263 100644 --- a/Controller/IActionFilter.go +++ b/WebFramework/Mvc/IActionFilter.go @@ -1,4 +1,4 @@ -package Controller +package Mvc type IActionFilter interface { OnActionExecuting(context ActionExecutorContext) bool diff --git a/WebFramework/Mvc/MvcOptions.go b/WebFramework/Mvc/MvcOptions.go new file mode 100644 index 00000000..94b6c555 --- /dev/null +++ b/WebFramework/Mvc/MvcOptions.go @@ -0,0 +1,4 @@ +package Mvc + +type MvcOptions struct { +} diff --git a/Router/MvcRouterHandler.go b/WebFramework/Mvc/MvcRouterHandler.go similarity index 69% rename from Router/MvcRouterHandler.go rename to WebFramework/Mvc/MvcRouterHandler.go index 826a16a9..6642d430 100644 --- a/Router/MvcRouterHandler.go +++ b/WebFramework/Mvc/MvcRouterHandler.go @@ -1,19 +1,16 @@ -package Router +package Mvc import ( - "github.com/maxzhang1985/yoyogo/ActionResult" - "github.com/maxzhang1985/yoyogo/Context" - "github.com/maxzhang1985/yoyogo/Controller" + "github.com/maxzhang1985/yoyogo/WebFramework/ActionResult" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "net/http" "strings" ) -type MvcRouterHandler struct { - actionFilters []Controller.IActionFilter - actionList map[string]map[string]string +type RouterHandler struct { } -func (handler *MvcRouterHandler) Invoke(ctx *Context.HttpContext, pathComponents []string) func(ctx *Context.HttpContext) { +func (handler *RouterHandler) Invoke(ctx *Context.HttpContext, pathComponents []string) func(ctx *Context.HttpContext) { if pathComponents == nil || len(pathComponents) < 2 { return nil @@ -24,21 +21,21 @@ func (handler *MvcRouterHandler) Invoke(ctx *Context.HttpContext, pathComponents } actionName := pathComponents[1] - controller, err := Controller.ActivateController(ctx.RequiredServices, controllerName) + controller, err := ActivateController(ctx.RequiredServices, controllerName) if err != nil { ctx.Response.WriteHeader(http.StatusNotFound) panic(controllerName + " controller is not found! " + err.Error()) } - actionMethodExecutor := Controller.NewActionMethodExecutor() - executorContext := &Controller.ActionExecutorContext{ + actionMethodExecutor := NewActionMethodExecutor() + executorContext := &ActionExecutorContext{ ControllerName: controllerName, Controller: controller, ActionName: actionName, Context: ctx, In: nil, } - executorContext.In = &Controller.ActionExecutorInParam{} + executorContext.In = &ActionExecutorInParam{} actionResult := actionMethodExecutor.Execute(executorContext) diff --git a/Controller/RequestBody.go b/WebFramework/Mvc/RequestBody.go similarity index 60% rename from Controller/RequestBody.go rename to WebFramework/Mvc/RequestBody.go index e283e061..79047777 100644 --- a/Controller/RequestBody.go +++ b/WebFramework/Mvc/RequestBody.go @@ -1,4 +1,4 @@ -package Controller +package Mvc type RequestBody struct { } diff --git a/Router/DefaultRouterBuilder.go b/WebFramework/Router/DefaultRouterBuilder.go similarity index 87% rename from Router/DefaultRouterBuilder.go rename to WebFramework/Router/DefaultRouterBuilder.go index 8685d370..b9474a42 100644 --- a/Router/DefaultRouterBuilder.go +++ b/WebFramework/Router/DefaultRouterBuilder.go @@ -1,13 +1,14 @@ package Router import ( - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Mvc" "net/url" "strings" ) type DefaultRouterBuilder struct { - mvcRouterHandler *MvcRouterHandler + mvcControllerBuilder *Mvc.ControllerBuilder endPointRouterHandler *EndPointRouterHandler } @@ -24,14 +25,18 @@ func NewRouterBuilder() IRouterBuilder { func (router *DefaultRouterBuilder) UseMvc(used bool) { if used { - router.mvcRouterHandler = &MvcRouterHandler{} + router.mvcControllerBuilder = Mvc.NewControllerBuilder() } else { - router.mvcRouterHandler = nil + router.mvcControllerBuilder = nil } } func (router *DefaultRouterBuilder) IsMvc() bool { - return router.mvcRouterHandler != nil + return router.mvcControllerBuilder != nil +} + +func (router *DefaultRouterBuilder) GetMvcBuilder() *Mvc.ControllerBuilder { + return router.mvcControllerBuilder } func (router *DefaultRouterBuilder) Search(ctx *Context.HttpContext, components []string, params url.Values) func(ctx *Context.HttpContext) { @@ -40,7 +45,7 @@ func (router *DefaultRouterBuilder) Search(ctx *Context.HttpContext, components handler = router.endPointRouterHandler.Invoke(ctx, pathComponents) if handler == nil && router.IsMvc() { - handler = router.mvcRouterHandler.Invoke(ctx, pathComponents) + handler = router.mvcControllerBuilder.GetRouterHandler().Invoke(ctx, pathComponents) } return handler diff --git a/Router/EndPointRouterHandler.go b/WebFramework/Router/EndPointRouterHandler.go similarity index 97% rename from Router/EndPointRouterHandler.go rename to WebFramework/Router/EndPointRouterHandler.go index 174abf94..58377c88 100644 --- a/Router/EndPointRouterHandler.go +++ b/WebFramework/Router/EndPointRouterHandler.go @@ -1,7 +1,7 @@ package Router import ( - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "net/url" "strings" ) diff --git a/Router/IRouterBuilder.go b/WebFramework/Router/IRouterBuilder.go similarity index 88% rename from Router/IRouterBuilder.go rename to WebFramework/Router/IRouterBuilder.go index 804ef6f2..d0e42f2b 100644 --- a/Router/IRouterBuilder.go +++ b/WebFramework/Router/IRouterBuilder.go @@ -1,13 +1,18 @@ package Router import ( - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Mvc" "net/url" ) type IRouterBuilder interface { IsMvc() bool + UseMvc(used bool) + + GetMvcBuilder() *Mvc.ControllerBuilder + Map(method string, path string, handler func(ctx *Context.HttpContext)) Search(ctx *Context.HttpContext, components []string, params url.Values) func(ctx *Context.HttpContext) diff --git a/Router/RouterGroup.go b/WebFramework/Router/RouterGroup.go similarity index 97% rename from Router/RouterGroup.go rename to WebFramework/Router/RouterGroup.go index 46eb89ad..f3ca7b89 100644 --- a/Router/RouterGroup.go +++ b/WebFramework/Router/RouterGroup.go @@ -1,7 +1,7 @@ package Router import ( - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" ) type RouterGroup struct { diff --git a/WebFramework/WebApplicationBuilder.go b/WebFramework/WebApplicationBuilder.go new file mode 100644 index 00000000..69a84f9d --- /dev/null +++ b/WebFramework/WebApplicationBuilder.go @@ -0,0 +1,154 @@ +package YoyoGo + +import ( + "github.com/maxzhang1985/yoyogo/Abstractions" + "github.com/maxzhang1985/yoyogo/DependencyInjection" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" + "github.com/maxzhang1985/yoyogo/WebFramework/Middleware" + "github.com/maxzhang1985/yoyogo/WebFramework/Mvc" + "github.com/maxzhang1985/yoyogo/WebFramework/Router" + "net/http" +) + +// HTTP methods + +//application builder struct +type WebApplicationBuilder struct { + hostContext *Abstractions.HostBuildContext // host build 's context + routerBuilder Router.IRouterBuilder // route builder of interface + middleware middleware + handlers []Handler + Profile string + routeConfigures []func(Router.IRouterBuilder) // endpoints router configure functions + mvcConfigures []func(builder *Mvc.ControllerBuilder) // mvc router configure functions +} + +// create classic application builder +func UseClassic() *WebApplicationBuilder { + return &WebApplicationBuilder{} +} + +//region Create the builder of Web host +func CreateDefaultBuilder(routerConfig func(router Router.IRouterBuilder)) *Abstractions.HostBuilder { + return NewWebHostBuilder(). + UseServer(DefaultHttpServer(Abstractions.DefaultAddress)). + Configure(func(app *WebApplicationBuilder) { + app.UseStatic("Static") + app.UseEndpoints(routerConfig) + }) +} + +// create application builder when combo all handlers to middleware +func New(handlers ...Handler) *WebApplicationBuilder { + return &WebApplicationBuilder{ + handlers: handlers, + middleware: build(handlers), + } +} + +// create new web application builder +func NewWebApplicationBuilder() *WebApplicationBuilder { + routerBuilder := Router.NewRouterBuilder() + recovery := Middleware.NewRecovery() + logger := Middleware.NewLogger() + router := Middleware.NewRouter(routerBuilder) + self := New(logger, recovery, router) + self.routerBuilder = routerBuilder + return self +} + +// UseMvc after create builder , apply router and logger and recovery middleware +func (self *WebApplicationBuilder) UseMvc(configure func(builder *Mvc.ControllerBuilder)) *WebApplicationBuilder { + if !self.routerBuilder.IsMvc() { + self.routerBuilder.UseMvc(true) + } + self.mvcConfigures = append(self.mvcConfigures, configure) + return self +} + +func (self *WebApplicationBuilder) UseEndpoints(configure func(Router.IRouterBuilder)) *WebApplicationBuilder { + self.routeConfigures = append(self.routeConfigures, configure) + return self +} + +func (this *WebApplicationBuilder) ConfigureMvcParts(configure func(builder *Mvc.ControllerBuilder)) *WebApplicationBuilder { + + return this +} + +func (this *WebApplicationBuilder) buildEndPoints() { + for _, configure := range this.routeConfigures { + configure(this.routerBuilder) + } +} + +func (this *WebApplicationBuilder) buildMvc(services *DependencyInjection.ServiceCollection) { + if this.routerBuilder.IsMvc() { + controllerBuilder := this.routerBuilder.GetMvcBuilder() + for _, configure := range this.mvcConfigures { + configure(controllerBuilder) + } + // add controllers to application services + controllerDescriptorList := controllerBuilder.GetControllerDescriptorList() + for _, descriptor := range controllerDescriptorList { + services.AddSingletonByNameAndImplements(descriptor.ControllerName, descriptor.ControllerType, new(Mvc.IController)) + } + } +} + +// build and combo all middleware to request delegate (ServeHTTP(w http.ResponseWriter, r *http.Request)) +// return Abstractions.IRequestDelegate type +func (this *WebApplicationBuilder) Build() interface{} { + if this.hostContext == nil { + panic("hostContext is nil! please set.") + } + + this.hostContext.HostingEnvironment.Profile = this.Profile + this.middleware = build(this.handlers) + this.buildEndPoints() + this.buildMvc(this.hostContext.ApplicationServicesDef) + return this +} + +func (this *WebApplicationBuilder) SetHostBuildContext(context *Abstractions.HostBuildContext) { + this.hostContext = context +} + +func (app *WebApplicationBuilder) SetEnvironment(mode string) { + app.Profile = mode +} + +// apply middleware in builder +func (app *WebApplicationBuilder) UseMiddleware(handler Handler) { + if handler == nil { + panic("handler cannot be nil") + } + app.handlers = append(app.handlers, handler) +} + +// apply static middleware in builder +func (app *WebApplicationBuilder) UseStatic(path string) { + app.UseMiddleware(Middleware.NewStatic("Static")) +} + +// apply handler middleware in builder +func (app *WebApplicationBuilder) UseHandler(handler http.Handler) { + app.UseMiddleware(wrap(handler)) +} + +// apply handler func middleware in builder +func (app *WebApplicationBuilder) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { + app.UseMiddleware(wrapFunc(handlerFunc)) +} + +// apply handler func middleware in builder +func (app *WebApplicationBuilder) UseFunc(handlerFunc HandlerFunc) { + app.UseMiddleware(handlerFunc) +} + +/* +Middleware of Server Handler , request port. +*/ +func (app *WebApplicationBuilder) ServeHTTP(w http.ResponseWriter, r *http.Request) { + app.middleware.Invoke(Context.NewContext(w, r, app.hostContext.ApplicationServices)) +} diff --git a/Framework/WebHost.go b/WebFramework/WebHost.go similarity index 64% rename from Framework/WebHost.go rename to WebFramework/WebHost.go index 85e59559..13e569a3 100644 --- a/Framework/WebHost.go +++ b/WebFramework/WebHost.go @@ -3,37 +3,46 @@ package YoyoGo import ( "encoding/base64" "fmt" - "github.com/maxzhang1985/yoyogo/Context" + "github.com/maxzhang1985/yoyogo/Abstractions" + "github.com/maxzhang1985/yoyogo/Abstractions/Platform" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" "log" "os" ) type WebHost struct { - HostContext *HostBuildContext - webServer IServer + HostContext *Abstractions.HostBuildContext + webServer Abstractions.IServer } -func NewWebHost(server IServer, hostContext *HostBuildContext) WebHost { +func NewWebHost(server Abstractions.IServer, hostContext *Abstractions.HostBuildContext) WebHost { return WebHost{webServer: server, HostContext: hostContext} } func (host WebHost) Run() { - hostEnv := host.HostContext.hostingEnvironment + hostEnv := host.HostContext.HostingEnvironment vlog := log.New(os.Stdout, "[yoyogo] ", 0) - runningHostEnvironmentSetting(hostEnv) + Abstractions.RunningHostEnvironmentSetting(hostEnv) printLogo(vlog, hostEnv) - vlog.Fatal(host.webServer.Run(host.HostContext)) + Platform.HookSignals(host) + _ = host.webServer.Run(host.HostContext) + +} + +func (host WebHost) StopApplicationNotify() { + host.HostContext.ApplicationCycle.StopApplication() } +// Shutdown is Graceful stop application func (host WebHost) Shutdown() { host.webServer.Shutdown() } func (host WebHost) SetAppMode(mode string) { - host.HostContext.hostingEnvironment.Profile = mode + host.HostContext.HostingEnvironment.Profile = mode } func printLogo(l *log.Logger, env *Context.HostEnvironment) { diff --git a/WebFramework/WebHostBuilder.go b/WebFramework/WebHostBuilder.go new file mode 100644 index 00000000..181cb8f1 --- /dev/null +++ b/WebFramework/WebHostBuilder.go @@ -0,0 +1,39 @@ +package YoyoGo + +import ( + "github.com/maxzhang1985/yoyogo/Abstractions" + "github.com/maxzhang1985/yoyogo/WebFramework/Context" +) + +type WebHostBuilder struct { + Abstractions.HostBuilder +} + +func NewWebHostBuilder() *WebHostBuilder { + return &WebHostBuilder{ + Abstractions.HostBuilder{ + Context: &Abstractions.HostBuildContext{HostingEnvironment: &Context.HostEnvironment{}}, + Decorator: NewWebHostBuilderDecorator(), + }, + } +} + +func (host *WebHostBuilder) UseFastHttpByAddr(addr string) *WebHostBuilder { + host.Server = NewFastHttp(addr) + return host +} + +func (host *WebHostBuilder) UseFastHttp() *WebHostBuilder { + host.Server = NewFastHttp("") + return host +} + +func (host *WebHostBuilder) UseHttpByAddr(addr string) *WebHostBuilder { + host.Server = DefaultHttpServer(addr) + return host +} + +func (host *WebHostBuilder) UseHttp() *WebHostBuilder { + host.Server = DefaultHttpServer("") + return host +} diff --git a/WebFramework/WebHostBuilderDecorator.go b/WebFramework/WebHostBuilderDecorator.go new file mode 100644 index 00000000..d1a63b6e --- /dev/null +++ b/WebFramework/WebHostBuilderDecorator.go @@ -0,0 +1,27 @@ +package YoyoGo + +import "github.com/maxzhang1985/yoyogo/Abstractions" + +type WebHostBuilderDecorator struct { +} + +// OverrideConfigure is configure function by web application builder. +func (decorator WebHostBuilderDecorator) OverrideConfigure(configureFunc interface{}, builder Abstractions.IApplicationBuilder) { + configureWebAppFunc := configureFunc.(func(applicationBuilder *WebApplicationBuilder)) + configureWebAppFunc(builder.(*WebApplicationBuilder)) +} + +// OverrideNewApplicationBuilder create web application builder. +func (decorator WebHostBuilderDecorator) OverrideNewApplicationBuilder() Abstractions.IApplicationBuilder { + return NewWebApplicationBuilder() +} + +// OverrideNewHost Create WebHost. +func (decorator WebHostBuilderDecorator) OverrideNewHost(server Abstractions.IServer, context *Abstractions.HostBuildContext) Abstractions.IServiceHost { + return NewWebHost(server, context) +} + +// NewWebHostBuilderDecorator WebHostBuilderDecorator. +func NewWebHostBuilderDecorator() WebHostBuilderDecorator { + return WebHostBuilderDecorator{} +} diff --git a/doc.go b/doc.go index 7e86ce30..20bb4c0b 100644 --- a/doc.go +++ b/doc.go @@ -98,4 +98,4 @@ // } // -package yoyogo +package YoyoGo diff --git a/go.mod b/go.mod index 76adf188..1b60f7bf 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/maxzhang1985/yoyogo -go 1.13 +go 1.14 require ( github.com/defval/inject/v2 v2.2.1