server/pkg/loafer/app/app.go

127 lines
3.2 KiB
Go
Raw Permalink Normal View History

2019-11-11 15:00:04 +00:00
package app
import (
2019-11-18 14:28:56 +00:00
"context"
2019-11-13 14:21:05 +00:00
"fmt"
2019-11-11 15:00:04 +00:00
"log"
2019-11-19 13:54:01 +00:00
"net/url"
2019-11-11 15:00:04 +00:00
"reflect"
2019-11-13 14:21:05 +00:00
"git.loafle.net/loafer/di-go"
2019-11-11 15:13:14 +00:00
appAnnotation "git.loafle.net/totopia/server/pkg/loafer/app/annotation"
webAnnotation "git.loafle.net/totopia/server/pkg/loafer/web/annotation"
2019-11-14 15:53:14 +00:00
"git.loafle.net/totopia/server/pkg/loafer/web/router"
2019-11-13 15:18:54 +00:00
"github.com/valyala/fasthttp"
2019-11-18 14:28:56 +00:00
2019-11-19 13:54:01 +00:00
"github.com/jackc/pgx/v4/pgxpool"
2019-11-11 15:00:04 +00:00
)
2019-11-13 14:21:05 +00:00
type MethodMapping struct {
Method string
ParamKeys []string
}
2019-11-13 15:18:54 +00:00
func Run(t reflect.Type) error {
2019-11-19 14:23:33 +00:00
pool, err := buildPgx(t)
if nil != err {
2019-11-19 13:54:01 +00:00
return fmt.Errorf("[%v]", err)
}
defer pool.Close()
2019-11-18 14:28:56 +00:00
2019-11-13 14:21:05 +00:00
taServer := di.GetTypeAnnotation(t, appAnnotation.ServerAnnotationType)
2019-11-11 15:13:14 +00:00
if nil == taServer {
2019-11-13 15:18:54 +00:00
return fmt.Errorf("[%s] is not Server, use @app:Server", t.Elem().Name())
2019-11-11 15:00:04 +00:00
}
2019-11-11 15:13:14 +00:00
aServer := taServer.(*appAnnotation.ServerAnnotation)
log.Printf("%s %d", t.Elem().Name(), aServer.HTTPPort)
2019-11-13 14:21:05 +00:00
restHandlers, err := di.GetInstancesByAnnotationType(webAnnotation.RestHandlerAnnotationType)
2019-11-11 15:13:14 +00:00
if nil != err {
2019-11-13 15:18:54 +00:00
return fmt.Errorf("[%v]", err)
2019-11-11 15:13:14 +00:00
}
2019-11-14 15:53:14 +00:00
r := router.New()
2019-11-11 15:13:14 +00:00
for _, restHandler := range restHandlers {
2019-11-14 15:53:14 +00:00
rha := parseRestHandler(restHandler)
parseRequestMapping(rha, r, restHandler)
2019-11-13 14:21:05 +00:00
}
2019-11-14 15:53:14 +00:00
if err := fasthttp.ListenAndServe(fmt.Sprintf(":%d", aServer.HTTPPort), r.Handler); nil != err {
2019-11-13 15:18:54 +00:00
return err
}
return nil
2019-11-13 14:21:05 +00:00
}
2019-11-19 14:23:33 +00:00
func buildPgx(t reflect.Type) (*pgxpool.Pool, error) {
taPgx := di.GetTypeAnnotation(t, webAnnotation.PgxAnnotationType)
if nil == taPgx {
return nil, fmt.Errorf("[%s] is not Pgx, use @web:Pgx", t.Elem().Name())
}
aPgx := taPgx.(*webAnnotation.PgxAnnotation)
pgURL := &url.URL{
Scheme: "postgres",
User: url.UserPassword(aPgx.User, aPgx.Password),
Path: aPgx.Database,
}
q := pgURL.Query()
if aPgx.SSLMode {
q.Add("sslmode", "enable")
} else {
q.Add("sslmode", "disable")
}
pgURL.RawQuery = q.Encode()
config, err := pgxpool.ParseConfig(pgURL.String())
if err != nil {
return nil, fmt.Errorf("[%v]", err)
}
config.ConnConfig.Host = aPgx.Host
config.ConnConfig.Port = aPgx.Port
pool, err := pgxpool.ConnectConfig(context.Background(), config)
if err != nil {
return nil, fmt.Errorf("[%v]", err)
}
di.RegisterResource("dbConnPool", pool)
return pool, nil
}
2019-11-14 15:53:14 +00:00
func parseRestHandler(restHandler interface{}) *webAnnotation.RestHandlerAnnotation {
2019-11-13 14:21:05 +00:00
t := reflect.TypeOf(restHandler)
ta := di.GetTypeAnnotation(t, webAnnotation.RestHandlerAnnotationType)
if nil == ta {
log.Printf("Service[%s] is not RESTService, use @RESTService", t.Elem().Name())
2019-11-14 15:53:14 +00:00
return nil
2019-11-13 14:21:05 +00:00
}
2019-11-14 15:53:14 +00:00
return ta.(*webAnnotation.RestHandlerAnnotation)
2019-11-13 14:21:05 +00:00
}
2019-11-14 15:53:14 +00:00
func parseRequestMapping(rha *webAnnotation.RestHandlerAnnotation, r *router.Router, restHandler interface{}) {
2019-11-13 14:21:05 +00:00
t := reflect.TypeOf(restHandler)
mas := di.GetMethodAnnotations(t, webAnnotation.RequestMappingAnnotationType)
if nil == mas || 0 == len(mas) {
return
}
2019-11-14 15:53:14 +00:00
mf := func(rh interface{}, mn string) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
reflect.ValueOf(rh).MethodByName(mn).Call([]reflect.Value{reflect.ValueOf(ctx)})
}
}
2019-11-13 14:21:05 +00:00
for methodName, v := range mas {
ma := v.(*webAnnotation.RequestMappingAnnotation)
2019-11-14 15:53:14 +00:00
entry := fmt.Sprintf("%s%s", rha.Entry, ma.Entry)
log.Printf("methodName %s entry %s", methodName, entry)
r.Handle(ma.Method, entry, mf(restHandler, methodName))
2019-11-11 15:13:14 +00:00
}
2019-11-11 15:00:04 +00:00
}