Merge branch 'main' of http://192.168.0.229:3180/OMC/ems_backend
This commit is contained in:
237
lib/core/redis/redis.go
Normal file
237
lib/core/redis/redis.go
Normal file
@@ -0,0 +1,237 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ems.agt/lib/core/conf"
|
||||
"ems.agt/lib/log"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// Redis连接实例
|
||||
var rdb *redis.Client
|
||||
|
||||
// 声明定义限流脚本命令
|
||||
var rateLimitCommand = redis.NewScript(`
|
||||
local key = KEYS[1]
|
||||
local time = tonumber(ARGV[1])
|
||||
local count = tonumber(ARGV[2])
|
||||
local current = redis.call('get', key);
|
||||
if current and tonumber(current) >= count then
|
||||
return tonumber(current);
|
||||
end
|
||||
current = redis.call('incr', key)
|
||||
if tonumber(current) == 1 then
|
||||
redis.call('expire', key, time)
|
||||
end
|
||||
return tonumber(current);`)
|
||||
|
||||
// 连接Redis实例
|
||||
func Connect() {
|
||||
ctx := context.Background()
|
||||
client := conf.Get("redis").(map[string]any)
|
||||
address := fmt.Sprintf("%s:%d", client["host"], client["port"])
|
||||
// 创建连接
|
||||
rdb = redis.NewClient(&redis.Options{
|
||||
Addr: address,
|
||||
Password: client["password"].(string),
|
||||
DB: client["db"].(int),
|
||||
})
|
||||
// 测试数据库连接
|
||||
pong, err := rdb.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
log.Fatalf("failed error ping redis: %v", err)
|
||||
}
|
||||
log.Infof("redis %s connection is successful.", pong)
|
||||
}
|
||||
|
||||
// 关闭Redis实例
|
||||
func Close() {
|
||||
if err := rdb.Close(); err != nil {
|
||||
log.Fatalf("fatal error db close: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Info 获取redis服务信息
|
||||
func Info() map[string]map[string]string {
|
||||
ctx := context.Background()
|
||||
info, err := rdb.Info(ctx).Result()
|
||||
if err != nil {
|
||||
return map[string]map[string]string{}
|
||||
}
|
||||
infoObj := make(map[string]map[string]string)
|
||||
lines := strings.Split(info, "\r\n")
|
||||
label := ""
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "#") {
|
||||
label = strings.Fields(line)[len(strings.Fields(line))-1]
|
||||
label = strings.ToLower(label)
|
||||
infoObj[label] = make(map[string]string)
|
||||
continue
|
||||
}
|
||||
kvArr := strings.Split(line, ":")
|
||||
if len(kvArr) >= 2 {
|
||||
key := strings.TrimSpace(kvArr[0])
|
||||
value := strings.TrimSpace(kvArr[len(kvArr)-1])
|
||||
infoObj[label][key] = value
|
||||
}
|
||||
}
|
||||
return infoObj
|
||||
}
|
||||
|
||||
// KeySize 获取redis当前连接可用键Key总数信息
|
||||
func KeySize() int64 {
|
||||
ctx := context.Background()
|
||||
size, err := rdb.DBSize(ctx).Result()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
// CommandStats 获取redis命令状态信息
|
||||
func CommandStats() []map[string]string {
|
||||
ctx := context.Background()
|
||||
commandstats, err := rdb.Info(ctx, "commandstats").Result()
|
||||
if err != nil {
|
||||
return []map[string]string{}
|
||||
}
|
||||
statsObjArr := make([]map[string]string, 0)
|
||||
lines := strings.Split(commandstats, "\r\n")
|
||||
for _, line := range lines {
|
||||
if !strings.HasPrefix(line, "cmdstat_") {
|
||||
continue
|
||||
}
|
||||
kvArr := strings.Split(line, ":")
|
||||
key := kvArr[0]
|
||||
valueStr := kvArr[len(kvArr)-1]
|
||||
statsObj := make(map[string]string)
|
||||
statsObj["name"] = key[8:]
|
||||
statsObj["value"] = valueStr[6:strings.Index(valueStr, ",usec=")]
|
||||
statsObjArr = append(statsObjArr, statsObj)
|
||||
}
|
||||
return statsObjArr
|
||||
}
|
||||
|
||||
// 获取键的剩余有效时间(秒)
|
||||
func GetExpire(key string) float64 {
|
||||
ctx := context.Background()
|
||||
ttl, err := rdb.TTL(ctx, key).Result()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return ttl.Seconds()
|
||||
}
|
||||
|
||||
// 获得缓存数据的key列表
|
||||
func GetKeys(pattern string) []string {
|
||||
// 初始化变量
|
||||
var keys []string
|
||||
var cursor uint64 = 0
|
||||
ctx := context.Background()
|
||||
// 循环遍历获取匹配的键
|
||||
for {
|
||||
// 使用 SCAN 命令获取匹配的键
|
||||
batchKeys, nextCursor, err := rdb.Scan(ctx, cursor, pattern, 100).Result()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to scan keys: %v", err)
|
||||
break
|
||||
}
|
||||
cursor = nextCursor
|
||||
keys = append(keys, batchKeys...)
|
||||
// 当 cursor 为 0,表示遍历完成
|
||||
if cursor == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// 批量获得缓存数据
|
||||
func GetBatch(keys []string) []any {
|
||||
if len(keys) == 0 {
|
||||
return []any{}
|
||||
}
|
||||
// 获取缓存数据
|
||||
result, err := rdb.MGet(context.Background(), keys...).Result()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get batch data: %v", err)
|
||||
return []any{}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 获得缓存数据
|
||||
func Get(key string) string {
|
||||
ctx := context.Background()
|
||||
value, err := rdb.Get(ctx, key).Result()
|
||||
if err == redis.Nil || err != nil {
|
||||
return ""
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// 获得缓存数据Hash
|
||||
func GetHash(key string) map[string]string {
|
||||
ctx := context.Background()
|
||||
value, err := rdb.HGetAll(ctx, key).Result()
|
||||
if err == redis.Nil || err != nil {
|
||||
return map[string]string{}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// 判断是否存在
|
||||
func Has(keys ...string) bool {
|
||||
ctx := context.Background()
|
||||
exists, err := rdb.Exists(ctx, keys...).Result()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return exists >= 1
|
||||
}
|
||||
|
||||
// 设置缓存数据
|
||||
func Set(key string, value any) bool {
|
||||
ctx := context.Background()
|
||||
err := rdb.Set(ctx, key, value, 0).Err()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 设置缓存数据与过期时间
|
||||
func SetByExpire(key string, value any, expiration time.Duration) bool {
|
||||
ctx := context.Background()
|
||||
err := rdb.Set(ctx, key, value, expiration).Err()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 删除单个
|
||||
func Del(key string) bool {
|
||||
ctx := context.Background()
|
||||
err := rdb.Del(ctx, key).Err()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 删除多个
|
||||
func DelKeys(keys []string) bool {
|
||||
if len(keys) == 0 {
|
||||
return false
|
||||
}
|
||||
ctx := context.Background()
|
||||
err := rdb.Del(ctx, keys...).Err()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 限流查询并记录
|
||||
func RateLimit(limitKey string, time, count int64) int64 {
|
||||
ctx := context.Background()
|
||||
result, err := rateLimitCommand.Run(ctx, rdb, []string{limitKey}, time, count).Result()
|
||||
if err != nil {
|
||||
log.Errorf("redis lua script err %v", err)
|
||||
return 0
|
||||
}
|
||||
return result.(int64)
|
||||
}
|
||||
@@ -47,16 +47,6 @@ func ShouldBindJSON(r *http.Request, args any) error {
|
||||
|
||||
// JSON 相应json数据
|
||||
func JSON(w http.ResponseWriter, code int, data any) {
|
||||
// 跨域响应头
|
||||
// To solve cross domain issue
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
// w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
||||
// w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
// w.Header().Set("Access-Control-Allow-Headers", "AccessToken")
|
||||
w.Header().Set("Access-Control-Expose-Headers", "Access-Control-Allow-Headers, Token")
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||
|
||||
response, err := json.Marshal(data)
|
||||
|
||||
@@ -181,17 +181,17 @@ func InsertDataWithJson(insertData interface{}) (int64, error) {
|
||||
|
||||
type NeInfo struct {
|
||||
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeId string `json:"neId" xorm:"ne_id"` // neUID/rmUID 网元唯一标识
|
||||
RmUID string `json:"rmUID" xorm:"rm_uid"` // neUID/rmUID网元UID
|
||||
NeName string `json:"neName" xorm:"ne_name"` // NeName/UserLabel 网元名称/网元设备友好名称
|
||||
NeType string `json:"ne_type" xorm:"ne_type"`
|
||||
NeId string `json:"ne_id" xorm:"ne_id"` // neUID/rmUID 网元唯一标识
|
||||
RmUID string `json:"rm_uid" xorm:"rm_uid"` // neUID/rmUID网元UID
|
||||
NeName string `json:"ne_name" xorm:"ne_name"` // NeName/UserLabel 网元名称/网元设备友好名称
|
||||
Ip string `json:"ip" xorm:"ip"`
|
||||
Port string `json:"port" xorm:"port"`
|
||||
PvFlag string `json:"pvFlag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理
|
||||
NeAddress string `json:"neAddress" xorm:"ne_address"` // 只对PNF
|
||||
Province string `json:"province" xorm:"province"` // 网元所在省份
|
||||
VendorName string `json:"vendorName" xorm:"vendor_name"` // 厂商名称
|
||||
Dn string `json:"dn" xorm:"dn"` // 网络标识
|
||||
PvFlag string `json:"pv_flag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理
|
||||
NeAddress string `json:"ne_address" xorm:"ne_address"` // 只对PNF
|
||||
Province string `json:"province" xorm:"province"` // 网元所在省份
|
||||
VendorName string `json:"vendor_name" xorm:"vendor_name"` // 厂商名称
|
||||
Dn string `json:"dn" xorm:"dn"` // 网络标识
|
||||
Status int `json:"status" xorm:"status"`
|
||||
UpdateTime string `json:"-" xorm:"-"`
|
||||
}
|
||||
|
||||
64
lib/midware/cors.go
Normal file
64
lib/midware/cors.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Cors 跨域
|
||||
func Cors(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 设置Vary头部
|
||||
w.Header().Set("Vary", "Origin")
|
||||
w.Header().Set("Keep-Alive", "timeout=5")
|
||||
|
||||
requestOrigin := r.Header.Get("Origin")
|
||||
if requestOrigin == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
// OPTIONS
|
||||
if r.Method == "OPTIONS" {
|
||||
requestMethod := r.Header.Get("Access-Control-Request-Method")
|
||||
if requestMethod == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 响应最大时间值
|
||||
w.Header().Set("Access-Control-Max-Age", "31536000")
|
||||
|
||||
// 允许方法
|
||||
allowMethods := []string{
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"PATCH",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Methods", strings.Join(allowMethods, ","))
|
||||
|
||||
// 允许请求头
|
||||
allowHeaders := []string{
|
||||
"Accesstoken",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Headers", strings.Join(allowHeaders, ","))
|
||||
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
|
||||
// 暴露请求头
|
||||
exposeHeaders := []string{"X-RepeatSubmit-Rest", "AccessToken"}
|
||||
w.Header().Set("Access-Control-Expose-Headers", strings.Join(exposeHeaders, ","))
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -37,6 +37,7 @@ func LoggerTrace(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
// 已禁用
|
||||
func OptionProcess(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "OPTIONS" {
|
||||
@@ -48,6 +49,7 @@ func OptionProcess(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
// 已禁用
|
||||
func CheckPermission(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
token := r.Header.Get("AccessToken")
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
sysrole "ems.agt/features/sys_role"
|
||||
sysuser "ems.agt/features/sys_user"
|
||||
"ems.agt/features/trace"
|
||||
udmuser "ems.agt/features/udm_user"
|
||||
"ems.agt/lib/midware"
|
||||
"ems.agt/lib/services"
|
||||
|
||||
@@ -327,6 +328,11 @@ func init() {
|
||||
for _, v := range sysuser.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
|
||||
// UDM 用户信息接口添加到路由
|
||||
for _, v := range udmuser.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
}
|
||||
|
||||
// To resolv rest POST/PUT/DELETE/PATCH cross domain
|
||||
@@ -342,7 +348,8 @@ func NewRouter() *mux.Router {
|
||||
r.MethodNotAllowedHandler = services.CustomResponseMethodNotAllowed405Handler()
|
||||
|
||||
r.Use(midware.LoggerTrace)
|
||||
r.Use(midware.OptionProcess)
|
||||
r.Use(midware.Cors)
|
||||
// r.Use(midware.OptionProcess)
|
||||
// r.Use(midware.ArrowIPAddr)
|
||||
|
||||
for _, router := range routers {
|
||||
|
||||
Reference in New Issue
Block a user