chore: 初始开源发布
iotlcm-upstream-proxy:渠道缓存与转发网关。 - 内联原私有依赖:yunze-public → internal/pub/(18 文件), yunze-pb/pb → internal/pb/(9 文件);Consul 注册改用官方 gogf/gf/contrib/registry/consul/v2(API 兼容) - Go module:yz-svr → git.5iot.com/iotlcm-public/iotlcm-upstream-proxy - 凭据与内部标识脱敏:MySQL/Redis/Consul 凭据、私网与生产 IP、内网域名 - 移除内部资产:CI 触发器 - Dockerfile 改用公共基础镜像,移除写死的 registry 凭据 - 补 Apache-2.0 LICENSE,重写 README,LF 行尾 + .gitattributes
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package initconsul
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/contrib/registry/consul/v2"
|
||||
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gsel"
|
||||
)
|
||||
|
||||
func InitConsul(ctx context.Context) error {
|
||||
// 初始化consul
|
||||
err := registerConsul(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func registerConsul(ctx context.Context) error {
|
||||
consulAddress := g.Cfg().MustGet(ctx, "registry.address", "127.0.0.1:8500").String()
|
||||
g.Log().Infof(ctx, "consulAddress: %+v", consulAddress)
|
||||
registry, err := consul.New(consul.WithAddress(consulAddress))
|
||||
if err != nil {
|
||||
g.Log().Fatalf(ctx, "consul初始化失败: %+v", err)
|
||||
return err
|
||||
}
|
||||
grpcx.Resolver.Register(registry)
|
||||
gsel.SetBuilder(gsel.NewBuilderRandom())
|
||||
g.Log().Infof(ctx, "consul注册成功")
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// package version
|
||||
// @Link https://github.com/xiujiecn/xiu-admin
|
||||
// @Copyright Copyright (c) 2025 LiXiujie
|
||||
// @Author Lxj <li@xiujie.cn>
|
||||
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
package version
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var (
|
||||
BuildTime string
|
||||
BuildVersion string
|
||||
CommitID string
|
||||
)
|
||||
|
||||
func ShowLogo(ctx context.Context, buildVersion, buildTime, commitID string) {
|
||||
BuildVersion = buildVersion
|
||||
BuildTime = buildTime
|
||||
CommitID = commitID
|
||||
//版本号
|
||||
|
||||
g.Log().Notice(ctx, `
|
||||
|
||||
██╗██╗███████╗ ██╗ ██████╗ ████████╗
|
||||
██║██║██╔════╝ ██║██╔═══██╗╚══██╔══╝
|
||||
██║██║█████╗ ██║██║ ██║ ██║
|
||||
██ ██║██║██╔══╝ ██║██║ ██║ ██║
|
||||
╚█████╔╝██║███████╗ ██║╚██████╔╝ ██║
|
||||
╚════╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
|
||||
`)
|
||||
|
||||
g.Log().Notice(ctx, "Version :", buildVersion)
|
||||
g.Log().Notice(ctx, "BuildTime :", buildTime)
|
||||
g.Log().Notice(ctx, "CommitID :", commitID)
|
||||
g.Log().Notice(ctx, "Copyright:", "2026 The iotLCM Authors")
|
||||
|
||||
fmt.Println("Version :", buildVersion)
|
||||
fmt.Println("BuildTime :", buildTime)
|
||||
fmt.Println("CommitID :", commitID)
|
||||
fmt.Println("Copyright:", "2026 The iotLCM Authors")
|
||||
}
|
||||
|
||||
func AppName(ctx context.Context) string {
|
||||
return g.Cfg().MustGet(ctx, "system.appName", "IotLCM").String()
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Package xjpubconsts
|
||||
// @Link https://github.com/xiujiecn/xiu-admin
|
||||
// @Copyright Copyright (c) 2025 LiXiujie
|
||||
// @Author Lxj <li@xiujie.cn>
|
||||
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
package xjpubconsts
|
||||
|
||||
const (
|
||||
HTTPContentTypeXml = "text/xml"
|
||||
HTTPContentTypeHtml = "text/html"
|
||||
HTTPContentTypeStream = "text/event-stream"
|
||||
HTTPContentTypeJson = "application/json"
|
||||
HTTPContentTypeExcel = "application/octet-stream"
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
package xjpubconsts
|
||||
|
||||
const (
|
||||
ServiceTypeWeb = "web" // web服务
|
||||
ServiceTypeQueue = "queue" // 队列服务
|
||||
ServiceTypeRedis = "redis" // 缓存类型
|
||||
ServiceTypeNotice = "notice" // 通知服务
|
||||
ServiceTypeTask = "task" // 任务服务
|
||||
ServiceTypeAccess = "access" // 接入服务
|
||||
)
|
||||
|
||||
const (
|
||||
ServiceNameYzAdminWeb = "yzadmin-web-svc" // 后台管理服务
|
||||
ServiceNameYzUpstreamChanSvc = "yzupstreamchan-grpc-svc" // 上游通道服务
|
||||
ServiceNameYzUpstreamProxySvc = "yzupstreamproxy-grpc-svc" // 上游代理服务
|
||||
ServiceNameYzApiHttpSvc = "yzapi-http-svc" // API 服务
|
||||
)
|
||||
@@ -0,0 +1,100 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubservice"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gclient"
|
||||
"github.com/gogf/gf/v2/net/gsvc"
|
||||
)
|
||||
|
||||
type sHttpClient struct {
|
||||
client *gclient.Client
|
||||
}
|
||||
|
||||
func NewHttpClient() *sHttpClient {
|
||||
client := g.Client()
|
||||
return &sHttpClient{
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
xjpubservice.RegisterHttpClient(NewHttpClient())
|
||||
}
|
||||
|
||||
func (s *sHttpClient) PostObj(ctx context.Context, serviceName string, path string, req interface{}, res interface{}) (err error) {
|
||||
reqJson, err := gjson.Marshal(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resJson, err := s.Post(ctx, serviceName, path, reqJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = gjson.Unmarshal(resJson, res)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "sHttpClient.PostObj gjson.Unmarshal error: %v, resJson: %s", err, string(resJson))
|
||||
return err
|
||||
}
|
||||
g.Log().Debugf(ctx, "sHttpClient.PostObj res: %+v, resJson: %s", res, string(resJson))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sHttpClient) Post(ctx context.Context, serviceName string, path string, req []byte) (res []byte, err error) {
|
||||
// s.client.SetHeader("Span-Id", "0.0.1")
|
||||
// s.client.SetHeader("Trace-Id", gctx.CtxId(ctx))
|
||||
|
||||
url := "http://" + serviceName + path
|
||||
s.client.SetDiscovery(gsvc.GetRegistry())
|
||||
// g.Log().Debugf(ctx, "sHttpClient.Post url: %s, req: %+v", url, string(req))
|
||||
response, err := s.client.Post(ctx, url, req)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "sHttpClient.Post Post error: %v, url: %s, req: %+v", err, url, string(req))
|
||||
return nil, err
|
||||
}
|
||||
defer response.Close()
|
||||
res = response.ReadAll()
|
||||
g.Log().Debugf(ctx, "sHttpClient.Post url: %s, req: %+v, res: %+v", url, string(req), string(res))
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *sHttpClient) AllServerPost(ctx context.Context, serviceName string, path string, req []byte) (resMap map[string][]byte, err error) {
|
||||
// s.client.SetHeader("Span-Id", "0.0.1")
|
||||
// s.client.SetHeader("Trace-Id", gctx.CtxId(ctx))
|
||||
s.client.SetDiscovery(gsvc.GetRegistry())
|
||||
|
||||
servers, err := gsvc.Search(ctx, gsvc.SearchInput{
|
||||
Name: serviceName,
|
||||
})
|
||||
if len(servers) == 0 {
|
||||
g.Log().Errorf(ctx, "sHttpClient.AllServerPost gsvc.Search(ctx, serviceName) error: %v, serviceName: %s", err, serviceName)
|
||||
return nil, err
|
||||
}
|
||||
// g.Log().Debugf(ctx, "sHttpClient.AllServerPost servers: %+v", servers)
|
||||
endpoints := make([]string, 0)
|
||||
for _, server := range servers {
|
||||
endpoint := server.GetEndpoints()
|
||||
if len(endpoint) == 0 {
|
||||
g.Log().Errorf(ctx, "sHttpClient.AllServerPost server.GetEndpoints() error: %v, serviceName: %s", err, serviceName)
|
||||
continue
|
||||
}
|
||||
endpoints = append(endpoints, endpoint[0].String())
|
||||
}
|
||||
resMap = make(map[string][]byte)
|
||||
for _, e := range endpoints {
|
||||
url := "http://" + e + path
|
||||
res, err := s.Post(ctx, e, path, req)
|
||||
// g.Log().Debugf(ctx, "sHttpClient.AllServerPost Post url: %s, req: %+v res: %+v err: %+v", url, string(req), string(res), err)
|
||||
if err != nil {
|
||||
resMap[e] = nil
|
||||
g.Log().Errorf(ctx, "sHttpClient.AllServerPost Post error: %v, url: %s, req: %+v", err, url, string(req))
|
||||
continue
|
||||
}
|
||||
resMap[e] = res
|
||||
}
|
||||
return resMap, nil
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubconsts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubmodel"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubmodel/response"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubservice"
|
||||
)
|
||||
|
||||
type sUpstreamProxyClient struct {
|
||||
}
|
||||
|
||||
func NewUpstreamProxyClient() *sUpstreamProxyClient {
|
||||
return &sUpstreamProxyClient{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
xjpubservice.RegisterUpstreamProxyClient(NewUpstreamProxyClient())
|
||||
}
|
||||
|
||||
// 物联网卡在线信息实时查询
|
||||
func (s *sUpstreamProxyClient) QuerySimSession(ctx context.Context, input *xjpubmodel.SimSessionInput) (output *xjpubmodel.SimSessionOutput, err error) {
|
||||
res := &response.ResponseGeneric[*xjpubmodel.SimSessionOutput]{}
|
||||
err = xjpubservice.HttpClient().PostObj(ctx, xjpubconsts.ServiceNameYzUpstreamChanSvc, "/query/sim-session", input, res)
|
||||
output = res.Data
|
||||
return output, err
|
||||
}
|
||||
|
||||
// 物联网卡卡状态查询
|
||||
func (s *sUpstreamProxyClient) QuerySimCardStatus(ctx context.Context, input *xjpubmodel.SimCardStatusInput) (output *xjpubmodel.SimCardStatusOutput, err error) {
|
||||
res := &response.ResponseGeneric[*xjpubmodel.SimCardStatusOutput]{}
|
||||
err = xjpubservice.HttpClient().PostObj(ctx, xjpubconsts.ServiceNameYzUpstreamChanSvc, "/query/sim-status", input, res)
|
||||
output = res.Data
|
||||
return output, err
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubmodel"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubservice"
|
||||
)
|
||||
|
||||
type sInfo struct {
|
||||
Info xjpubmodel.InfoModel
|
||||
}
|
||||
|
||||
func NewInfo() *sInfo {
|
||||
return &sInfo{
|
||||
Info: xjpubmodel.InfoModel{},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
xjpubservice.RegisterInfo(NewInfo())
|
||||
}
|
||||
|
||||
func (s *sInfo) GetInfo() *xjpubmodel.InfoModel {
|
||||
return &s.Info
|
||||
}
|
||||
|
||||
func (s *sInfo) SetInfoName(Type, Name, Title, Description string) {
|
||||
if s.Info.Name == "" {
|
||||
s.Info.Type = Type
|
||||
s.Info.Name = Name
|
||||
s.Info.Title = Title
|
||||
s.Info.Description = Description
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sInfo) SetInfoBuild(buildVersion, buildTime, commitID string) {
|
||||
s.Info.Version = buildVersion
|
||||
s.Info.Build = buildTime
|
||||
s.Info.Commit = commitID
|
||||
}
|
||||
|
||||
func (s *sInfo) SetInfoData(data map[string]interface{}) {
|
||||
s.Info.Data = data
|
||||
}
|
||||
|
||||
func (s *sInfo) GetInfoData() map[string]interface{} {
|
||||
return s.Info.Data
|
||||
}
|
||||
|
||||
func (s *sInfo) AddInfoData(key string, value interface{}) {
|
||||
if s.Info.Data == nil {
|
||||
s.Info.Data = make(map[string]interface{})
|
||||
}
|
||||
s.Info.Data[key] = value
|
||||
}
|
||||
|
||||
func (s *sInfo) DelInfoData(key string) {
|
||||
delete(s.Info.Data, key)
|
||||
}
|
||||
|
||||
func (s *sInfo) GetInfoDataByKey(key string) interface{} {
|
||||
if s.Info.Data == nil {
|
||||
return nil
|
||||
}
|
||||
if _, ok := s.Info.Data[key]; !ok {
|
||||
return nil
|
||||
}
|
||||
return s.Info.Data[key]
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubmodel"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubservice"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
)
|
||||
|
||||
type sInfoRpc struct {
|
||||
Info *xjpubmodel.InfoModel
|
||||
}
|
||||
|
||||
func NewInfoRpc() *sInfoRpc {
|
||||
return &sInfoRpc{
|
||||
Info: xjpubmodel.NewInfoModel(),
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
xjpubservice.RegisterInfoRpc(NewInfoRpc())
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) GetInfo() *xjpubmodel.InfoModel {
|
||||
ctx := context.Background()
|
||||
logLevel := g.Cfg().MustGet(ctx, "logger.level", "").String()
|
||||
if logLevel != "" {
|
||||
g.Log().SetLevelStr(logLevel)
|
||||
}
|
||||
s.AddInfoData("log_level_conf", logLevel)
|
||||
s.AddInfoData("log_level_real", toLogLevelStr(g.Log().GetLevel()))
|
||||
s.AddInfoData("Goroutines", runtime.NumGoroutine())
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
s.AddInfoData("MemAllocKB", m.Alloc/1024)
|
||||
s.AddInfoData("MemTotalAllocKB", m.TotalAlloc/1024)
|
||||
s.AddInfoData("MemSysKB", m.Sys/1024)
|
||||
s.AddInfoData("MemHeapAllocKB", m.HeapAlloc/1024)
|
||||
s.AddInfoData("MemHeapSysKB", m.HeapSys/1024)
|
||||
s.AddInfoData("MemHeapIdleKB", m.HeapIdle/1024)
|
||||
s.AddInfoData("MemHeapInuseKB", m.HeapInuse/1024)
|
||||
s.AddInfoData("MemHeapReleasedKB", m.HeapReleased/1024)
|
||||
s.AddInfoData("MemHeapObjects", m.HeapObjects)
|
||||
s.AddInfoData("MemStackInuseKB", m.StackInuse/1024)
|
||||
s.AddInfoData("MemStackSysKB", m.StackSys/1024)
|
||||
s.AddInfoData("MemNumGC", m.NumGC)
|
||||
return s.Info
|
||||
}
|
||||
|
||||
func toLogLevelStr(level int) string {
|
||||
if level == glog.LEVEL_NONE {
|
||||
return "NONE"
|
||||
}
|
||||
if level == glog.LEVEL_ALL {
|
||||
return "ALL"
|
||||
}
|
||||
if level == glog.LEVEL_DEV {
|
||||
return "DEV"
|
||||
}
|
||||
if level == glog.LEVEL_PROD {
|
||||
return "PROD"
|
||||
}
|
||||
str := ""
|
||||
if level&glog.LEVEL_DEBU != 0 {
|
||||
str += "DEBUG "
|
||||
}
|
||||
if level&glog.LEVEL_INFO != 0 {
|
||||
str += "INFO "
|
||||
}
|
||||
if level&glog.LEVEL_NOTI != 0 {
|
||||
str += "NOTI "
|
||||
}
|
||||
if level&glog.LEVEL_WARN != 0 {
|
||||
str += "WARN "
|
||||
}
|
||||
if level&glog.LEVEL_ERRO != 0 {
|
||||
str += "ERRO "
|
||||
}
|
||||
if level&glog.LEVEL_CRIT != 0 {
|
||||
str += "CRIT "
|
||||
}
|
||||
if level&glog.LEVEL_PANI != 0 {
|
||||
str += "PANI "
|
||||
}
|
||||
if level&glog.LEVEL_FATA != 0 {
|
||||
str += "FATA "
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) SetInfoName(Type, Name, Title, Description string) {
|
||||
if s.Info.Name == "" {
|
||||
s.Info.Type = Type
|
||||
s.Info.Name = Name
|
||||
s.Info.Title = Title
|
||||
s.Info.Description = Description
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) SetInfoBuild(buildVersion, buildTime, commitID string) {
|
||||
s.Info.Version = buildVersion
|
||||
s.Info.Build = buildTime
|
||||
s.Info.Commit = commitID
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) SetInfoData(data map[string]interface{}) {
|
||||
s.Info.Data = data
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) GetInfoData() map[string]interface{} {
|
||||
return s.Info.Data
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) AddInfoData(key string, value interface{}) {
|
||||
s.Info.Data[key] = value
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) DelInfoData(key string) {
|
||||
delete(s.Info.Data, key)
|
||||
}
|
||||
|
||||
func (s *sInfoRpc) GetInfoDataByKey(key string) interface{} {
|
||||
return s.Info.Data[key]
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// package middleware
|
||||
// @Link https://github.com/xiujiecn/xiu-admin
|
||||
// @Copyright Copyright (c) 2025 LiXiujie
|
||||
// @Author Lxj <li@xiujie.cn>
|
||||
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"slices"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/util/gmeta"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubconsts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubmodel/response"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubservice"
|
||||
)
|
||||
|
||||
type sMiddleware struct {
|
||||
}
|
||||
|
||||
func New() *sMiddleware {
|
||||
return &sMiddleware{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
xjpubservice.RegisterMiddleware(New())
|
||||
}
|
||||
|
||||
func getContentType(r *ghttp.Request) (contentType string) {
|
||||
contentType = r.Response.Header().Get("Content-Type")
|
||||
if contentType != "" {
|
||||
return
|
||||
}
|
||||
|
||||
mime := gmeta.Get(r.GetHandlerResponse(), "mime").String()
|
||||
if mime == "" {
|
||||
contentType = xjpubconsts.HTTPContentTypeJson
|
||||
} else {
|
||||
contentType = mime
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 响应处理中间件
|
||||
func (m *sMiddleware) ResponseHandler(r *ghttp.Request) {
|
||||
r.Middleware.Next()
|
||||
if r.Response.BufferLength() > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
contentType := getContentType(r)
|
||||
if contentType == xjpubconsts.HTTPContentTypeExcel {
|
||||
r.Response.Status = http.StatusOK
|
||||
return
|
||||
}
|
||||
// g.Log().Infof(r.GetCtx(), "sMiddleware.ResponseHandler,contentType %v", contentType)
|
||||
err := r.GetError()
|
||||
res := r.GetHandlerResponse()
|
||||
var code gcode.Code = gcode.CodeOK
|
||||
|
||||
if err != nil {
|
||||
code = gerror.Code(err)
|
||||
if code == gcode.CodeNil {
|
||||
code = gcode.CodeInternalError
|
||||
}
|
||||
response.JsonExit(r, code.Code(), err.Error())
|
||||
} else {
|
||||
response.Json(r, code.Code(), "", res)
|
||||
}
|
||||
}
|
||||
|
||||
// CORS 跨域处理
|
||||
func (s *sMiddleware) CORS(r *ghttp.Request) {
|
||||
r.SetCtx(r.GetNeverDoneCtx())
|
||||
|
||||
corsOptions := r.Response.DefaultCORSOptions()
|
||||
corsConfig := g.Cfg().MustGet(context.Background(), "server.allowedDomains").Strings()
|
||||
if len(corsConfig) == 0 {
|
||||
r.Response.CORSDefault()
|
||||
} else {
|
||||
corsOptions.AllowDomain = corsConfig
|
||||
r.Response.CORS(corsOptions)
|
||||
}
|
||||
r.Middleware.Next()
|
||||
}
|
||||
|
||||
// IsExceptLogin 判断是否需要验证登录
|
||||
func (s *sMiddleware) IsExceptLogin(ctx context.Context, path string) bool {
|
||||
pathList := g.Cfg().MustGet(ctx, "router.exceptLogin").Strings()
|
||||
return slices.Contains(pathList, path)
|
||||
}
|
||||
|
||||
// ResponseHandlerRaw 返回处理中间件
|
||||
func (s *sMiddleware) ResponseHandlerRaw(r *ghttp.Request) {
|
||||
r.Middleware.Next()
|
||||
// 如果已经有返回内容,那么该中间件什么也不做
|
||||
if r.Response.BufferLength() > 0 {
|
||||
g.Log().Infof(r.Context(), "ResponseHandler r.Response.BufferLength() %d buf:%s", r.Response.BufferLength(), r.Response.BufferString())
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
err = r.GetError()
|
||||
res = r.GetHandlerResponse()
|
||||
)
|
||||
if err != nil {
|
||||
r.Response.WriteJson(res)
|
||||
r.ExitAll()
|
||||
} else {
|
||||
r.Response.WriteJson(res)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package xjpublogic
|
||||
|
||||
import (
|
||||
_ "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpublogic/httpclient"
|
||||
_ "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpublogic/info"
|
||||
_ "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpublogic/middleware"
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
package xjpubmodel
|
||||
|
||||
type InfoModel struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Version string `json:"version"`
|
||||
Build string `json:"build"`
|
||||
Commit string `json:"commit"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func NewInfoModel() *InfoModel {
|
||||
return &InfoModel{
|
||||
Data: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// package response
|
||||
// @Link https://github.com/xiujiecn/xiu-admin
|
||||
// @Copyright Copyright (c) 2025 LiXiujie
|
||||
// @Author Lxj <li@xiujie.cn>
|
||||
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
package response
|
||||
|
||||
type PageResult struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// package response
|
||||
// @Link https://github.com/xiujiecn/xiu-admin
|
||||
// @Copyright Copyright (c) 2025 LiXiujie
|
||||
// @Author Lxj <li@xiujie.cn>
|
||||
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
package response
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// 泛型
|
||||
type ResponseGeneric[T any] struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data T `json:"data"`
|
||||
}
|
||||
|
||||
type JsonResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
Error interface{} `json:"error"`
|
||||
}
|
||||
|
||||
func Json(r *ghttp.Request, code int, message string, data ...interface{}) {
|
||||
var responseData interface{}
|
||||
if len(data) > 0 {
|
||||
responseData = data[0]
|
||||
} else {
|
||||
responseData = g.Map{}
|
||||
}
|
||||
// g.Log().Infof(r.GetCtx(), "response.Json: %v", responseData)
|
||||
r.Response.WriteJson(JsonResponse{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Data: responseData,
|
||||
})
|
||||
}
|
||||
|
||||
func JsonExit(r *ghttp.Request, code int, message string, data ...interface{}) {
|
||||
Json(r, code, message, data...)
|
||||
r.ExitAll()
|
||||
}
|
||||
|
||||
// 向前端返回Excel文件 参数 content 为上面生成的io.ReadSeeker, fileTag 为返回前端的文件名
|
||||
func Excel(r *ghttp.Request, content io.ReadSeeker, fileTag string) {
|
||||
fileName := fmt.Sprintf("%s%s%s.xlsx", gtime.Now().Format("Ymdhis"), `_`, fileTag)
|
||||
r.Response.Header().Set("Content-Type", "application/vnd.ms-excel")
|
||||
r.Response.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
|
||||
http.ServeContent(r.Response.Writer, r.Request, fileTag, time.Now(), content)
|
||||
}
|
||||
|
||||
// 向前端返回Json文件 参数 content 为上面生成的io.ReadSeeker, fileTag 为返回前端的文件名
|
||||
func JsonFile(r *ghttp.Request, content io.ReadSeeker, fileTag string) {
|
||||
fileName := fmt.Sprintf("%s%s%s.json", gtime.Now().Format("Ymdhis"), `_`, fileTag)
|
||||
r.Response.Header().Set("Content-Type", "application/json")
|
||||
r.Response.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
|
||||
http.ServeContent(r.Response.Writer, r.Request, fileTag, time.Now(), content)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package xjpubmodel
|
||||
|
||||
type SimKey struct {
|
||||
ChanKey string `json:"chanKey" dc:"通道标识"`
|
||||
ICCID string `json:"iccid" dc:"联网卡集成电路卡识别码20位"`
|
||||
}
|
||||
|
||||
// 物联网卡在线信息实时查询 请求参数
|
||||
type SimSessionInput struct {
|
||||
SimKeys []*SimKey `json:"simKeys" dc:"SIM卡标识列表"`
|
||||
}
|
||||
|
||||
type SimSessionItem struct {
|
||||
*SimKey
|
||||
ApnId string `json:"apnId" dc:"APN ID"`
|
||||
Rat string `json:"rat" dc:"接入方式"`
|
||||
Ipv4 string `json:"ipv4" dc:"IPV4"`
|
||||
Ipv6 string `json:"ipv6" dc:"IPV6"`
|
||||
Ipv6Prefix string `json:"ipv6Prefix" dc:"IPV6前缀"`
|
||||
Status string `json:"status" dc:"状态(0:用户在线 -1:用户不在线 -2:未查询到会话信息)"`
|
||||
CreateTime string `json:"createTime" dc:"创建时间"`
|
||||
ApiStatus int `json:"apiStatus" dc:"API状态"`
|
||||
ApiMessage string `json:"apiMessage" dc:"API消息"`
|
||||
}
|
||||
|
||||
// 物联网卡在线信息实时查询 响应参数
|
||||
type SimSessionOutput struct {
|
||||
Items []*SimSessionItem `json:"items" dc:"SIM卡会话列表"`
|
||||
}
|
||||
|
||||
// 物联网卡卡状态查询 请求参数
|
||||
type SimCardStatusInput struct {
|
||||
SimKeys []*SimKey `json:"simKeys" dc:"SIM卡标识列表"`
|
||||
}
|
||||
|
||||
// 物联网卡卡状态查询 响应参数
|
||||
type SimCardStatusOutput struct {
|
||||
Items []*SimCardStatusItem `json:"items" dc:"SIM卡状态列表"`
|
||||
}
|
||||
|
||||
// {"cardStatus":"2","lastChangeDate":"2024-05-30 22:05:31"}]
|
||||
type SimCardStatusItem struct {
|
||||
*SimKey
|
||||
CardStatus int `json:"cardStatus" dc:"卡状态"`
|
||||
LastChangeDate string `json:"lastChangeDate" dc:"最后变更时间"`
|
||||
ApiStatus int `json:"apiStatus" dc:"API状态"`
|
||||
ApiMessage string `json:"apiMessage" dc:"API消息"`
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package xjpubmodel
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type MetricItem struct {
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
Time *gtime.Time `json:"time"`
|
||||
}
|
||||
|
||||
func (m *MetricItem) SetValue(value interface{}) {
|
||||
m.Value = gconv.Float64(value)
|
||||
m.Time = gtime.Now()
|
||||
}
|
||||
func (m *MetricItem) GetValue() float64 {
|
||||
return m.Value
|
||||
}
|
||||
func (m *MetricItem) GetTime() *gtime.Time {
|
||||
return m.Time
|
||||
}
|
||||
func (m *MetricItem) GetName() string {
|
||||
return m.Name
|
||||
}
|
||||
func (m *MetricItem) SetName(name string) {
|
||||
m.Name = name
|
||||
}
|
||||
func (m *MetricItem) AddValue(value interface{}) {
|
||||
m.Value += gconv.Float64(value)
|
||||
m.Time = gtime.Now()
|
||||
}
|
||||
func (m *MetricItem) Inc() {
|
||||
m.Value++
|
||||
m.Time = gtime.Now()
|
||||
}
|
||||
func (m *MetricItem) Dec() {
|
||||
m.Value--
|
||||
m.Time = gtime.Now()
|
||||
}
|
||||
|
||||
type MetricData struct {
|
||||
MetricClientCount MetricItem `json:"clientCount"` // 当前在线数
|
||||
MetricConnectedCounter MetricItem `json:"connectedCounter"` // 连接数
|
||||
MetricDisconnectedCounter MetricItem `json:"disconnectedCounter"` // 断开连接数
|
||||
MetricRecvPkgCount MetricItem `json:"recvPkgCount"` // 接收包数
|
||||
MetricSendPkgCount MetricItem `json:"sendPkgCount"` // 发送包数
|
||||
MetricRecvPkgSize MetricItem `json:"recvPkgSize"` // 接收包大小
|
||||
MetricSendPkgSize MetricItem `json:"sendPkgSize"` // 发送包大小
|
||||
MetricRecvPkgTime MetricItem `json:"recvPkgTime"` // 接收包时间(毫秒)
|
||||
MetricSendPkgTime MetricItem `json:"sendPkgTime"` // 发送包时间(毫秒)
|
||||
MetricSubTopicCount MetricItem `json:"subTopicCount"` // 订阅主题数
|
||||
MetricAuthSuccessCount MetricItem `json:"authSuccessCount"` // 认证成功数
|
||||
MetricAuthFailCount MetricItem `json:"authFailCount"` // 认证失败数
|
||||
MetricAuthCostTime MetricItem `json:"authCostTime"` // 认证耗时
|
||||
MetricUpMsgConnectCostTime MetricItem `json:"upMsgConnectCostTime"` // 上行消息连接耗时(毫秒)
|
||||
MetricUpMsgDataCostTime MetricItem `json:"upMsgDataCostTime"` // 上行消息数据耗时(毫秒)
|
||||
MetricUpMsgDisconnectCostTime MetricItem `json:"upMsgDisconnectCostTime"` // 上行消息断开连接耗时(毫秒)
|
||||
MetricTopicCount MetricItem `json:"topicCount"` // 累计主题数
|
||||
MetricProcessMemSize MetricItem `json:"processMemSize"` // 进程内存大小
|
||||
MetricProcessCpuUsage MetricItem `json:"processCpuUsage"` // 进程CPU使用率
|
||||
MetricProcessThreads MetricItem `json:"processThreads"` // 进程线程数
|
||||
MetricProcessGoroutines MetricItem `json:"processGoroutines"` // 进程协程数
|
||||
MetricSysCpuNum MetricItem `json:"sysCpuNum"` // 系统CPU数量
|
||||
MetricSysCpuCores MetricItem `json:"sysCpuCores"` // 系统CPU核数
|
||||
MetricSysCpuUsage MetricItem `json:"sysCpuUsage"` // 系统CPU使用率
|
||||
MetricSysCpuLoad1 MetricItem `json:"sysCpuLoad1"` // 系统CPU负载1
|
||||
MetricSysCpuLoad5 MetricItem `json:"sysCpuLoad5"` // 系统CPU负载2
|
||||
MetricSysCpuLoad15 MetricItem `json:"sysCpuLoad15"` // 系统CPU负载3
|
||||
MetricSysMemTotal MetricItem `json:"sysMemTotal"` // 系统内存总量
|
||||
MetricSysMemUsage MetricItem `json:"sysMemUsage"` // 系统内存使用率
|
||||
MetricSysDiskTotal MetricItem `json:"sysDiskTotal"` // 系统磁盘总量
|
||||
MetricSysDiskUsage MetricItem `json:"sysDiskUsage"` // 系统磁盘使用率
|
||||
MetricWaitMsgCount MetricItem `json:"waitMsgCount"` // 等待消息数量
|
||||
MetricOneDeviceWaitMsgCount MetricItem `json:"oneDeviceWaitMsgCount"` // 同一个设备等待消息数量
|
||||
MetricRecvMsgFailCount MetricItem `json:"recvMsgFailCount"` // 接收消息处理失败数
|
||||
MetricRecvMsgWaitCostTime MetricItem `json:"recvMsgWaitCostTime"` // 接收消息等待耗时
|
||||
}
|
||||
type XjServerInfo struct {
|
||||
NodeName string `json:"nodeName"`
|
||||
SvrType int `json:"svrType"`
|
||||
SvrCode string `json:"svrCode"` // 服务器编号
|
||||
ShardId int64 `json:"shardId"` // 分片ID
|
||||
StartTime *gtime.Time `json:"startTime"` // 启动时间
|
||||
SysIpLan string `json:"sysIpLan"` // 内网IP
|
||||
SysIpWan string `json:"sysIpWan"` // 外网IP
|
||||
AppVersion string `json:"appVersion"` // 程序版本
|
||||
TenantId string `json:"tenantId"` // 租户ID
|
||||
ReportInterval int64 `json:"reportInterval"` // 上报间隔
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package xjpubservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
xjpubmodel "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubmodel"
|
||||
)
|
||||
|
||||
type (
|
||||
IHttpClient interface {
|
||||
PostObj(ctx context.Context, serviceName string, path string, req interface{}, res interface{}) (err error)
|
||||
Post(ctx context.Context, serviceName string, path string, req []byte) (res []byte, err error)
|
||||
AllServerPost(ctx context.Context, serviceName string, path string, req []byte) (resMap map[string][]byte, err error)
|
||||
}
|
||||
IUpstreamProxyClient interface {
|
||||
// 物联网卡在线信息实时查询
|
||||
QuerySimSession(ctx context.Context, req *xjpubmodel.SimSessionInput) (res *xjpubmodel.SimSessionOutput, err error)
|
||||
// 物联网卡卡状态查询
|
||||
QuerySimCardStatus(ctx context.Context, req *xjpubmodel.SimCardStatusInput) (res *xjpubmodel.SimCardStatusOutput, err error)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localHttpClient IHttpClient
|
||||
localUpstreamProxyClient IUpstreamProxyClient
|
||||
)
|
||||
|
||||
func HttpClient() IHttpClient {
|
||||
if localHttpClient == nil {
|
||||
panic("implement not found for interface IHttpClient, forgot register?")
|
||||
}
|
||||
return localHttpClient
|
||||
}
|
||||
|
||||
func RegisterHttpClient(i IHttpClient) {
|
||||
localHttpClient = i
|
||||
}
|
||||
|
||||
func UpstreamProxyClient() IUpstreamProxyClient {
|
||||
if localUpstreamProxyClient == nil {
|
||||
panic("implement not found for interface IUpstreamProxyClient, forgot register?")
|
||||
}
|
||||
return localUpstreamProxyClient
|
||||
}
|
||||
|
||||
func RegisterUpstreamProxyClient(i IUpstreamProxyClient) {
|
||||
localUpstreamProxyClient = i
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package xjpubservice
|
||||
|
||||
import (
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubmodel"
|
||||
)
|
||||
|
||||
type (
|
||||
IInfo interface {
|
||||
GetInfo() *xjpubmodel.InfoModel
|
||||
SetInfoName(Type string, Name string, Title string, Description string)
|
||||
SetInfoBuild(buildVersion string, buildTime string, commitID string)
|
||||
SetInfoData(data map[string]interface{})
|
||||
GetInfoData() map[string]interface{}
|
||||
AddInfoData(key string, value interface{})
|
||||
DelInfoData(key string)
|
||||
GetInfoDataByKey(key string) interface{}
|
||||
}
|
||||
IInfoRpc interface {
|
||||
GetInfo() *xjpubmodel.InfoModel
|
||||
SetInfoName(Type string, Name string, Title string, Description string)
|
||||
SetInfoBuild(buildVersion string, buildTime string, commitID string)
|
||||
SetInfoData(data map[string]interface{})
|
||||
GetInfoData() map[string]interface{}
|
||||
AddInfoData(key string, value interface{})
|
||||
DelInfoData(key string)
|
||||
GetInfoDataByKey(key string) interface{}
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localInfo IInfo
|
||||
localInfoRpc IInfoRpc
|
||||
)
|
||||
|
||||
func Info() IInfo {
|
||||
if localInfo == nil {
|
||||
panic("implement not found for interface IInfo, forgot register?")
|
||||
}
|
||||
return localInfo
|
||||
}
|
||||
|
||||
func RegisterInfo(i IInfo) {
|
||||
localInfo = i
|
||||
}
|
||||
|
||||
func InfoRpc() IInfoRpc {
|
||||
if localInfoRpc == nil {
|
||||
panic("implement not found for interface IInfoRpc, forgot register?")
|
||||
}
|
||||
return localInfoRpc
|
||||
}
|
||||
|
||||
func RegisterInfoRpc(i IInfoRpc) {
|
||||
localInfoRpc = i
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package xjpubservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
type (
|
||||
IMiddleware interface {
|
||||
// 响应处理中间件
|
||||
ResponseHandler(r *ghttp.Request)
|
||||
// CORS 跨域处理
|
||||
CORS(r *ghttp.Request)
|
||||
// IsExceptLogin 判断是否需要验证登录
|
||||
IsExceptLogin(ctx context.Context, path string) bool
|
||||
// ResponseHandlerRaw 返回处理中间件
|
||||
ResponseHandlerRaw(r *ghttp.Request)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localMiddleware IMiddleware
|
||||
)
|
||||
|
||||
func Middleware() IMiddleware {
|
||||
if localMiddleware == nil {
|
||||
panic("implement not found for interface IMiddleware, forgot register?")
|
||||
}
|
||||
return localMiddleware
|
||||
}
|
||||
|
||||
func RegisterMiddleware(i IMiddleware) {
|
||||
localMiddleware = i
|
||||
}
|
||||
Reference in New Issue
Block a user