You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

125 lines
3.0 KiB

package sig
import (
"context"
"encoding/json"
"io"
"net/http"
"runtime/debug"
"sig-pub/pkg/grpc/generic"
"sig-pub/pkg/grpc/session"
"sig-pub/pkg/resp"
"sig-pub/pkg/utils/strs"
"sig-pub/pkg/zlog"
"strings"
"time"
"github.com/gin-gonic/gin"
"google.golang.org/grpc"
"google.golang.org/protobuf/encoding/protojson"
)
type SigServer struct {
engine *gin.Engine
grpcGenericClientFactory *generic.GrpcGenericClientFactory
}
func NewSigServer(grpcGenericClientFactory *generic.GrpcGenericClientFactory) *SigServer {
return &SigServer{
grpcGenericClientFactory: grpcGenericClientFactory,
}
}
func (s *SigServer) Init() (err error) {
s.initGinServer()
return
}
func (s *SigServer) initGinServer() {
s.engine = gin.Default()
s.engine.Use(func(c *gin.Context) {
// global recover
defer func() {
if r := recover(); r != nil {
zlog.Error("http server recover error:", r)
debug.PrintStack()
c.JSON(http.StatusInternalServerError, resp.Error("server error"))
c.Abort()
}
}()
c.Next()
})
routerGroup := s.engine.Group("/api")
routerGroup.POST("/v1/:svr/:method", s.handleGrpcGenericCall)
// inst api
// tradeInstanceApi := inst.NewTradeInstanceApi()
// tradeInstanceApi.InitRoute(routerGroup)
}
func (s *SigServer) Run(addr string) (err error) {
// todo grpc server run
return s.engine.Run(addr)
}
func (s *SigServer) handleGrpcGenericCall(c *gin.Context) {
svr := strs.UpperInitialLetter(c.Param("svr"))
method := strs.UpperInitialLetter(c.Param("method"))
if svr == "" || method == "" {
c.JSON(http.StatusBadRequest, resp.Error("service not found"))
return
}
if !strings.HasSuffix(svr, "Service") {
svr += "Service"
}
// todo service white list
// get request body
jsonBody, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, resp.Error("parse request body error: "+err.Error()))
return
}
ctx1, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
grpcGenericClient, err := s.grpcGenericClientFactory.GetClient(ctx1, svr)
if err != nil {
zlog.Error(err)
c.JSON(http.StatusForbidden, resp.Error(err.Error()))
return
}
// put session
ctx := context.Background()
ctx = session.PutSubject(ctx, session.NewRpcSubject("123456"))
ctx, cancel = context.WithTimeout(ctx, time.Second*20)
defer cancel()
// todo config call options
var opts []grpc.CallOption
if svr == "ExchangeService" && method == "HistoryKline" {
opts = append(opts, grpc.UseCompressor("snappy"))
}
// generic call with json
rsp, err := grpcGenericClient.InvokeUnaryJsonBytes(ctx, method, jsonBody, opts...)
if err != nil {
if err == generic.ErrorMethodNotExists {
c.JSON(http.StatusNotFound, resp.Error(err.Error()))
return
}
c.JSON(http.StatusInternalServerError, resp.Error(err.Error()))
return
}
// decode response
bytes, err := protojson.Marshal(rsp)
if err != nil {
c.JSON(http.StatusInternalServerError, resp.Error(err.Error()))
return
}
r := json.RawMessage(bytes)
c.JSON(http.StatusOK, resp.Success(r))
}