Merge branch 'dev' into permission
This commit is contained in:
commit
902f32ad3f
@ -1,6 +1,6 @@
|
||||
{
|
||||
"gamesapi_url": "https://game2006sapi-test.kingsome.cn",
|
||||
"redirect_url": "https://game2006api-test.kingsome.cn",
|
||||
"max_request_cache": 10,
|
||||
"max_concurrent_num": 10,
|
||||
"request_over_time": 30
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package app
|
||||
import (
|
||||
"f5"
|
||||
//. "main/global"
|
||||
"main/middleware"
|
||||
"mt"
|
||||
)
|
||||
|
||||
@ -30,7 +29,6 @@ func (this *app) Init() {
|
||||
f5.LoadMetaTable(mt.Table)
|
||||
this.registerDataSources()
|
||||
this.initCb()
|
||||
f5.GetApp().GetGinEngine().Use(middleware.CaCheck)
|
||||
}
|
||||
|
||||
func (this *app) UnInit() {
|
||||
|
@ -6,3 +6,6 @@ type App interface {
|
||||
|
||||
type RouterGroup interface {
|
||||
}
|
||||
|
||||
type ServiceMgr interface {
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
package constant
|
||||
|
||||
const (
|
||||
MAIL_DB = "maildb"
|
||||
)
|
||||
|
||||
const (
|
||||
APP_MODULE_IDX = iota
|
||||
ROUTER_MODULE_IDX
|
||||
CONTROLLER_MGR_MODULE_IDX
|
||||
SERVICE_MGR_MODULE_IDX
|
||||
MAX_MODULE_IDX
|
||||
)
|
||||
|
@ -9,15 +9,21 @@ import (
|
||||
|
||||
var modules [constant.MAX_MODULE_IDX]q5.Module
|
||||
var initOrders = []int32{
|
||||
constant.SERVICE_MGR_MODULE_IDX,
|
||||
constant.ROUTER_MODULE_IDX,
|
||||
}
|
||||
|
||||
var app common.App
|
||||
var serviceMgr common.ServiceMgr
|
||||
|
||||
func GetApp() common.App {
|
||||
return app
|
||||
}
|
||||
|
||||
func GetServiceMgr() common.ServiceMgr {
|
||||
return serviceMgr
|
||||
}
|
||||
|
||||
func RegModule(idx int32, m q5.Module) {
|
||||
fmt.Printf("RegModule module %d\n", idx)
|
||||
modules[idx] = m
|
||||
@ -26,10 +32,11 @@ func RegModule(idx int32, m q5.Module) {
|
||||
{
|
||||
app = m.(common.App)
|
||||
}
|
||||
case constant.ROUTER_MODULE_IDX:
|
||||
case constant.SERVICE_MGR_MODULE_IDX:
|
||||
{
|
||||
|
||||
serviceMgr = m.(common.ServiceMgr)
|
||||
}
|
||||
case constant.ROUTER_MODULE_IDX:
|
||||
default:
|
||||
{
|
||||
panic("unknow module")
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
_ "main/controller"
|
||||
. "main/global"
|
||||
_ "main/router"
|
||||
_ "main/service"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
|
@ -1,133 +1,4 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"f5"
|
||||
"fmt"
|
||||
"mt"
|
||||
"net/http"
|
||||
"q5"
|
||||
"time"
|
||||
|
||||
//. "main/global"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type RedirectInfo struct {
|
||||
trace_id string
|
||||
ori_req *gin.Context
|
||||
sig string
|
||||
sigtime int64
|
||||
}
|
||||
|
||||
var requestCache = q5.ConcurrentMap[string, []*RedirectInfo]{}
|
||||
var redirectRequest = q5.ConcurrentMap[string, *RedirectInfo]{}
|
||||
|
||||
func CaCheck(c *gin.Context) {
|
||||
accountId := c.DefaultQuery("account_id", "")
|
||||
|
||||
if accountId == "" || !lockAccount(accountId) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"errcode": 1004,
|
||||
"errmsg": "Too many requests",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
emptyreq := false
|
||||
|
||||
defer unlockAccount(accountId, emptyreq)
|
||||
|
||||
cache, exist := requestCache.Load(accountId)
|
||||
if !exist {
|
||||
pcache := make([]*RedirectInfo, 0, mt.Table.Config.GetMaxCache())
|
||||
cache = &pcache
|
||||
}
|
||||
|
||||
info := new(RedirectInfo)
|
||||
info.ori_req = c
|
||||
info.sigtime = f5.GetApp().GetRealSeconds()
|
||||
info.trace_id = fmt.Sprintf("%x%02x-%s", info.sigtime, len(*cache), accountId)
|
||||
info.sig = q5.Md5Str(c.Request.URL.RawQuery + info.trace_id)
|
||||
|
||||
if len(*cache) < int(mt.Table.Config.GetMaxCache()) {
|
||||
*cache = append(*cache, info)
|
||||
requestCache.Store(accountId, *cache)
|
||||
unlockAccount(accountId, emptyreq)
|
||||
|
||||
for {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
|
||||
if lockAccount(accountId) {
|
||||
reqlist, _ := requestCache.Load(accountId)
|
||||
if len(*reqlist) > 0 && (*reqlist)[0].trace_id == info.trace_id {
|
||||
req := (*reqlist)[0]
|
||||
(*reqlist) = (*reqlist)[1:]
|
||||
|
||||
if req.sigtime+int64(mt.Table.Config.GetById(0).GetRequestOverTime()) > f5.GetApp().GetRealSeconds() {
|
||||
redirectRequest.Store(accountId, req)
|
||||
CaForward(req.ori_req, req.sig, req.trace_id)
|
||||
redirectRequest.Delete(accountId)
|
||||
} else {
|
||||
req.ori_req.JSON(http.StatusOK, gin.H{
|
||||
"errcode": 1004,
|
||||
"errmsg": "Too many players",
|
||||
})
|
||||
}
|
||||
|
||||
if len(*reqlist) > 0 {
|
||||
requestCache.Store(accountId, *reqlist)
|
||||
} else {
|
||||
requestCache.Delete(accountId)
|
||||
emptyreq = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
unlockAccount(accountId, emptyreq)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"errcode": 1004,
|
||||
"errmsg": "Too many requests",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func VerifySig(c *gin.Context) {
|
||||
accountId := c.DefaultQuery("account_id", "")
|
||||
traceId := c.DefaultQuery("trace_id", "")
|
||||
sig := c.DefaultQuery("sig", "")
|
||||
|
||||
if accountId == "" || traceId == "" || sig == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"errcode": 1002,
|
||||
"errmsg": "empty params",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
failresp := gin.H{
|
||||
"errcode": 1002,
|
||||
"errmsg": "sig unavailable",
|
||||
}
|
||||
|
||||
req, exist := redirectRequest.Load(accountId)
|
||||
if !exist {
|
||||
c.JSON(http.StatusOK, failresp)
|
||||
return
|
||||
}
|
||||
|
||||
if (*req).sig != sig || (*req).trace_id != traceId ||
|
||||
(*req).sigtime+int64(mt.Table.Config.GetById(0).GetRequestOverTime()) < f5.GetApp().GetRealSeconds() {
|
||||
c.JSON(http.StatusOK, failresp)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"errcode": 0,
|
||||
"errmsg": "",
|
||||
})
|
||||
}
|
||||
|
@ -5,47 +5,108 @@ import (
|
||||
"mt"
|
||||
"net/http"
|
||||
"q5"
|
||||
|
||||
"main/service"
|
||||
"jccommon"
|
||||
"io/ioutil"
|
||||
"bytes"
|
||||
net_url "net/url"
|
||||
"strings"
|
||||
"errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func CaForward(c *gin.Context, sig string, traceid string) {
|
||||
func CaForward(c *gin.Context) {
|
||||
accountId := c.DefaultQuery("account_id", "")
|
||||
sessionId := c.DefaultQuery("session_id", "")
|
||||
|
||||
queryParams := c.Request.URL.Query()
|
||||
params := map[string]string{}
|
||||
for k, v := range queryParams {
|
||||
params[k] = v[0]
|
||||
}
|
||||
if sig != "" {
|
||||
params["sig"] = sig
|
||||
params["trace_id"] = traceid
|
||||
if !jccommon.IsValidSessionId(accountId, sessionId) {
|
||||
f5.RspErr(c, 500, "invalid session_id")
|
||||
c.Abort()
|
||||
service.SApiForward.IncInvalidSessionTimes()
|
||||
return
|
||||
}
|
||||
|
||||
fullrequrl := mt.Table.Config.GetById(0).GetRedirectUrl() + c.Request.URL.Path[5:]
|
||||
cb := func(rsp f5.HttpCliResponse) {
|
||||
if rsp.GetErr() != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"errcode": 1004,
|
||||
"errmsg": rsp.GetErr(),
|
||||
})
|
||||
cLock := service.SApiForward.AcquireLock(accountId)
|
||||
defer service.SApiForward.ReleaseLock(cLock)
|
||||
service.SApiForward.IncTotalTimes()
|
||||
beginTick := q5.GetTickCount()
|
||||
defer func() {
|
||||
costTime := q5.GetTickCount() - beginTick
|
||||
service.SApiForward.UpdateCostTime(costTime)
|
||||
}()
|
||||
newUrl := mt.Table.Config.GetById(0).GetRedirectUrl() + c.Request.URL.Path[5:]
|
||||
if !q5.StrContains(newUrl, "?") {
|
||||
newUrl = newUrl + "?"
|
||||
}
|
||||
{
|
||||
u := net_url.Values{}
|
||||
for k, v := range c.Request.URL.Query() {
|
||||
u.Set(k, v[0])
|
||||
}
|
||||
newUrl += u.Encode()
|
||||
}
|
||||
|
||||
var httpRequest *http.Request
|
||||
var createErr error
|
||||
switch strings.ToUpper(c.Request.Method) {
|
||||
case "GET": {
|
||||
service.SApiForward.IncGetTimes()
|
||||
httpRequest, createErr = http.NewRequest("GET", newUrl, nil)
|
||||
if !f5.IsOnlineEnv() {
|
||||
f5.GetSysLog().Info("CaForward method:%s newUrl:%s ", c.Request.Method, newUrl)
|
||||
}
|
||||
}
|
||||
case "POST": {
|
||||
service.SApiForward.IncPostTimes()
|
||||
if postData, err := c.GetRawData(); err == nil {
|
||||
httpRequest, createErr = http.NewRequest("POST", newUrl, bytes.NewBuffer(postData))
|
||||
contentType := c.GetHeader("Content-Type")
|
||||
if contentType != "" {
|
||||
httpRequest.Header.Set("Content-Type", contentType)
|
||||
}
|
||||
if !f5.IsOnlineEnv() {
|
||||
f5.GetSysLog().Info("CaForward method:%s newUrl:%s Content-Type:%s postData:%s",
|
||||
c.Request.Method,
|
||||
newUrl,
|
||||
contentType,
|
||||
postData)
|
||||
}
|
||||
} else {
|
||||
createErr = err
|
||||
}
|
||||
}
|
||||
default: {
|
||||
createErr = errors.New("method error")
|
||||
}
|
||||
}
|
||||
if createErr != nil {
|
||||
service.SApiForward.IncCreateErrTimes()
|
||||
f5.RspErr(c, 500, "create request error")
|
||||
c.Abort()
|
||||
f5.GetSysLog().Info("CaForward create request url:%s error:%s", newUrl, createErr)
|
||||
return
|
||||
}
|
||||
client := &http.Client{}
|
||||
if resp, err := client.Do(httpRequest); err == nil {
|
||||
defer resp.Body.Close()
|
||||
if bytes, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||
service.SApiForward.IncOkTimes()
|
||||
c.String(200, string(bytes))
|
||||
c.Abort()
|
||||
return
|
||||
} else {
|
||||
service.SApiForward.IncReadRspErrTimes()
|
||||
f5.RspErr(c, 500, "read response error")
|
||||
c.Abort()
|
||||
f5.GetSysLog().Info("CaForward read response url:%s eror:%s", newUrl, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.String(http.StatusOK, rsp.GetRawData())
|
||||
} else {
|
||||
service.SApiForward.IncDoErrTimes()
|
||||
f5.RspErr(c, 500, "client.Do error")
|
||||
c.Abort()
|
||||
f5.GetSysLog().Info("CaForward client.Do url:%s error:%s", newUrl, err)
|
||||
return
|
||||
}
|
||||
|
||||
switch c.Request.Method {
|
||||
case "GET":
|
||||
f5.GetHttpCliMgr().SendGoStyleRequest(
|
||||
fullrequrl,
|
||||
params,
|
||||
cb)
|
||||
case "POST":
|
||||
f5.GetHttpCliMgr().SendGoStylePost(
|
||||
fullrequrl,
|
||||
params,
|
||||
c.ContentType(),
|
||||
q5.GetPostBody(c.Request),
|
||||
cb)
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"q5"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var accountMutexmap q5.ConcurrentMap[string, *sync.Mutex]
|
||||
|
||||
func lockAccount(account string) bool {
|
||||
mutex, exist := accountMutexmap.Load(account)
|
||||
if !exist {
|
||||
tmp := new(sync.Mutex)
|
||||
mutex = &tmp
|
||||
}
|
||||
return (*mutex).TryLock()
|
||||
}
|
||||
|
||||
func unlockAccount(account string, del bool) {
|
||||
mutex, exist := accountMutexmap.Load(account)
|
||||
if exist {
|
||||
(*mutex).Unlock()
|
||||
if del {
|
||||
accountMutexmap.Delete(account)
|
||||
}
|
||||
}
|
||||
}
|
@ -20,15 +20,15 @@ func (this *ConfigTable) GetGameSApiUrl() string {
|
||||
|
||||
func (this *ConfigTable) GetSecretKey() string {
|
||||
return this.selfConf.GetSecretKey()
|
||||
|
||||
}
|
||||
|
||||
func (this *ConfigTable) GetMaxConcurrentNum() int32 {
|
||||
return this.selfConf.GetMaxConcurrentNum()
|
||||
}
|
||||
|
||||
func (this *ConfigTable) PostInit1() {
|
||||
this.selfConf = this.GetById(int64(0))
|
||||
if this.selfConf == nil {
|
||||
panic("gamesapi config无法读取本服配置")
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ConfigTable) GetMaxCache() int32 {
|
||||
return this.selfConf.GetMaxRequestCache()
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ type Config struct {
|
||||
gm_open int32
|
||||
gm_secret_key string
|
||||
redirect_url string
|
||||
max_request_cache int32
|
||||
max_concurrent_num int32
|
||||
request_over_time int32
|
||||
|
||||
_flags1_ uint64
|
||||
@ -90,11 +90,11 @@ func (this *Config) HasRedirectUrl() bool {
|
||||
return (this._flags1_ & (uint64(1) << 5)) > 0
|
||||
}
|
||||
|
||||
func (this *Config) GetMaxRequestCache() int32 {
|
||||
return this.max_request_cache
|
||||
func (this *Config) GetMaxConcurrentNum() int32 {
|
||||
return this.max_concurrent_num
|
||||
}
|
||||
|
||||
func (this *Config) HasMaxRequestCache() bool {
|
||||
func (this *Config) HasMaxConcurrentNum() bool {
|
||||
return (this._flags1_ & (uint64(1) << 6)) > 0
|
||||
}
|
||||
|
||||
@ -119,6 +119,6 @@ func (this *Config) LoadFromKv(kv map[string]interface{}) {
|
||||
f5.ReadMetaTableField(&this.gm_open, "gm_open", &this._flags1_, 3, kv)
|
||||
f5.ReadMetaTableField(&this.gm_secret_key, "gm_secret_key", &this._flags1_, 4, kv)
|
||||
f5.ReadMetaTableField(&this.redirect_url, "redirect_url", &this._flags1_, 5, kv)
|
||||
f5.ReadMetaTableField(&this.max_request_cache, "max_request_cache", &this._flags1_, 6, kv)
|
||||
f5.ReadMetaTableField(&this.max_concurrent_num, "max_concurrent_num", &this._flags1_, 6, kv)
|
||||
f5.ReadMetaTableField(&this.request_over_time, "request_over_time", &this._flags1_, 7, kv)
|
||||
}
|
||||
|
@ -16,6 +16,6 @@ message Config
|
||||
optional int32 gm_open = 3;
|
||||
optional string gm_secret_key = 4;
|
||||
optional string redirect_url = 5;
|
||||
optional int32 max_request_cache = 6;
|
||||
optional int32 max_concurrent_num = 6;
|
||||
optional int32 request_over_time = 7;
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ type routerMgr struct {
|
||||
|
||||
func (this *routerMgr) Init() {
|
||||
redirectGroup := f5.GetApp().GetGinEngine().Group("/sapi")
|
||||
redirectGroup.Any("webapp/index.php?", middleware.CaCheck)
|
||||
redirectGroup.Any("check", middleware.VerifySig)
|
||||
redirectGroup.Any("webapp/index.php", middleware.CaForward)
|
||||
|
||||
f5.GetSysLog().Info("routerMgr.init")
|
||||
}
|
||||
|
13
server/gamesapi/service/export.go
Normal file
13
server/gamesapi/service/export.go
Normal file
@ -0,0 +1,13 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"main/constant"
|
||||
"main/global"
|
||||
)
|
||||
|
||||
var _serviceMgr = new(serviceMgr)
|
||||
var SApiForward *sApiForward
|
||||
|
||||
func init() {
|
||||
global.RegModule(constant.SERVICE_MGR_MODULE_IDX, _serviceMgr)
|
||||
}
|
102
server/gamesapi/service/sapi_forward.go
Normal file
102
server/gamesapi/service/sapi_forward.go
Normal file
@ -0,0 +1,102 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"q5"
|
||||
"sync"
|
||||
"mt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type sApiForward struct {
|
||||
userCache []*SApiForwardLockCache
|
||||
}
|
||||
|
||||
type SApiForwardLockCache struct {
|
||||
lock *sync.Mutex
|
||||
userHash *map[string]*SApiForwardLock
|
||||
}
|
||||
|
||||
type SApiForwardLock struct {
|
||||
accountId string
|
||||
lockTimes int32
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
func (this *sApiForward) init() {
|
||||
q5.NewSlice(&this.userCache, 1024, 1024)
|
||||
for i := 0; i < len(this.userCache); i++ {
|
||||
p := new(SApiForwardLockCache)
|
||||
p.lock = new(sync.Mutex)
|
||||
p.userHash = new(map[string]*SApiForwardLock)
|
||||
this.userCache[i] = p
|
||||
}
|
||||
}
|
||||
|
||||
func (this *sApiForward) unInit() {
|
||||
}
|
||||
|
||||
func (this *sApiForward) AcquireLock(accountId string) *SApiForwardLock {
|
||||
crc32 := q5.Crc32(accountId)
|
||||
c := this.userCache[int64(crc32) % int64(len(this.userCache))]
|
||||
u := this.getOrCreate(c, accountId)
|
||||
if atomic.AddInt32(&u.lockTimes, 1) > mt.Table.Config.GetMaxConcurrentNum() {
|
||||
atomic.AddInt32(&u.lockTimes, -1)
|
||||
return nil
|
||||
}
|
||||
u.lock.Lock()
|
||||
return u
|
||||
}
|
||||
|
||||
func (this *sApiForward) ReleaseLock(l *SApiForwardLock) {
|
||||
l.lock.Unlock()
|
||||
atomic.AddInt32(&l.lockTimes, -1)
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncInvalidSessionTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncTotalTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncGetTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncPostTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncCreateErrTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncDoErrTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncOkTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) IncReadRspErrTimes() {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) UpdateCostTime(costTime int64) {
|
||||
|
||||
}
|
||||
|
||||
func (this *sApiForward) getOrCreate(c *SApiForwardLockCache, accountId string) *SApiForwardLock {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
if u, ok := (*c.userHash)[accountId]; ok {
|
||||
return u
|
||||
} else {
|
||||
u = new(SApiForwardLock)
|
||||
u.accountId = accountId
|
||||
u.lock = new(sync.Mutex)
|
||||
return u
|
||||
}
|
||||
}
|
13
server/gamesapi/service/servicemgr.go
Normal file
13
server/gamesapi/service/servicemgr.go
Normal file
@ -0,0 +1,13 @@
|
||||
package service
|
||||
|
||||
type serviceMgr struct {
|
||||
}
|
||||
|
||||
func (this *serviceMgr) Init() {
|
||||
SApiForward = new(sApiForward)
|
||||
SApiForward.init()
|
||||
}
|
||||
|
||||
func (this *serviceMgr) UnInit() {
|
||||
SApiForward.unInit()
|
||||
}
|
@ -84,3 +84,7 @@ func CalcContributionScore(nfts []*NftStacking) float64 {
|
||||
score = baseScore * (1 + rate)
|
||||
return score
|
||||
}
|
||||
|
||||
func IsValidSessionId(accountId string, sessionId string) bool {
|
||||
return true
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ func (ea *EventApi) ActivityQuery(c *gin.Context) {
|
||||
func(ds *f5.DataSet) {
|
||||
p := new(common.NftDto)
|
||||
p.NetId = q5.ToInt32(ds.GetByName("net_id"))
|
||||
p.ContractAddress = ds.GetByName("contract_address")
|
||||
p.ContractAddress = ds.GetByName("nft_contract_address")
|
||||
p.TokenId = ds.GetByName("token_id")
|
||||
p.Payload = map[string]string{}
|
||||
p.Payload.(map[string]string)["type"] = ds.GetByName("event_name")
|
||||
|
Loading…
x
Reference in New Issue
Block a user