diff --git a/conf/env.go b/conf/env.go index 99befc55..c6b677ac 100644 --- a/conf/env.go +++ b/conf/env.go @@ -6,17 +6,21 @@ import ( "strings" ) +const envKey = "Env" +const ProdEnv = "prod" +const DevEnv = "dev" + type Env struct { Name string // env Name, like `prod`, `dev` and etc., Debugger bool // whether to use debugger } func (env *Env) IsDevelopment() bool { - return strings.EqualFold("dev", env.Name) + return strings.EqualFold(DevEnv, env.Name) } func (env *Env) IsProduction() bool { - return strings.EqualFold("prod", env.Name) + return strings.EqualFold(ProdEnv, env.Name) } func (env *Env) GetEnvName() *string { @@ -34,14 +38,14 @@ func getConfFilePath() *string { var Environment *Env func init() { - envName := "prod" - if len(os.Getenv("Env")) > 0 { - envName = os.Getenv("Env") + envName := ProdEnv + if len(os.Getenv(envKey)) > 0 { + envName = os.Getenv(envKey) } Environment = &Env{ Name: envName, Debugger: func() bool { - return envName != "prod" + return envName != ProdEnv }(), } } diff --git a/rpc_server/api/health.go b/rpc_server/api/health.go new file mode 100644 index 00000000..a2ec82ab --- /dev/null +++ b/rpc_server/api/health.go @@ -0,0 +1,27 @@ +package api + +import ( + "AAStarCommunity/EthPaymaster_BackService/conf" + "AAStarCommunity/EthPaymaster_BackService/rpc_server/models" + "github.com/gin-gonic/gin" + "time" +) + +// Healthz +// @Tags Healthz +// @Description Get Healthz +// @Accept json +// @Product json +// @Param +// @Router /api/health [post,get,put,delete] +// @Success 200 +func Healthz(c *gin.Context) { + response := models.GetResponse() + response.WithDataSuccess(c, gin.H{ + "hello": "Eth Paymaster", + "environment": conf.Environment.Name, + "time": time.Now(), + "version": "v1.0.0", + }) + response.Success(c) +} diff --git a/rpc_server/middlewares/logger.go b/rpc_server/middlewares/logger.go new file mode 100644 index 00000000..ef5a96b0 --- /dev/null +++ b/rpc_server/middlewares/logger.go @@ -0,0 +1,10 @@ +package middlewares + +import ( + "github.com/gin-gonic/gin" +) + +// LogHandler log handler +func LogHandler() gin.HandlerFunc { + return gin.Logger() +} diff --git a/rpc_server/middlewares/rate_limit.go b/rpc_server/middlewares/rate_limit.go index 4e5bed35..0d52d82d 100644 --- a/rpc_server/middlewares/rate_limit.go +++ b/rpc_server/middlewares/rate_limit.go @@ -15,8 +15,8 @@ const ( var limiter map[string]*rate.Limiter -// RateLimiterByApiKey represents the rate limit by each ApiKey for each api calling -func RateLimiterByApiKey() gin.HandlerFunc { +// RateLimiterByApiKeyHandler represents the rate limit by each ApiKey for each api calling +func RateLimiterByApiKeyHandler() gin.HandlerFunc { return func(ctx *gin.Context) { if exists, current := utils.CurrentUser(ctx); exists { diff --git a/rpc_server/middlewares/recovery.go b/rpc_server/middlewares/recovery.go index c86016e1..5bb6a889 100644 --- a/rpc_server/middlewares/recovery.go +++ b/rpc_server/middlewares/recovery.go @@ -10,8 +10,8 @@ import ( "strings" ) -// GenericRecovery represents the generic error(panic) process -func GenericRecovery() gin.HandlerFunc { +// GenericRecoveryHandler represents the generic error(panic) process +func GenericRecoveryHandler() gin.HandlerFunc { DefaultErrorWriter := &PanicExceptionRecord{} return gin.RecoveryWithWriter(DefaultErrorWriter, func(c *gin.Context, err interface{}) { errStr := "" diff --git a/rpc_server/routers/boot.go b/rpc_server/routers/boot.go index 051d19fc..94abcdb0 100644 --- a/rpc_server/routers/boot.go +++ b/rpc_server/routers/boot.go @@ -16,37 +16,44 @@ import ( func SetRouters() (routers *gin.Engine) { routers = gin.New() - // middlewares - handlers := make([]gin.HandlerFunc, 0) - handlers = append(handlers, middlewares.GenericRecovery()) + buildMod(routers) + buildRoute(routers) + routers.NoRoute(func(ctx *gin.Context) { + models.GetResponse().SetHttpCode(http.StatusNotFound).FailCode(ctx, http.StatusNotFound) + }) + + return +} +func buildRoute(routers *gin.Engine) { + // build http routers and middleware + routers.Use(middlewares.GenericRecoveryHandler()) if conf.Environment.IsDevelopment() { - handlers = append(handlers, gin.Logger()) + routers.Use(middlewares.LogHandler()) } - handlers = append(handlers, middlewares.CorsHandler()) + routers.Use(middlewares.CorsHandler()) + //build the routers not need api access like auth or Traffic limit + buildRouters(routers, PublicRouterMaps) + + routers.Use(middlewares.AuthHandler()) + routers.Use(middlewares.RateLimiterByApiKeyHandler()) + buildRouters(routers, PrivateRouterMaps) +} + +func buildMod(routers *gin.Engine) { // prod mode if conf.Environment.IsProduction() { gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = io.Discard // disable gin log + return } // dev mod if conf.Environment.IsDevelopment() { gin.SetMode(gin.DebugMode) buildSwagger(routers) + return } - - // use middlewares - routers.Use(handlers...) - - // build http routers - buildRouters(routers) - - routers.NoRoute(func(ctx *gin.Context) { - models.GetResponse().SetHttpCode(http.StatusNotFound).FailCode(ctx, http.StatusNotFound) - }) - - return } // buildSwagger build swagger diff --git a/rpc_server/routers/builder.go b/rpc_server/routers/builder.go index a3d62638..72c77a93 100644 --- a/rpc_server/routers/builder.go +++ b/rpc_server/routers/builder.go @@ -1,32 +1,23 @@ package routers import ( - "AAStarCommunity/EthPaymaster_BackService/rpc_server/api" - "AAStarCommunity/EthPaymaster_BackService/rpc_server/middlewares" "github.com/gin-gonic/gin" ) // buildRouters Build Routers -func buildRouters(router *gin.Engine) { - - router.POST("api/auth", api.Auth) - - router.Use(middlewares.AuthHandler()) - { - router.Use(middlewares.RateLimiterByApiKey()) - - for _, routerMap := range RouterMaps { - for _, method := range routerMap.Methods { - if method == GET { - router.GET(routerMap.Url, routerMap.Func) - } else if method == PUT { - router.PUT(routerMap.Url, routerMap.Func) - } else if method == POST { - router.POST(routerMap.Url, routerMap.Func) - } else if method == DELETE { - router.DELETE(routerMap.Url, routerMap.Func) - } // ignore rest methods - } +func buildRouters(router *gin.Engine, routerMaps []RouterMap) { + for _, routerMap := range routerMaps { + for _, method := range routerMap.Methods { + if method == GET { + router.GET(routerMap.Url, routerMap.Func) + } else if method == PUT { + router.PUT(routerMap.Url, routerMap.Func) + } else if method == POST { + router.POST(routerMap.Url, routerMap.Func) + } else if method == DELETE { + router.DELETE(routerMap.Url, routerMap.Func) + } // ignore rest methods } + } } diff --git a/rpc_server/routers/map.go b/rpc_server/routers/map.go deleted file mode 100644 index 1a9b78cf..00000000 --- a/rpc_server/routers/map.go +++ /dev/null @@ -1,18 +0,0 @@ -package routers - -import "github.com/gin-gonic/gin" - -type RestfulMethod string - -const ( - PUT RestfulMethod = "PUT" - GET RestfulMethod = "GET" - DELETE RestfulMethod = "DELETE" - POST RestfulMethod = "POST" -) - -type RouterMap struct { - Url string - Methods []RestfulMethod - Func func(ctx *gin.Context) -} diff --git a/rpc_server/routers/method_map.go b/rpc_server/routers/method_map.go new file mode 100644 index 00000000..0a89d780 --- /dev/null +++ b/rpc_server/routers/method_map.go @@ -0,0 +1,20 @@ +package routers + +import "github.com/gin-gonic/gin" + +type RestfulMethod string + +const ( + PUT RestfulMethod = "PUT" + GET RestfulMethod = "GET" + DELETE RestfulMethod = "DELETE" + POST RestfulMethod = "POST" + HEAD RestfulMethod = "HEAD" + OPTIONS RestfulMethod = "OPTIONS" +) + +type RouterMap struct { + Url string + Methods []RestfulMethod + Func func(ctx *gin.Context) +} diff --git a/rpc_server/routers/router_test.go b/rpc_server/routers/router_test.go new file mode 100644 index 00000000..b91e913c --- /dev/null +++ b/rpc_server/routers/router_test.go @@ -0,0 +1,8 @@ +package routers + +import "testing" + +func TestConst(t *testing.T) { + + t.Logf("%s", string(TryPayUserOperation)) +} diff --git a/rpc_server/routers/routers.go b/rpc_server/routers/routers.go deleted file mode 100644 index ed860980..00000000 --- a/rpc_server/routers/routers.go +++ /dev/null @@ -1,13 +0,0 @@ -package routers - -import v1 "AAStarCommunity/EthPaymaster_BackService/rpc_server/api/v1" - -var RouterMaps []RouterMap - -func init() { - RouterMaps = make([]RouterMap, 0) - - RouterMaps = append(RouterMaps, RouterMap{"api/v1/try-pay-user-operation", []RestfulMethod{POST}, v1.TryPayUserOperation}) - RouterMaps = append(RouterMaps, RouterMap{"api/v1/get-support-strategy", []RestfulMethod{GET}, v1.GetSupportStrategy}) - RouterMaps = append(RouterMaps, RouterMap{"api/v1/get-support-entrypoint", []RestfulMethod{GET}, v1.GetSupportEntrypoint}) -} diff --git a/rpc_server/routers/routers_map.go b/rpc_server/routers/routers_map.go new file mode 100644 index 00000000..ec90f12b --- /dev/null +++ b/rpc_server/routers/routers_map.go @@ -0,0 +1,29 @@ +package routers + +import ( + "AAStarCommunity/EthPaymaster_BackService/rpc_server/api" + v1 "AAStarCommunity/EthPaymaster_BackService/rpc_server/api/v1" +) + +var PrivateRouterMaps []RouterMap +var PublicRouterMaps []RouterMap + +func init() { + PrivateRouterMaps = make([]RouterMap, 0) + + PrivateRouterMaps = append(PrivateRouterMaps, RouterMap{string(TryPayUserOperation), []RestfulMethod{POST}, v1.TryPayUserOperation}) + PrivateRouterMaps = append(PrivateRouterMaps, RouterMap{string(GetSupportStrategy), []RestfulMethod{GET}, v1.GetSupportStrategy}) + PrivateRouterMaps = append(PrivateRouterMaps, RouterMap{string(GetSupportEntrypoint), []RestfulMethod{GET}, v1.GetSupportEntrypoint}) + PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(Auth), []RestfulMethod{POST}, api.Auth}) + PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(Healthz), []RestfulMethod{GET, HEAD, OPTIONS}, api.Healthz}) +} + +type Path string + +const ( + TryPayUserOperation Path = "api/v1/try-pay-user-operation" + GetSupportStrategy Path = "api/v1/get-support-strategy" + GetSupportEntrypoint Path = "api/v1/get-support-entrypoint" + Auth Path = "api/auth" + Healthz Path = "api/healthz" +)