Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c62f529e3 | ||
|
|
9d3b3404e4 | ||
| bfccf4d468 | |||
| cd72620e49 | |||
|
|
5bb23deb3b | ||
| 2c713adc16 | |||
|
|
21f09ea41e | ||
| 4d06ad3e8b | |||
| 52a81a404e | |||
| 6cd06d86bc | |||
|
|
ca9f7047c6 | ||
|
|
2de73fea00 | ||
|
|
4b73f086b1 | ||
|
|
c08950c10a | ||
|
|
d691648916 | ||
|
|
8060cdb508 | ||
|
|
50c23df124 | ||
|
|
04b8e5b03b | ||
|
|
dd95b8d8b1 | ||
|
|
dd9a692858 | ||
|
|
b5374b85ff | ||
|
|
5172824358 | ||
|
|
51ff7d1ffd | ||
|
|
c7f24e3b6d | ||
| f7948263c5 | |||
| fc42bc92ff | |||
| b8f693ef82 | |||
| 6ec06c2813 | |||
| 7983651fcd | |||
| d7fb72b5e0 | |||
| 6d1f59fd35 | |||
| 93daa022bc | |||
| ca00b34e24 | |||
| 922cfd6a02 | |||
| d131495f4f | |||
| 04451d4b2f | |||
| e184fff689 | |||
| 33d1b2e0ee | |||
| 433cd1f8bc | |||
| da87dee55c | |||
| 4fe311b722 | |||
| a4c6acf56d | |||
| ce98b833ae | |||
| 4aa5110726 | |||
| d4b7e7e9e6 | |||
| 98ee26f215 | |||
| 0218dfd02e | |||
|
|
629ec74be6 | ||
| a128eb8461 | |||
| c2858f1002 | |||
|
|
5819a8e08f | ||
|
|
a2e3bfab77 | ||
|
|
f1310d093e | ||
|
|
fd967b8c1d | ||
|
|
8d8ec866cd |
2
cache/redis/redis.go
vendored
2
cache/redis/redis.go
vendored
@@ -59,6 +59,6 @@ func New(dsn string, hashRadix string) *RedisClient {
|
||||
|
||||
func Hash(s string) int {
|
||||
h := fnv.New32a()
|
||||
h.Write([]byte(s))
|
||||
h.Write([]byte(strings.ToLower(s)))
|
||||
return int(h.Sum32()) % vars.RedisShardings
|
||||
}
|
||||
|
||||
31
conf/new.go
31
conf/new.go
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/env"
|
||||
"git.apinb.com/bsm-sdk/core/print"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -26,9 +27,11 @@ func New(srvKey string, cfg any) {
|
||||
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)
|
||||
|
||||
print.Info("[BSM - %s] Config File: %s", srvKey, cfp)
|
||||
print.Info("[BSM - %s] Check Configure ...", vars.ServiceKey)
|
||||
|
||||
// 读取配置文件内容
|
||||
yamlFile, err := os.ReadFile(cfp)
|
||||
@@ -41,10 +44,6 @@ func New(srvKey string, cfg any) {
|
||||
log.Fatalln("ERROR: Service Not Nil", cfp)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(yamlFile), "Port:") {
|
||||
log.Fatalln("ERROR: Port Not Nil", cfp)
|
||||
}
|
||||
|
||||
// 解析YAML
|
||||
err = yaml.Unmarshal(yamlFile, cfg)
|
||||
if err != nil {
|
||||
@@ -55,15 +54,29 @@ func New(srvKey string, cfg any) {
|
||||
func NotNil(values ...string) {
|
||||
for _, value := range values {
|
||||
if strings.TrimSpace(value) == "" {
|
||||
log.Fatalln("ERROR:Must config not nil")
|
||||
log.Fatalln("ERROR:Must config key not nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CheckPort(port int) int {
|
||||
if port <= 0 || port >= 65535 {
|
||||
func PrintInfo(addr string) {
|
||||
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())))
|
||||
return r.IntN(65535-1024) + 1024 // 生成1024到65535之间的随机端口
|
||||
p := r.IntN(65535-1024) + 1024 // 生成1024到65535之间的随机端口
|
||||
return utils.Int2String(p)
|
||||
}
|
||||
return port
|
||||
}
|
||||
|
||||
func CheckIP(ip string) string {
|
||||
if ip == "" {
|
||||
return utils.GetLocationIP()
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package conf
|
||||
|
||||
type Base struct {
|
||||
Service string `yaml:"Service"` // 服务名称
|
||||
Port int `yaml:"Port"` // 服务监听端口,0为自动随机端口
|
||||
Cache string `yaml:"Cache"` // REDIS缓存
|
||||
OnMicroService bool `yaml:"OnMicroService"` // 是否启用微服务
|
||||
SecretKey string `yaml:"SecretKey"` // 服务秘钥
|
||||
Service string `yaml:"Service"` // 服务名称
|
||||
Port string `yaml:"Port"` // 服务监听端口,0为自动随机端口
|
||||
Cache string `yaml:"Cache"` // REDIS缓存
|
||||
SecretKey string `yaml:"SecretKey"` // 服务秘钥
|
||||
BindIP string `yaml:"BindIP"` // 绑定IP
|
||||
Addr string `yaml:"Addr"`
|
||||
OnMicroService bool `yaml:"OnMicroService"`
|
||||
}
|
||||
|
||||
type DBConf struct {
|
||||
@@ -13,6 +15,16 @@ type DBConf struct {
|
||||
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 {
|
||||
Name string // APM服务名称
|
||||
Platform string `yaml:"Platform"` // APM平台:apm,skywalking
|
||||
@@ -37,11 +49,14 @@ type RpcConf struct {
|
||||
}
|
||||
|
||||
type OssConf struct {
|
||||
Platform string `yaml:"Platform"` // oss平台:aliyun,tencent,huawei,aws,minio
|
||||
Site string `yaml:"Site"` // oss站点HOST
|
||||
Endpoint string `yaml:"Endpoint"` // oss服务接入地址
|
||||
Region string `yaml:"Region"` // oss服务区域
|
||||
AccessKeyID string `yaml:"AccessKeyId"` // oss AccessKeyId
|
||||
AccessKeySecret string `yaml:"AccessKeySecret"` // oss AccessKeySecret
|
||||
UseSSL bool `yaml:"UseSSL"` // 是否使用SSL
|
||||
|
||||
}
|
||||
|
||||
type MqConf struct {
|
||||
|
||||
@@ -21,13 +21,13 @@ var (
|
||||
JwtSecretLen int
|
||||
)
|
||||
|
||||
func New(token string) {
|
||||
JwtSecret = []byte(token)
|
||||
func New(secret string) {
|
||||
JwtSecret = []byte(secret)
|
||||
JwtSecretLen = len(env.Runtime.JwtSecretKey)
|
||||
}
|
||||
|
||||
func GenerateTokenAes(id uint, identity, client, role string, owner any, extend map[string]string) (string, error) {
|
||||
if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false {
|
||||
if !(JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) {
|
||||
return "", errcode.ErrJWTSecretKey
|
||||
}
|
||||
expireTime := time.Now().Add(vars.JwtExpireDay)
|
||||
|
||||
58
data/map_float.go
Normal file
58
data/map_float.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// Cache
|
||||
CacheMapFloat *MapFloat
|
||||
)
|
||||
|
||||
// lock
|
||||
type MapFloat struct {
|
||||
sync.RWMutex
|
||||
Data map[string]float64
|
||||
}
|
||||
|
||||
func NewMapFloat() *MapFloat {
|
||||
return &MapFloat{
|
||||
Data: make(map[string]float64),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *MapFloat) All() map[string]float64 {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
return c.Data
|
||||
}
|
||||
|
||||
func (c *MapFloat) Get(key string) float64 {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
vals, ok := c.Data[key]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
return vals
|
||||
}
|
||||
|
||||
func (c *MapFloat) Set(key string, val float64) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.Data[key] = val
|
||||
}
|
||||
|
||||
func (c *MapFloat) Keys() (keys []string) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
for k, _ := range c.Data {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
51
data/map_string.go
Normal file
51
data/map_string.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// Cache
|
||||
CacheMapString *MapString
|
||||
)
|
||||
|
||||
// lock
|
||||
type MapString struct {
|
||||
sync.RWMutex
|
||||
Data map[string]string
|
||||
}
|
||||
|
||||
func NewMapString() *MapString {
|
||||
return &MapString{
|
||||
Data: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *MapString) Get(key string) string {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
vals, ok := c.Data[key]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
return vals
|
||||
}
|
||||
|
||||
func (c *MapString) Set(key, val string) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.Data[key] = val
|
||||
}
|
||||
|
||||
func (c *MapString) Keys() (keys []string) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
for k, _ := range c.Data {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -8,6 +8,20 @@ import (
|
||||
"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.
|
||||
func NewPostgreSql(dsn string, options *types.SqlOptions) (*gorm.DB, error) {
|
||||
var err error
|
||||
|
||||
@@ -10,16 +10,23 @@ var (
|
||||
ErrHeaderRequestId = NewError(101, "Header Request-Id Not Found")
|
||||
ErrHeaderAuthorization = NewError(102, "Header Authorization Not Found")
|
||||
ErrHeaderSecretKey = NewError(103, "Header Secret-Key Not Found")
|
||||
ErrHeaderMustParams = NewError(104, "Header Must Params")
|
||||
)
|
||||
|
||||
// standard error code ,start:110
|
||||
var (
|
||||
ErrRequestParse = NewError(111, "Request Parse Fail")
|
||||
ErrRequestMust = NewError(112, "Request Params Required")
|
||||
ErrPermission = NewError(113, "Permission Denied")
|
||||
ErrJsonUnmarshal = NewError(114, "Json Unmarshal Fail")
|
||||
ErrJsonMarshal = NewError(115, "Json Marshal Fail")
|
||||
ErrInternal = NewError(116, "Internal Server Error")
|
||||
ErrEmpty = NewError(110, "Data Is Empty")
|
||||
ErrRequestParse = NewError(111, "Request Parse Fail")
|
||||
ErrRequestMust = NewError(112, "Request Params Required")
|
||||
ErrPermission = NewError(113, "Permission Denied")
|
||||
ErrJsonUnmarshal = NewError(114, "Json Unmarshal Fail")
|
||||
ErrJsonMarshal = NewError(115, "Json Marshal Fail")
|
||||
ErrInternal = NewError(116, "Internal Server Error")
|
||||
ErrPassword = NewError(117, "Password Incorrect")
|
||||
ErrAccountNotFound = NewError(118, "Account Not Found")
|
||||
ErrAccountDisabled = NewError(119, "Account Disabled")
|
||||
ErrDisabled = NewError(120, "Status Disabled")
|
||||
ErrRecordNotFound = NewError(121, "Record Not Found")
|
||||
)
|
||||
|
||||
// jwt error code ,start:130
|
||||
|
||||
24
go.mod
24
go.mod
@@ -1,10 +1,12 @@
|
||||
module git.apinb.com/bsm-sdk/core
|
||||
|
||||
go 1.23.6
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
github.com/FishGoddess/cachego v0.6.1
|
||||
github.com/elastic/go-elasticsearch/v8 v8.17.0
|
||||
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/oklog/ulid/v2 v2.1.0
|
||||
github.com/redis/go-redis/v9 v9.7.0
|
||||
@@ -16,14 +18,14 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.12.8 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.3 // indirect
|
||||
github.com/bytedance/sonic v1.13.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.24.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.25.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
@@ -42,7 +44,7 @@ require (
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/elastic/elastic-transport-go/v8 v8.6.0 // indirect
|
||||
github.com/elastic/elastic-transport-go/v8 v8.6.1 // indirect
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
@@ -57,7 +59,7 @@ require (
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/nats-io/nkeys v0.4.9 // indirect
|
||||
github.com/nats-io/nkeys v0.4.10 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
github.com/tklauser/numcpus v0.9.0 // indirect
|
||||
@@ -69,13 +71,13 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/grpc v1.70.0
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
)
|
||||
|
||||
46
go.sum
46
go.sum
@@ -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/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
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.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
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.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
|
||||
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||
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/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
@@ -23,10 +23,10 @@ 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/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/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/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/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/go-elasticsearch/v8 v8.17.1 h1:bOXChDoCMB4TIwwGqKd031U8OXssmWLT3UrAr9EGs3Q=
|
||||
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/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||
@@ -47,8 +47,8 @@ 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/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/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/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/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@@ -56,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/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
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.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
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/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
@@ -98,8 +100,8 @@ 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/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/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/go.mod h1:OjRrnIKnWBFl+s4YK5ChQfvHP2fxqZexrKJoVVyWB3U=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
|
||||
@@ -168,16 +170,16 @@ 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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
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-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/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -203,10 +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-20191204190536-9bdfabe68543/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-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
|
||||
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/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||
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/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
|
||||
@@ -8,31 +8,30 @@ import (
|
||||
var Response Reply
|
||||
|
||||
type Reply struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data any `json:"data"`
|
||||
Code int32 `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Result any `json:"result"`
|
||||
}
|
||||
|
||||
func (reply *Reply) Success(ctx *gin.Context, data any) {
|
||||
reply.Code = 200
|
||||
reply.Code = 0
|
||||
reply.Result = data
|
||||
reply.Message = ""
|
||||
if data == nil {
|
||||
reply.Data = ""
|
||||
reply.Result = ""
|
||||
}
|
||||
|
||||
ctx.JSON(200, reply)
|
||||
return
|
||||
}
|
||||
func (reply *Reply) Error(ctx *gin.Context, err error) {
|
||||
reply.Code = 500
|
||||
reply.Result = ""
|
||||
// Status code defaults to 500
|
||||
e, ok := status.FromError(err)
|
||||
if ok {
|
||||
reply.Code = int(e.Code())
|
||||
reply.Code = int32(e.Code())
|
||||
}
|
||||
|
||||
reply.Msg = e.Message()
|
||||
reply.Message = e.Message()
|
||||
|
||||
// Send error
|
||||
ctx.JSON(200, reply)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -17,14 +17,14 @@ var (
|
||||
|
||||
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)
|
||||
grantResp, err := lease.Grant(context.TODO(), 5)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceAddr := utils.GetLocationIP() + ":" + utils.Int2String(port)
|
||||
serviceAddr := utils.GetLocationIP() + ":" + port
|
||||
|
||||
key := RootPrefix + serviceName + "/" + utils.Int642String(time.Now().UnixNano())
|
||||
_, err = cli.KV.Put(context.TODO(), key, serviceAddr, clientv3.WithLease(grantResp.ID))
|
||||
|
||||
@@ -58,8 +58,8 @@ var (
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
const (
|
||||
signKey = "8E853B589944FF7A56BEF02AAA51D6F4"
|
||||
LICENCE_KEY = "TRAIN_LICENCE_KEY"
|
||||
signKey = "1F36659EC27CFFF849E068EA80B1A4CA"
|
||||
LICENCE_KEY = "BLOCKS_KEY"
|
||||
)
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
72
middleware/jwt.go
Normal file
72
middleware/jwt.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"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
|
||||
}
|
||||
14
oplog/new.go
Normal file
14
oplog/new.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package oplog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
)
|
||||
|
||||
func New(endpoint string, data []*LogItem) {
|
||||
jsonBytes, _ := json.Marshal(data)
|
||||
|
||||
go utils.HttpPost(endpoint, nil, jsonBytes)
|
||||
|
||||
}
|
||||
19
oplog/types.go
Normal file
19
oplog/types.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package oplog
|
||||
|
||||
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"
|
||||
Type_Create string = "create"
|
||||
)
|
||||
@@ -3,28 +3,36 @@ package print
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var logger *log.Logger
|
||||
|
||||
func init() {
|
||||
logger = log.New(os.Stdout, "", 0) // 创建一个新的 Logger 实例,不带任何标志
|
||||
logger.SetFlags(log.Ldate | log.Ltime)
|
||||
}
|
||||
|
||||
// record INFO message. Color White
|
||||
func Info(format string, a ...interface{}) {
|
||||
message := fmt.Sprintf("\033[37m[Info] "+format+"\033[0m\n", a...)
|
||||
log.Print(message)
|
||||
logger.Print(message)
|
||||
}
|
||||
|
||||
// record Warn message. Color Orange
|
||||
func Warn(format string, a ...interface{}) {
|
||||
message := fmt.Sprintf("\033[33m[Warn] "+format+"\033[0m\n", a...)
|
||||
log.Print(message)
|
||||
logger.Print(message)
|
||||
}
|
||||
|
||||
// record Success message. Color Green
|
||||
func Success(format string, a ...interface{}) {
|
||||
message := fmt.Sprintf("\033[32m[Success] "+format+"\033[0m\n", a...)
|
||||
log.Print(message)
|
||||
message := fmt.Sprintf("\033[32m[Succ] "+format+"\033[0m\n", a...)
|
||||
logger.Print(message)
|
||||
}
|
||||
|
||||
// record ERROR message. Color Red
|
||||
func Error(format string, a ...interface{}) {
|
||||
message := fmt.Sprintf("\033[31m[Error] "+format+"\033[0m\n", a...)
|
||||
log.Print(message)
|
||||
logger.Print(message)
|
||||
}
|
||||
|
||||
60
service/meta.go
Normal file
60
service/meta.go
Normal 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
128
service/register.go
Normal 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
125
service/service.go
Normal 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
65
third/wechat.go
Normal 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
|
||||
}
|
||||
46
types/db.go
46
types/db.go
@@ -10,62 +10,68 @@ type (
|
||||
|
||||
// sql options
|
||||
SqlOptions struct {
|
||||
MaxIdleConns int
|
||||
MaxOpenConns int
|
||||
MaxIdleConns int `gorm:"column:max_idle_conns;" json:"max_idle_conns"`
|
||||
MaxOpenConns int `gorm:"column:max_open_conns;" json:"max_open_conns"`
|
||||
ConnMaxLifetime time.Duration
|
||||
|
||||
LogStdout bool
|
||||
Debug bool
|
||||
LogStdout bool `gorm:"column:log_stdout;" json:"log_stdout"`
|
||||
Debug bool `gorm:"column:debug;" json:"debug"`
|
||||
}
|
||||
|
||||
// standard ID,Identity definition.
|
||||
Std_IDIdentity struct {
|
||||
ID uint `gorm:"primarykey;" json:"id"`
|
||||
ID uint `gorm:"column:id;primarykey;" json:"id"`
|
||||
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识,24位NanoID,36位为ULID
|
||||
}
|
||||
|
||||
// standard ID,Created,Updated,Deleted definition.
|
||||
Std_IICUDS struct {
|
||||
ID uint `gorm:"primarykey;" json:"id"`
|
||||
ID uint `gorm:"column:id;primarykey;" json:"id"`
|
||||
Identity string `gorm:"column:identity;type:varchar(36);uniqueIndex;" json:"identity"` // 唯一标识,24位NanoID,36位为ULID
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"`
|
||||
Status int8 `gorm:"default:0;index;" json:"status"` // 状态:默认为0,-1禁止,1为正常
|
||||
CreatedAt time.Time `gorm:"column:created_at;" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index;" json:"deleted_at"`
|
||||
Status int8 `gorm:"column:status;default:0;index;" json:"status"` // 状态:默认为0,-1禁止,1为正常
|
||||
}
|
||||
|
||||
// standard ID,Identity,Created,Updated,Deleted,Status definition.
|
||||
Std_ICUD struct {
|
||||
ID uint `gorm:"primarykey;" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"`
|
||||
ID uint `gorm:"column:id;primarykey;" json:"id"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index;" json:"deleted_at"`
|
||||
}
|
||||
|
||||
// standard ID,Created definition.
|
||||
Std_IdCreated struct {
|
||||
ID uint `gorm:"primarykey;" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ID uint `gorm:"column:id;primarykey;" json:"id"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;" json:"created_at"`
|
||||
}
|
||||
|
||||
// standard PassportID,PassportIdentity definition.
|
||||
Std_Passport struct {
|
||||
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;" json:"passport_identity"` // 用户唯一标识,24位NanoID,36位为UUID
|
||||
}
|
||||
|
||||
// standard OwnerID,OwnerIdentity definition.
|
||||
Std_Owner struct {
|
||||
OwnerID uint `gorm:"column:owner_id;Index;" json:"owner_id"`
|
||||
OwnerIdentity string `gorm:"column:owner_identity;type:varchar(36);Index;" json:"owner_identity"` // 用户唯一标识,24位NanoID,36位为UUID
|
||||
}
|
||||
|
||||
// standard ID definition.
|
||||
Std_ID struct {
|
||||
ID uint `gorm:"primarykey;" json:"id"`
|
||||
ID uint `gorm:"column:id;primarykey;" json:"id"`
|
||||
}
|
||||
|
||||
// standard Identity definition.
|
||||
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;" json:"identity"` // 唯一标识,24位NanoID,36位为UUID
|
||||
}
|
||||
|
||||
// standard Status definition.
|
||||
Std_Status struct {
|
||||
Status int8 `gorm:"default:0;index;" json:"status"` // 状态:默认为0,-1禁止,1为正常
|
||||
Status int64 `gorm:"column:status;default:0;index;" json:"status"` // 状态:默认为0,-1禁止,1为正常
|
||||
}
|
||||
)
|
||||
|
||||
@@ -13,4 +13,5 @@ type JwtClaims struct {
|
||||
Owner any `json:"owner"`
|
||||
Role string `json:"role"`
|
||||
ExpiresAt int64 `json:"exp"`
|
||||
SsoToken string `json:"sso_token"`
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// 将字符串写入文件
|
||||
func StringToFile(path, content string) error {
|
||||
startF, err := os.Create(path)
|
||||
if err != nil {
|
||||
@@ -18,3 +20,44 @@ func StringToFile(path, content string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 递归遍历文件夹
|
||||
// rootDir: 文件夹根目录
|
||||
// s: 存储文件名的切片
|
||||
// filter: 过滤条件:".git", ".idea", ".vscode", ".gitignore", ".gitea", ".github", ".golangci.yml", "*.pyc"
|
||||
func FileTree(rootDir string, s []string, filter []string) ([]string, error) {
|
||||
rd, err := os.ReadDir(rootDir)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
for _, fi := range rd {
|
||||
// 检查文件名是否匹配任何一个过滤模式
|
||||
matched := false
|
||||
for _, item := range filter {
|
||||
exists, err := filepath.Match(item, fi.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if exists {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if matched {
|
||||
continue
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
fullDir := rootDir + "/" + fi.Name()
|
||||
s, err = FileTree(fullDir, s, filter)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
} else {
|
||||
fullName := rootDir + "/" + fi.Name()
|
||||
s = append(s, fullName)
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
ulid "github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
func UUID() string {
|
||||
return uuid.Must(uuid.NewV7()).String()
|
||||
}
|
||||
|
||||
// remove nanoid,uuid,replace to ulid
|
||||
func ULID() string {
|
||||
return ulid.Make().String()
|
||||
|
||||
68
utils/net.go
68
utils/net.go
@@ -2,6 +2,7 @@ package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func IsPublicIP(ipString string) bool {
|
||||
@@ -32,24 +34,55 @@ func IsPublicIP(ipString string) bool {
|
||||
}
|
||||
|
||||
// Get Location IP .
|
||||
func GetLocationIP() string {
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
func GetLocationIP() (localIp string) {
|
||||
localIp = "127.0.0.1"
|
||||
// Get all network interfaces
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return ""
|
||||
return
|
||||
}
|
||||
ip := ""
|
||||
for _, a := range addrs {
|
||||
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||
if ipnet.IP.To4() != nil {
|
||||
ip = ipnet.IP.String()
|
||||
break
|
||||
|
||||
for _, iface := range interfaces {
|
||||
// Skip the loopback interface
|
||||
if iface.Flags&net.FlagLoopback != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 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 ip
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func LocalIPv4s() ([]string, error) {
|
||||
@@ -89,6 +122,15 @@ func HttpGet(url string) ([]byte, error) {
|
||||
return body, err
|
||||
}
|
||||
|
||||
func HttpPostJSON(url string, header map[string]string, data map[string]any) ([]byte, error) {
|
||||
bytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return HttpPost(url, header, bytes)
|
||||
}
|
||||
|
||||
func HttpPost(url string, header map[string]string, data []byte) ([]byte, error) {
|
||||
var err error
|
||||
reader := bytes.NewBuffer(data)
|
||||
|
||||
14
utils/time.go
Normal file
14
utils/time.go
Normal 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
|
||||
}
|
||||
@@ -4,4 +4,7 @@ var (
|
||||
RUN_MODE_DEV = "dev"
|
||||
RUN_MODE_TEST = "test"
|
||||
RUN_MODE_PROD = "prod"
|
||||
|
||||
ServiceLease int64 = 60
|
||||
ServiceRootPrefix string = "/"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user