golang restframework plugin with gin+gorm, fast and high scalable
p.s: spring restframework like :)
打开终端输入
$ go get -u github.com/PolarPanda611/trinitygo
done.
- integrate gorm
- integrate gin
- fast register router
- customize middleware
- customize runtime (Tracing Analysis, user authentication , event bus ...)
- support automic request
- support customize validator ( API permission , data validation ...)
- support URL query analyze (search , filter , order by , preload ...)
- start server
// can see the example in example/http
trinitygo.SetConfigPath(configPath) // put config path here
// by default the health check is disabled
//trinitygo.EnableHealthCheckURL("/v1/ping") ==> // the health check path will be /baseurl/v1/ping
//trinitygo.EnableHealthCheckURL() ==> // if the path not set , the check path will be default /baseurl/ping
//trinitygo.SetHealthCheckDefaultHandler(handler) == > also can use this func to change the default health check handler
t := trinitygo.DefaultHTTP()
t.InitHTTP()
t.ServeHTTP()
- integrate gorm
// by default , trinitygo will install the gorm according the config
// config.toml
[database]
db_type = "postgres" #mysql postgres
server = "host=127.0.0.1 port=60901 user=trinity password= dbname=trinity sslmode=disable" #mysql option = charset=utf8&parseTime=True&loc=Local
table_prefix = "trinity_"
max_idle_conn = 10
max_open_conn = 100
f := func() *gorm.DB {
return db.DefaultInstallGORM(
app.config.GetDebug(),
true,
app.config.GetDBType(),
app.config.GetDBTablePrefix(),
app.config.GetDBServer(),
app.config.GetDbMaxIdleConn(),
app.config.GetDbMaxOpenConn(),
)
}
t := trinitygo.DefaultHTTP()
t.InstallDB(f)
t.InitHTTP()
t.ServeHTTP()
- fast register router
// example/http/domain/controller/http
// @BindController to trinitygo
// when init trinity and the trinity
// will auto register as root controller to
// the gin router
// @application.NewRequestMapping
// the new request mapping will add new router
// to trinity router
// @this example
// router :
// GET ---> /users/:id ==> GET func as the handler
// GET ---> /users ==> Getsssss func as the handler
func init() {
trinitygo.BindController("/users",
&sync.Pool{
New: func() interface{} {
controller := new(userControllerImpl)
return controller
},
},
application.NewRequestMapping(httputil.GET, "/:id", "GET", PermissionValidator([]string{"manager"}), gValidator, g1Validator),
// application.NewRequestMapping(httputil.GET, "/:id", "GET"),
application.NewRequestMapping(httputil.GET, "", "Getsssss"),
)
}
// You can bind your service and repository layer to container
// The container will auto dependency injection to your
// controller
func init() {
trinitygo.BindContainer(reflect.TypeOf(&userServiceImpl{}), &sync.Pool{
New: func() interface{} {
service := new(userServiceImpl)
return service
},
})
}
- customize middleware
// by default , trinity will register
// the following middleware
// runtime middleware
// logger middleware
// recovery middleware
// you can also add your middleware
// e.g :
// authentication middleware ...
...
t.UseMiddleware(mlogger.New(app))
t.UseMiddleware(httprecovery.New(app))
t.UseMiddleware(mruntime.New(app))
...
- customize runtime
// register your runtime key before trinity serve the service
//@param "trace_id" --> key of the runtime
//@param false --> if required , when the runtime is not existed in request
//@param func --> to create default value
//@param islog --> if this value will logging
// usage :
// Tracing Analysis : the trace_id will be passing in the whole lifecycle
// in your request , log middleware ,db logger ...
// DB callback : register in db callback , see callback in db/install (auto manager the updatetime , update user etc ..)
t.RegRuntimeKey(truntime.NewRuntimeKey("trace_id", false, func() string { return uuid.New().String() }, true))
t.RegRuntimeKey(truntime.NewRuntimeKey("user_id", false, func() string { return "" }, false))
t.RegRuntimeKey(truntime.NewRuntimeKey("user_name", false, func() string { return "" }, true))
- support automic request
// set true for atomic_request to
// open the automic_request ,
// your request will auto be wrapped
// in one transaction
// if you response err ,
// the transaction will be auto rollbacked
// if response normal ,
// the transaction will be auto commit
[app]
...
atomic_request = true
...
// if the controller you add the tag transaction
// this tag will replace the automic request
// if transaction is true , will get the db with tx
// if transaction is false , will get the db without tx
// UserController test
type userControllerImpl struct {
UserSrv service.UserService
Tctx application.Context `transaction:"false"`
}
- support customize validator
// see the example/http/domain/controller
// the validatior will run sorted
// PermissionValidator -> gValidator -> g1Validator
application.NewRequestMapping(httputil.GET, "/:id", "GET", PermissionValidator([]string{"manager"}), gValidator, g1Validator),
var gValidator = func(tctx application.Context) {
id, _ := strconv.Atoi(tctx.GinCtx().Param("id"))
if id < 3 {
tctx.HTTPResponseUnauthorizedErr(errors.New("gValidator no permission"))
}
return
}
var g1Validator = func(tctx application.Context) {
id, _ := strconv.Atoi(tctx.GinCtx().Param("id"))
if id > 3 {
tctx.HTTPResponseUnauthorizedErr(errors.New("g1Validator no permission"))
}
return
}
// PermissionValidator example validator
func PermissionValidator(requiredP []string) func(application.Context) {
return func(c application.Context) {
// c.GinCtx().Set("permission", []string{"employee"}) // no permission
c.GinCtx().Set("permission", []string{"employee", "manager"}) // ok
in := util.SliceInSlice(requiredP, c.GinCtx().GetStringSlice("permission"))
if !in {
c.HTTPResponseUnauthorizedErr(errors.New("np permission"))
}
}
}
-
support URL query analyze
- URL Query config
_userConfig *queryutil.QueryConfig = &queryutil.QueryConfig{
// TablePrefix : table prefix defined in config.toml
// the model User will be treated as "trinitygo_user"
TablePrefix: "trinitygo_",
// DbBackend: handle the authorization
// no effect with the url change
// the base filter
DbBackend: nil,
PageSize: 20,
FilterList: []string{"user_name", "user_name__ilike"},
OrderByList: []string{"id"},
SearchByList: []string{"user_name", "email"},
FilterCustomizeFunc: map[string]interface{}{
"test": func(db *gorm.DB, queryValue string) *gorm.DB {
fmt.Println("Where xxxxx = ?", queryValue)
return db.Where("xxxxx = ?", queryValue)
},
},
IsDebug: true,
}
)
## GRPC Server
```new GRPC server
// can see the example in example/server
trinitygo.SetConfigPath(configPath) // put config path here
t := trinitygo.DefaultGRPC()
t.RegRuntimeKey(truntime.NewRuntimeKey("trace_id", true, func() string { return "" }, true))
t.RegRuntimeKey(truntime.NewRuntimeKey("user_id", true, func() string { return "" }, true))
t.RegRuntimeKey(truntime.NewRuntimeKey("user_name", true, func() string { return "" }, true))
t.InitGRPC()
{
helloworldpb.RegisterGreeterServer(t.GetGRPCServer(), &grpc.Server{}) // register your grpc server here
}
t.ServeGRPC()