Compare commits

...

28 Commits

Author SHA1 Message Date
zhaoxiaorong
c08950c10a fix 2025-04-11 18:06:08 +08:00
zhaoxiaorong
d691648916 fix 2025-04-11 17:53:50 +08:00
zhaoxiaorong
8060cdb508 fix 2025-04-11 17:50:06 +08:00
zhaoxiaorong
50c23df124 fix 2025-04-11 17:44:49 +08:00
zhaoxiaorong
04b8e5b03b fix 2025-04-11 16:45:11 +08:00
zhaoxiaorong
dd95b8d8b1 fix 2025-04-09 15:24:28 +08:00
zhaoxiaorong
dd9a692858 fix 2025-04-09 11:12:42 +08:00
zhaoxiaorong
b5374b85ff fix 2025-04-09 10:56:49 +08:00
zhaoxiaorong
5172824358 fix 2025-04-09 10:34:01 +08:00
zhaoxiaorong
51ff7d1ffd fix 2025-04-09 10:19:15 +08:00
zhaoxiaorong
c7f24e3b6d fix 2025-04-09 09:39:51 +08:00
f7948263c5 Merge branch 'main' of https://git.apinb.com/bsm-sdk/core 2025-04-08 15:20:34 +08:00
fc42bc92ff fix parse meta ctx 2025-04-08 15:20:22 +08:00
b8f693ef82 fix net getLocationIP 2025-04-07 11:14:07 +08:00
6ec06c2813 add third 2025-04-06 13:42:44 +08:00
7983651fcd add time <=> string 2025-04-02 14:53:45 +08:00
d7fb72b5e0 add types.db identity default:uuid_generate_v4() 2025-04-01 23:34:24 +08:00
6d1f59fd35 add gateway 2025-03-30 13:24:13 +08:00
93daa022bc add gateway 2025-03-30 13:23:46 +08:00
ca00b34e24 add GatewayConf 2025-03-29 20:14:26 +08:00
922cfd6a02 feat:service mod 2025-03-29 15:02:49 +08:00
d131495f4f up go.mod 2025-03-27 03:17:48 +08:00
04451d4b2f add conf.PrintInfo 2025-03-27 03:10:56 +08:00
e184fff689 add conf.PrintInfo 2025-03-27 03:08:59 +08:00
33d1b2e0ee add SetOptions 2025-03-27 02:52:01 +08:00
433cd1f8bc fix hash key 2025-03-27 02:49:44 +08:00
da87dee55c fix srv key to lower 2025-03-27 02:43:15 +08:00
4fe311b722 add uuid v7 2025-03-12 17:10:04 +08:00
20 changed files with 657 additions and 64 deletions

View File

@@ -59,6 +59,6 @@ func New(dsn string, hashRadix string) *RedisClient {
func Hash(s string) int { func Hash(s string) int {
h := fnv.New32a() h := fnv.New32a()
h.Write([]byte(s)) h.Write([]byte(strings.ToLower(s)))
return int(h.Sum32()) % vars.RedisShardings return int(h.Sum32()) % vars.RedisShardings
} }

View File

@@ -12,6 +12,7 @@ import (
"git.apinb.com/bsm-sdk/core/env" "git.apinb.com/bsm-sdk/core/env"
"git.apinb.com/bsm-sdk/core/print" "git.apinb.com/bsm-sdk/core/print"
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/bsm-sdk/core/vars" "git.apinb.com/bsm-sdk/core/vars"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
) )
@@ -26,9 +27,11 @@ func New(srvKey string, cfg any) {
vars.HostName, _ = os.Hostname() vars.HostName, _ = os.Hostname()
// 构造配置文件路径,输出配置文件信息 // 构造配置文件路径,输出配置文件信息
cfp := fmt.Sprintf("%s_%s.yaml", srvKey, env.Runtime.Mode) cfp := fmt.Sprintf("%s_%s.yaml", strings.ToLower(srvKey), env.Runtime.Mode)
cfp = filepath.Join(env.Runtime.Prefix, "etc", cfp) cfp = filepath.Join(env.Runtime.Prefix, "etc", cfp)
print.Info("[BSM - %s] Config File: %s", srvKey, cfp) print.Info("[BSM - %s] Config File: %s", srvKey, cfp)
print.Info("[BSM - %s] Check Configure ...", vars.ServiceKey)
// 读取配置文件内容 // 读取配置文件内容
yamlFile, err := os.ReadFile(cfp) yamlFile, err := os.ReadFile(cfp)
@@ -56,10 +59,24 @@ func NotNil(values ...string) {
} }
} }
func CheckPort(port int) int { func PrintInfo(addr string) {
if port <= 0 || port >= 65535 { print.Success("[BSM - %s] Config Check Success.", vars.ServiceKey)
print.Info("[BSM - %s] Service Name: %s", vars.ServiceKey, vars.ServiceKey)
print.Info("[BSM - %s] Runtime Mode: %s", vars.ServiceKey, env.Runtime.Mode)
}
func CheckPort(port string) string {
if port == "" {
r := rand.New(rand.NewPCG(1000, uint64(time.Now().UnixNano()))) r := rand.New(rand.NewPCG(1000, uint64(time.Now().UnixNano())))
return r.IntN(65535-1024) + 1024 // 生成1024到65535之间的随机端口 p := r.IntN(65535-1024) + 1024 // 生成1024到65535之间的随机端口
return utils.Int2String(p)
} }
return port return port
} }
func CheckIP(ip string) string {
if ip == "" {
return utils.GetLocationIP()
}
return ip
}

View File

@@ -1,11 +1,14 @@
package conf package conf
type Base struct { type Base struct {
Service string `yaml:"Service"` // 服务名称 Service string `yaml:"Service"` // 服务名称
Port int `yaml:"Port"` // 服务监听端口,0为自动随机端口 Port string `yaml:"Port"` // 服务监听端口,0为自动随机端口
Cache string `yaml:"Cache"` // REDIS缓存 Cache string `yaml:"Cache"` // REDIS缓存
OnMicroService bool `yaml:"OnMicroService"` // 是否启用微服务 SecretKey string `yaml:"SecretKey"` // 服务秘钥
SecretKey string `yaml:"SecretKey"` // 服务秘钥 BindIP string `yaml:"BindIP"` // 绑定IP
Addr string `yaml:"Addr"`
OnMicroService bool `yaml:"OnMicroService"`
LoginUrl string `yaml:"LoginUrl"`
} }
type DBConf struct { type DBConf struct {
@@ -13,6 +16,16 @@ type DBConf struct {
Source []string `yaml:"Source"` // 数据库连接 Source []string `yaml:"Source"` // 数据库连接
} }
type MicroServiceConf struct {
Enable bool `yaml:"Enable"` // 是否启用微服务
Anonymous []string `yaml:"Anonymous"`
}
type GatewayConf struct {
Enable bool `yaml:"Enable"` // 是否启用网关服务
Port int `yaml:"Port"` // 服务监听端口
}
type ApmConf struct { type ApmConf struct {
Name string // APM服务名称 Name string // APM服务名称
Platform string `yaml:"Platform"` // APM平台apm,skywalking Platform string `yaml:"Platform"` // APM平台apm,skywalking
@@ -37,11 +50,14 @@ type RpcConf struct {
} }
type OssConf struct { type OssConf struct {
Platform string `yaml:"Platform"` // oss平台aliyun,tencent,huawei,aws,minio
Site string `yaml:"Site"` // oss站点HOST Site string `yaml:"Site"` // oss站点HOST
Endpoint string `yaml:"Endpoint"` // oss服务接入地址 Endpoint string `yaml:"Endpoint"` // oss服务接入地址
Region string `yaml:"Region"` // oss服务区域 Region string `yaml:"Region"` // oss服务区域
AccessKeyID string `yaml:"AccessKeyId"` // oss AccessKeyId AccessKeyID string `yaml:"AccessKeyId"` // oss AccessKeyId
AccessKeySecret string `yaml:"AccessKeySecret"` // oss AccessKeySecret AccessKeySecret string `yaml:"AccessKeySecret"` // oss AccessKeySecret
UseSSL bool `yaml:"UseSSL"` // 是否使用SSL
} }
type MqConf struct { type MqConf struct {

View File

@@ -8,6 +8,20 @@ import (
"gorm.io/gorm/schema" "gorm.io/gorm/schema"
) )
func SetOptions(options *types.SqlOptions) *types.SqlOptions {
if options == nil {
options = &types.SqlOptions{
MaxIdleConns: vars.SqlOptionMaxIdleConns,
MaxOpenConns: vars.SqlOptionMaxIdleConns,
ConnMaxLifetime: vars.SqlOptionConnMaxLifetime,
LogStdout: false,
Debug: false,
}
}
return options
}
// new grom db. // new grom db.
func NewPostgreSql(dsn string, options *types.SqlOptions) (*gorm.DB, error) { func NewPostgreSql(dsn string, options *types.SqlOptions) (*gorm.DB, error) {
var err error var err error

10
go.mod
View File

@@ -5,6 +5,8 @@ go 1.24
require ( require (
github.com/FishGoddess/cachego v0.6.1 github.com/FishGoddess/cachego v0.6.1
github.com/elastic/go-elasticsearch/v8 v8.17.1 github.com/elastic/go-elasticsearch/v8 v8.17.1
github.com/google/uuid v1.6.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3
github.com/nats-io/nats.go v1.39.0 github.com/nats-io/nats.go v1.39.0
github.com/oklog/ulid/v2 v2.1.0 github.com/oklog/ulid/v2 v2.1.0
github.com/redis/go-redis/v9 v9.7.0 github.com/redis/go-redis/v9 v9.7.0
@@ -16,8 +18,8 @@ require (
) )
require ( require (
github.com/bytedance/sonic v1.12.8 // indirect github.com/bytedance/sonic v1.13.2 // indirect
github.com/bytedance/sonic/loader v0.2.3 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect github.com/cloudwego/base64x v0.1.5 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gin-contrib/sse v1.0.0 // indirect github.com/gin-contrib/sse v1.0.0 // indirect
@@ -74,8 +76,8 @@ require (
golang.org/x/sync v0.11.0 // indirect golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/grpc v1.70.0 google.golang.org/grpc v1.70.0
google.golang.org/protobuf v1.36.5 // indirect google.golang.org/protobuf v1.36.5 // indirect
) )

38
go.sum
View File

@@ -4,11 +4,11 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs= github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0= github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
@@ -23,12 +23,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/elastic/elastic-transport-go/v8 v8.6.0 h1:Y2S/FBjx1LlCv5m6pWAF2kDJAHoSjSRSJCApolgfthA=
github.com/elastic/elastic-transport-go/v8 v8.6.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk=
github.com/elastic/elastic-transport-go/v8 v8.6.1 h1:h2jQRqH6eLGiBSN4eZbQnJLtL4bC5b4lfVFRjw2R4e4= github.com/elastic/elastic-transport-go/v8 v8.6.1 h1:h2jQRqH6eLGiBSN4eZbQnJLtL4bC5b4lfVFRjw2R4e4=
github.com/elastic/elastic-transport-go/v8 v8.6.1/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk= github.com/elastic/elastic-transport-go/v8 v8.6.1/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk=
github.com/elastic/go-elasticsearch/v8 v8.17.0 h1:e9cWksE/Fr7urDRmGPGp47Nsp4/mvNOrU8As1l2HQQ0=
github.com/elastic/go-elasticsearch/v8 v8.17.0/go.mod h1:lGMlgKIbYoRvay3xWBeKahAiJOgmFDsjZC39nmO3H64=
github.com/elastic/go-elasticsearch/v8 v8.17.1 h1:bOXChDoCMB4TIwwGqKd031U8OXssmWLT3UrAr9EGs3Q= github.com/elastic/go-elasticsearch/v8 v8.17.1 h1:bOXChDoCMB4TIwwGqKd031U8OXssmWLT3UrAr9EGs3Q=
github.com/elastic/go-elasticsearch/v8 v8.17.1/go.mod h1:MVJCtL+gJJ7x5jFeUmA20O7rvipX8GcQmo5iBcmaJn4= github.com/elastic/go-elasticsearch/v8 v8.17.1/go.mod h1:MVJCtL+gJJ7x5jFeUmA20O7rvipX8GcQmo5iBcmaJn4=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
@@ -51,8 +47,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8= github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
@@ -62,11 +56,13 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
@@ -104,8 +100,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nats-io/nats.go v1.39.0 h1:2/yg2JQjiYYKLwDuBzV0FbB2sIV+eFNkEevlRi4n9lI= github.com/nats-io/nats.go v1.39.0 h1:2/yg2JQjiYYKLwDuBzV0FbB2sIV+eFNkEevlRi4n9lI=
github.com/nats-io/nats.go v1.39.0/go.mod h1:MgRb8oOdigA6cYpEPhXJuRVH6UE/V4jblJ2jQ27IXYM= github.com/nats-io/nats.go v1.39.0/go.mod h1:MgRb8oOdigA6cYpEPhXJuRVH6UE/V4jblJ2jQ27IXYM=
github.com/nats-io/nkeys v0.4.9 h1:qe9Faq2Gxwi6RZnZMXfmGMZkg3afLLOtrU+gDZJ35b0=
github.com/nats-io/nkeys v0.4.9/go.mod h1:jcMqs+FLG+W5YO36OX6wFIFcmpdAns+w1Wm6D3I/evE=
github.com/nats-io/nkeys v0.4.10 h1:glmRrpCmYLHByYcePvnTBEAwawwapjCPMjy2huw20wc= github.com/nats-io/nkeys v0.4.10 h1:glmRrpCmYLHByYcePvnTBEAwawwapjCPMjy2huw20wc=
github.com/nats-io/nkeys v0.4.10/go.mod h1:OjRrnIKnWBFl+s4YK5ChQfvHP2fxqZexrKJoVVyWB3U= github.com/nats-io/nkeys v0.4.10/go.mod h1:OjRrnIKnWBFl+s4YK5ChQfvHP2fxqZexrKJoVVyWB3U=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
@@ -176,8 +170,6 @@ golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -186,8 +178,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -215,14 +205,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b h1:i+d0RZa8Hs2L/MuaOQYI+krthcxdEbEM2N+Tf3kJ4zk= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 h1:5bKytslY8ViY0Cj/ewmRtrWHW64bNF03cAatUUFCdFI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=

View File

@@ -17,14 +17,14 @@ var (
type service struct{} type service struct{}
func (s *service) Register(cli *clientv3.Client, serviceName string, port int) error { func (s *service) Register(cli *clientv3.Client, serviceName string, port string) error {
lease := clientv3.NewLease(cli) lease := clientv3.NewLease(cli)
grantResp, err := lease.Grant(context.TODO(), 5) grantResp, err := lease.Grant(context.TODO(), 5)
if err != nil { if err != nil {
return err return err
} }
serviceAddr := utils.GetLocationIP() + ":" + utils.Int2String(port) serviceAddr := utils.GetLocationIP() + ":" + port
key := RootPrefix + serviceName + "/" + utils.Int642String(time.Now().UnixNano()) key := RootPrefix + serviceName + "/" + utils.Int642String(time.Now().UnixNano())
_, err = cli.KV.Put(context.TODO(), key, serviceAddr, clientv3.WithLease(grantResp.ID)) _, err = cli.KV.Put(context.TODO(), key, serviceAddr, clientv3.WithLease(grantResp.ID))

73
middleware/jwt.go Normal file
View File

@@ -0,0 +1,73 @@
package middleware
import (
"encoding/json"
"fmt"
"log"
"net/http"
"git.apinb.com/bsm-sdk/core/cache/redis"
"git.apinb.com/bsm-sdk/core/crypto/encipher"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/types"
"github.com/gin-gonic/gin"
)
func JwtAuth(redis *redis.RedisClient) gin.HandlerFunc {
return func(c *gin.Context) {
// 从请求头中获取 Authorization
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
log.Println("获取token异常:", "Authorization header is required")
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header is required"})
c.Abort()
return
}
// 提取Token
claims, err := encipher.ParseTokenAes(authHeader)
if err != nil || claims == nil {
log.Println("提取token异常:", "Token is required")
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token is required"})
c.Abort()
return
}
// 从redis 获取token,判断当前redis 是否为空
tokenKey := fmt.Sprintf("%d-%s-%s", claims.ID, claims.Role, "token")
redisToken := redis.Client.Get(redis.Ctx, tokenKey)
if redisToken.Val() == "" {
log.Println("redis异常", "Token status unauthorized")
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token status unauthorized"})
c.Abort()
return
}
// 将解析后的 Token 存储到上下文中
c.Set("Auth", claims)
// 如果 Token 有效,继续处理请求
c.Next()
}
}
// 获取上下文用户登录信息
func ParseAuth(c *gin.Context) (*types.JwtClaims, error) {
claims, ok := c.Get("Auth")
if !ok {
log.Printf("获取登录信息异常: %v", errcode.ErrJWTAuthNotFound)
return nil, errcode.ErrJWTAuthNotFound
}
json_claims, err := json.Marshal(claims)
if err != nil {
log.Printf("解析json异常: %v", err)
return nil, errcode.ErrJsonMarshal
}
var auth *types.JwtClaims
if err := json.Unmarshal(json_claims, &auth); err != nil {
log.Printf("解析json异常: %v", err)
return nil, errcode.ErrJsonUnmarshal
}
return auth, nil
}

32
oplog/new.go Normal file
View File

@@ -0,0 +1,32 @@
package oplog
import (
"bytes"
"encoding/json"
"net/http"
)
func New(endpoint string, data []*LogItem) error {
go PostLog(data, endpoint)
return nil
}
func PostLog(data []*LogItem, endpoint string) (resp *http.Response, err error) {
jsonBytes, err := json.Marshal(data)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(jsonBytes))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err = client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return
}

21
oplog/types.go Normal file
View File

@@ -0,0 +1,21 @@
package oplog
type LogRequest struct {
Data []*LogItem `json:"data"`
}
type LogItem struct {
OpID uint `json:"op_id"`
OpName string `json:"op_name"`
OpType string `json:"op_type"`
Text string `json:"text"`
}
var (
Type_Login string = "login"
Type_Logout string = "logout"
Type_Register string = "register"
Type_Update string = "update"
Type_Delete string = "delete"
Type_Query string = "query"
Type_Other string = "other"
)

View File

@@ -15,24 +15,24 @@ func init() {
// record INFO message. Color White // record INFO message. Color White
func Info(format string, a ...interface{}) { func Info(format string, a ...interface{}) {
message := fmt.Sprintf("\033[37m[Info] "+format+"\033[0m\n", a...) message := fmt.Sprintf("\033[37m[Info] "+format+"\033[0m\n", a...)
logger.Print(message) logger.Print(message)
} }
// record Warn message. Color Orange // record Warn message. Color Orange
func Warn(format string, a ...interface{}) { func Warn(format string, a ...interface{}) {
message := fmt.Sprintf("\033[33m[Warn] "+format+"\033[0m\n", a...) message := fmt.Sprintf("\033[33m[Warn] "+format+"\033[0m\n", a...)
logger.Print(message) logger.Print(message)
} }
// record Success message. Color Green // record Success message. Color Green
func Success(format string, a ...interface{}) { func Success(format string, a ...interface{}) {
message := fmt.Sprintf("\033[32m[Success] "+format+"\033[0m\n", a...) message := fmt.Sprintf("\033[32m[Succ] "+format+"\033[0m\n", a...)
logger.Print(message) logger.Print(message)
} }
// record ERROR message. Color Red // record ERROR message. Color Red
func Error(format string, a ...interface{}) { func Error(format string, a ...interface{}) {
message := fmt.Sprintf("\033[31m[Error] "+format+"\033[0m\n", a...) message := fmt.Sprintf("\033[31m[Error] "+format+"\033[0m\n", a...)
logger.Print(message) logger.Print(message)
} }

60
service/meta.go Normal file
View File

@@ -0,0 +1,60 @@
package service
import (
"context"
"git.apinb.com/bsm-sdk/core/crypto/encipher"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/types"
"git.apinb.com/bsm-sdk/core/utils"
"google.golang.org/grpc/metadata"
)
// 解析Context中MetaData的数据
type ParseOptions struct {
RoleValue string // 判断角色的值
MustPrivateAllow bool // 是否只允许私有IP访问
}
func ParseMetaCtx(ctx context.Context, opts *ParseOptions) (*types.JwtClaims, error) {
// 解析metada中的信息并验证
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil, errcode.ErrJWTAuthNotFound
}
var Authorizations []string = md.Get("authorization")
if len(Authorizations) == 0 || Authorizations[0] == "" {
return nil, errcode.ErrJWTAuthNotFound
}
claims, err := encipher.ParseTokenAes(Authorizations[0])
if err != nil {
return nil, err
}
if opts != nil {
if !checkRole(claims, "role", opts.RoleValue) {
return nil, errcode.ErrPermissionDenied
}
if opts.MustPrivateAllow {
if utils.IsPublicIP(claims.Client) {
return nil, errcode.ErrPermissionDenied
}
}
}
return claims, nil
}
func checkRole(claims *types.JwtClaims, roleKey, roleValue string) bool {
if roleValue == "" {
return true
}
if role, exists := claims.Extend[roleKey]; !exists || role != roleValue {
return false
} else {
return true
}
}

128
service/register.go Normal file
View File

@@ -0,0 +1,128 @@
package service
import (
"context"
"strings"
"time"
"git.apinb.com/bsm-sdk/core/print"
"git.apinb.com/bsm-sdk/core/vars"
clientv3 "go.etcd.io/etcd/client/v3"
)
// ServiceRegister 创建租约注册服务
type ServiceRegister struct {
cli *clientv3.Client //etcd client
leaseID clientv3.LeaseID //租约ID
//租约keepalieve相应chan
keepAliveChan <-chan *clientv3.LeaseKeepAliveResponse
key string //key
val string //value
}
// NewRegister 注册服务至路由表.
//
// ec:EtcdConfig;
//
// routeKey: ServiceRouteRootPrefix + ServiceKey + "/" + utils.GetLocationIP() + addr;
//
// gs:grpc.Server;
func RegisterService(cli *clientv3.Client, routeKey string, methods []string, lease int64) (*ServiceRegister, error) {
ser := &ServiceRegister{
cli: cli,
key: routeKey,
val: strings.Join(methods, ","),
}
//申请租约设置时间keepalive
if err := ser.putKeyWithLease(lease); err != nil {
return nil, err
}
return ser, nil
}
// 设置租约
func (s *ServiceRegister) putKeyWithLease(lease int64) error {
//设置租约时间
resp, err := s.cli.Grant(context.Background(), lease)
if err != nil {
return err
}
//注册服务并绑定租约
_, err = s.cli.Put(context.Background(), s.key, s.val, clientv3.WithLease(resp.ID))
if err != nil {
return err
}
//设置续租 定期发送需求请求
leaseRespChan, err := s.cli.KeepAlive(context.Background(), resp.ID)
if err != nil {
return err
}
s.leaseID = resp.ID
s.keepAliveChan = leaseRespChan
return nil
}
// ListenLeaseRespChan 监听 续租情况
func (s *ServiceRegister) ListenLeaseRespChan() {
for {
select {
case leaseKeepResp := <-s.keepAliveChan:
if leaseKeepResp == nil {
//log.Println("close lease.")
return
} else {
goto END
}
}
END:
time.Sleep(500 * time.Millisecond)
}
}
// Close 注销服务
func (s *ServiceRegister) Close() error {
//撤销租约
if _, err := s.cli.Revoke(context.Background(), s.leaseID); err != nil {
return err
}
return s.cli.Close()
}
func (s *ServiceRegister) SetAnonymous(key string, urls []string) {
// remove reppeat, clear service all anonymous uri.
anonymous, _ := s.cli.Get(context.Background(), key)
var as []string
if len(anonymous.Kvs) > 0 {
val := string(anonymous.Kvs[0].Value)
as = strings.Split(val, ",")
}
as = append(clearService(as), urls...)
newAnonymous := strings.Join(as, ",")
// put anonymous to etcd
_, err := s.cli.Put(context.Background(), key, newAnonymous)
if err != nil {
print.Error("[BSM Register] Anonymous Fail.")
} else {
print.Info("[BSM Register] Anonymous: %s", newAnonymous)
}
}
func clearService(as []string) (out []string) {
for _, v := range as {
if len(v) >= len(vars.ServiceKey) {
if v[0:len(vars.ServiceKey)] != vars.ServiceKey {
out = append(out, v)
}
}
}
return
}

125
service/service.go Normal file
View File

@@ -0,0 +1,125 @@
package service
import (
"context"
"log"
"net"
"os"
"strconv"
"strings"
"net/http"
gwRuntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"git.apinb.com/bsm-sdk/core/conf"
"git.apinb.com/bsm-sdk/core/env"
"git.apinb.com/bsm-sdk/core/print"
"git.apinb.com/bsm-sdk/core/vars"
clientv3 "go.etcd.io/etcd/client/v3"
"google.golang.org/grpc"
)
type (
// RegisterFn defines the method to register a server.
RegisterFn func(*grpc.Server)
Service struct {
GrpcSrv *grpc.Server
Opts *Options
}
Options struct {
Addr string
EtcdClient *clientv3.Client
MsConf *conf.MicroServiceConf
GatewayConf *conf.GatewayConf
GatewayCtx context.Context
GatewayMux *gwRuntime.ServeMux
}
)
func New(srv *grpc.Server, opts *Options) *Service {
return &Service{GrpcSrv: srv, Opts: opts}
}
func Addr(ip string, port int) string {
return net.JoinHostPort(ip, strconv.Itoa(port))
}
func (s *Service) Start() {
print.Info("[BSM - %s] Service Starting ...", vars.ServiceKey)
// register to etcd.
if s.Opts.MsConf != nil && s.Opts.MsConf.Enable {
if s.Opts.EtcdClient == nil {
print.Error("[BSM Register] Etcd Client is nil.")
os.Exit(1)
}
print.Info("[BSM - %s] Registering Service to Etcd ...", vars.ServiceKey)
// get methods
methods := FoundGrpcMethods(s.GrpcSrv)
// set router key
routerKey := vars.ServiceRootPrefix + "Router/" + env.Runtime.Workspace + "/" + strings.ToLower(vars.ServiceKey) + "/" + s.Opts.Addr
// register to etcd
register, err := RegisterService(s.Opts.EtcdClient, routerKey, methods, vars.ServiceLease)
if err != nil {
log.Panicf("[ERROR] %s Service Register:%s \n", vars.ServiceKey, err.Error())
}
anonKey := vars.ServiceRootPrefix + "Router/" + env.Runtime.Workspace + "/"
register.SetAnonymous(anonKey, s.Opts.MsConf.Anonymous)
// service register lease
go register.ListenLeaseRespChan()
}
// run grpc srv.
tcpListen, err := net.Listen("tcp", s.Opts.Addr)
if err != nil {
panic(err)
}
go func() {
if err := s.GrpcSrv.Serve(tcpListen); err != nil {
panic(err)
}
}()
print.Success("[BSM - %s] Grpc %s Runing Success !", vars.ServiceKey, s.Opts.Addr)
if s.Opts.GatewayConf != nil && s.Opts.GatewayConf.Enable {
addr := Addr("0.0.0.0", s.Opts.GatewayConf.Port)
go s.Gateway(s.Opts.Addr, addr)
print.Success("[BSM - %s] Http %s Runing Success!", vars.ServiceKey, addr)
}
select {}
}
func (s *Service) Gateway(grpcAddr string, httpAddr string) {
// 1. 定义一个context
_, cancel := context.WithCancel(s.Opts.GatewayCtx)
defer cancel()
http.ListenAndServe(httpAddr, s.Opts.GatewayMux)
}
func (s *Service) Stop() {
s.GrpcSrv.GracefulStop()
}
// found grpc methods.
func FoundGrpcMethods(s *grpc.Server) []string {
var mothods []string
for key, srv := range s.GetServiceInfo() {
srvName := strings.Split(key, ".")[1]
for _, mn := range srv.Methods {
mothods = append(mothods, srvName+"."+mn.Name)
}
}
return mothods
}

65
third/wechat.go Normal file
View File

@@ -0,0 +1,65 @@
package third
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"errors"
)
func WeChat_Decrypt(sessionKey, encryptedData, iv string) (string, error) {
aesKey, err := base64.StdEncoding.DecodeString(sessionKey)
if err != nil {
return "", err
}
cipherText, err := base64.StdEncoding.DecodeString(encryptedData)
if err != nil {
return "", err
}
ivBytes, err := base64.StdEncoding.DecodeString(iv)
if err != nil {
return "", err
}
block, err := aes.NewCipher(aesKey)
if err != nil {
return "", err
}
mode := cipher.NewCBCDecrypter(block, ivBytes)
mode.CryptBlocks(cipherText, cipherText)
cipherText, err = WeChat_Pkcs7Unpad(cipherText, block.BlockSize())
if err != nil {
return "", err
}
return string(cipherText), nil
}
// pkcs7Unpad returns slice of the original data without padding
func WeChat_Pkcs7Unpad(data []byte, blockSize int) ([]byte, error) {
var (
// ErrInvalidBlockSize block size不合法
ErrInvalidBlockSize = errors.New("invalid block size")
// ErrInvalidPKCS7Data PKCS7数据不合法
ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data")
// ErrInvalidPKCS7Padding 输入padding失败
ErrInvalidPKCS7Padding = errors.New("invalid padding on input")
)
if blockSize <= 0 {
return nil, ErrInvalidBlockSize
}
if len(data)%blockSize != 0 || len(data) == 0 {
return nil, ErrInvalidPKCS7Data
}
c := data[len(data)-1]
n := int(c)
if n == 0 || n > len(data) {
return nil, ErrInvalidPKCS7Padding
}
for i := 0; i < n; i++ {
if data[len(data)-n+i] != c {
return nil, ErrInvalidPKCS7Padding
}
}
return data[:len(data)-n], nil
}

View File

@@ -21,17 +21,17 @@ type (
// standard ID,Identity definition. // standard ID,Identity definition.
Std_IDIdentity struct { Std_IDIdentity struct {
ID uint `gorm:"primarykey;" json:"id"` ID uint `gorm:"primarykey;" json:"id"`
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识24位NanoID,36位为ULID Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;default:uuid_generate_v4()" json:"identity"` // 唯一标识24位NanoID,36位为ULID
} }
// standard ID,Created,Updated,Deleted definition. // standard ID,Created,Updated,Deleted definition.
Std_IICUDS struct { Std_IICUDS struct {
ID uint `gorm:"primarykey;" json:"id"` ID uint `gorm:"primarykey;" json:"id"`
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识24位NanoID,36位为ULID Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;default:uuid_generate_v4()" json:"identity"` // 唯一标识24位NanoID,36位为ULID
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"` DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"`
Status int64 `gorm:"default:0;index;" json:"status"` // 状态默认为0-1禁止1为正常 Status int8 `gorm:"default:0;index;" json:"status"` // 状态默认为0-1禁止1为正常
} }
// standard ID,Identity,Created,Updated,Deleted,Status definition. // standard ID,Identity,Created,Updated,Deleted,Status definition.
@@ -51,7 +51,7 @@ type (
// standard PassportID,PassportIdentity definition. // standard PassportID,PassportIdentity definition.
Std_Passport struct { Std_Passport struct {
PassportID uint `gorm:"column:passport_id;Index;" json:"passport_id"` PassportID uint `gorm:"column:passport_id;Index;" json:"passport_id"`
PassportIdentity string `gorm:"column:passport_identity;type:varchar(36);Index;" json:"passport_identity"` // 用户唯一标识24位NanoID,36位为ULID PassportIdentity string `gorm:"column:passport_identity;type:varchar(36);Index;default:uuid_generate_v4()" json:"passport_identity"` // 用户唯一标识24位NanoID,36位为ULID
} }
// standard ID definition. // standard ID definition.
@@ -61,7 +61,7 @@ type (
// standard Identity definition. // standard Identity definition.
Std_Identity struct { Std_Identity struct {
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识24位NanoID,36位为ULID Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;default:uuid_generate_v4()" json:"identity"` // 唯一标识24位NanoID,36位为ULID
} }
// standard Status definition. // standard Status definition.

View File

@@ -1,9 +1,14 @@
package utils package utils
import ( import (
"github.com/google/uuid"
ulid "github.com/oklog/ulid/v2" ulid "github.com/oklog/ulid/v2"
) )
func UUID() string {
return uuid.Must(uuid.NewV7()).String()
}
// remove nanoid,uuid,replace to ulid // remove nanoid,uuid,replace to ulid
func ULID() string { func ULID() string {
return ulid.Make().String() return ulid.Make().String()

View File

@@ -9,6 +9,7 @@ import (
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
"strings"
) )
func IsPublicIP(ipString string) bool { func IsPublicIP(ipString string) bool {
@@ -32,24 +33,55 @@ func IsPublicIP(ipString string) bool {
} }
// Get Location IP . // Get Location IP .
func GetLocationIP() string { func GetLocationIP() (localIp string) {
addrs, err := net.InterfaceAddrs() localIp = "127.0.0.1"
// Get all network interfaces
interfaces, err := net.Interfaces()
if err != nil { if err != nil {
return "" return
} }
ip := ""
for _, a := range addrs { for _, iface := range interfaces {
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { // Skip the loopback interface
if ipnet.IP.To4() != nil { if iface.Flags&net.FlagLoopback != 0 {
ip = ipnet.IP.String() continue
break }
// Get addresses associated with the interface
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, addr := range addrs {
// Check if the address is an IPNet
ipnet, ok := addr.(*net.IPNet)
if !ok || ipnet.IP.IsLoopback() {
continue
} }
// Get the IP address
ip := ipnet.IP.To4()
if ip == nil {
continue
}
// Skip IP addresses in the 169.254.x.x range
if strings.HasPrefix(ip.String(), "169.254") {
continue
}
// Skip IP addresses in the 169.254.x.x range
if strings.HasPrefix(ip.String(), "26.26") {
continue
}
// Return the first valid IP address found
return ip.String()
} }
} }
if ip == "" {
return "" return
}
return ip
} }
func LocalIPv4s() ([]string, error) { func LocalIPv4s() ([]string, error) {

14
utils/time.go Normal file
View File

@@ -0,0 +1,14 @@
package utils
import (
"time"
)
func Time2String(layout string, t time.Time) string {
return t.Format(layout)
}
func String2Time(layout, in string) time.Time {
t, _ := time.ParseInLocation(layout, in, time.Local)
return t
}

View File

@@ -4,4 +4,7 @@ var (
RUN_MODE_DEV = "dev" RUN_MODE_DEV = "dev"
RUN_MODE_TEST = "test" RUN_MODE_TEST = "test"
RUN_MODE_PROD = "prod" RUN_MODE_PROD = "prod"
ServiceLease int64 = 60
ServiceRootPrefix string = "/"
) )