add: 提交
This commit is contained in:
64
lib/aes/aes.go
Normal file
64
lib/aes/aes.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package aes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
func AesEncrypt(orig string, key string) string {
|
||||
// 转成字节数组
|
||||
origData := []byte(orig)
|
||||
k := []byte(key)
|
||||
|
||||
// 分组秘钥
|
||||
block, _ := aes.NewCipher(k)
|
||||
// 获取秘钥块的长度
|
||||
blockSize := block.BlockSize()
|
||||
// 补全码
|
||||
origData = PKCS7Padding(origData, blockSize)
|
||||
// 加密模式
|
||||
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
|
||||
// 创建数组
|
||||
cryted := make([]byte, len(origData))
|
||||
// 加密
|
||||
blockMode.CryptBlocks(cryted, origData)
|
||||
|
||||
return base64.StdEncoding.EncodeToString(cryted)
|
||||
|
||||
}
|
||||
|
||||
func AesDecrypt(cryted string, key string) string {
|
||||
// 转成字节数组
|
||||
crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
|
||||
k := []byte(key)
|
||||
|
||||
// 分组秘钥
|
||||
block, _ := aes.NewCipher(k)
|
||||
// 获取秘钥块的长度
|
||||
blockSize := block.BlockSize()
|
||||
// 加密模式
|
||||
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
|
||||
// 创建数组
|
||||
orig := make([]byte, len(crytedByte))
|
||||
// 解密
|
||||
blockMode.CryptBlocks(orig, crytedByte)
|
||||
// 去补全码
|
||||
orig = PKCS7UnPadding(orig)
|
||||
return string(orig)
|
||||
}
|
||||
|
||||
// 补码
|
||||
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
|
||||
padding := blocksize - len(ciphertext)%blocksize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
// 去码
|
||||
func PKCS7UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
92
lib/cache/badger_db/badger_db.go
vendored
Normal file
92
lib/cache/badger_db/badger_db.go
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package badger_db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
db *badger.DB
|
||||
}
|
||||
|
||||
func NewCacheDB(db *badger.DB) *Cache {
|
||||
return &Cache{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) SetNX(key string, value interface{}) error {
|
||||
err := c.db.Update(func(txn *badger.Txn) error {
|
||||
_, err := txn.Get([]byte(key))
|
||||
if errors.Is(err, badger.ErrKeyNotFound) {
|
||||
v := []byte(fmt.Sprintf("%v", value))
|
||||
return txn.Set([]byte(key), v)
|
||||
}
|
||||
return err
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Cache) Set(key string, value interface{}) error {
|
||||
err := c.db.Update(func(txn *badger.Txn) error {
|
||||
v := []byte(fmt.Sprintf("%v", value))
|
||||
return txn.Set([]byte(key), v)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Cache) Del(key string) error {
|
||||
err := c.db.Update(func(txn *badger.Txn) error {
|
||||
return txn.Delete([]byte(key))
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Cache) Clean() error {
|
||||
return c.db.DropAll()
|
||||
}
|
||||
|
||||
func (c *Cache) Get(key string) ([]byte, error) {
|
||||
var result []byte
|
||||
err := c.db.View(func(txn *badger.Txn) error {
|
||||
item, err := txn.Get([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = item.Value(func(val []byte) error {
|
||||
result = append([]byte{}, val...)
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *Cache) SetWithTTL(key string, value interface{}, duration time.Duration) error {
|
||||
err := c.db.Update(func(txn *badger.Txn) error {
|
||||
v := []byte(fmt.Sprintf("%v", value))
|
||||
e := badger.NewEntry([]byte(key), v).WithTTL(duration)
|
||||
return txn.SetEntry(e)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Cache) PrefixScanKey(prefixStr string) ([]string, error) {
|
||||
var res []string
|
||||
err := c.db.View(func(txn *badger.Txn) error {
|
||||
it := txn.NewIterator(badger.DefaultIteratorOptions)
|
||||
defer it.Close()
|
||||
prefix := []byte(prefixStr)
|
||||
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
|
||||
item := it.Item()
|
||||
k := item.Key()
|
||||
res = append(res, string(k))
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return res, err
|
||||
}
|
||||
55
lib/cache/cache.go
vendored
Normal file
55
lib/cache/cache.go
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"ems.agt/lib/cache/badger_db"
|
||||
"ems.agt/lib/log"
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
|
||||
var CACHE *badger_db.Cache
|
||||
|
||||
func Init() {
|
||||
options := badger.Options{
|
||||
Dir: "tmp/badger",
|
||||
ValueDir: "tmp/badger",
|
||||
ValueLogFileSize: 64 << 20,
|
||||
ValueLogMaxEntries: 10 << 20,
|
||||
VLogPercentile: 0.1,
|
||||
|
||||
MemTableSize: 32 << 20,
|
||||
BaseTableSize: 2 << 20,
|
||||
BaseLevelSize: 10 << 20,
|
||||
TableSizeMultiplier: 2,
|
||||
LevelSizeMultiplier: 10,
|
||||
MaxLevels: 7,
|
||||
NumGoroutines: 4,
|
||||
MetricsEnabled: true,
|
||||
NumCompactors: 2,
|
||||
NumLevelZeroTables: 5,
|
||||
NumLevelZeroTablesStall: 15,
|
||||
NumMemtables: 1,
|
||||
BloomFalsePositive: 0.01,
|
||||
BlockSize: 2 * 1024,
|
||||
SyncWrites: false,
|
||||
NumVersionsToKeep: 1,
|
||||
CompactL0OnClose: false,
|
||||
VerifyValueChecksum: false,
|
||||
BlockCacheSize: 32 << 20,
|
||||
IndexCacheSize: 0,
|
||||
ZSTDCompressionLevel: 1,
|
||||
EncryptionKey: []byte{},
|
||||
EncryptionKeyRotationDuration: 10 * 24 * time.Hour, // Default 10 days.
|
||||
DetectConflicts: true,
|
||||
NamespaceOffset: -1,
|
||||
}
|
||||
|
||||
cache, err := badger.Open(options)
|
||||
if err != nil {
|
||||
log.Errorf("failed to badger init cache:", err)
|
||||
}
|
||||
|
||||
CACHE = badger_db.NewCacheDB(cache)
|
||||
log.Info("init cache successfully")
|
||||
}
|
||||
1412
lib/dborm/dborm.go
Normal file
1412
lib/dborm/dborm.go
Normal file
File diff suppressed because it is too large
Load Diff
120
lib/file/file.go
Normal file
120
lib/file/file.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"ems.agt/lib/dborm"
|
||||
"ems.agt/lib/global"
|
||||
"ems.agt/lib/log"
|
||||
"ems.agt/lib/services"
|
||||
"ems.agt/restagent/config"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const (
|
||||
//经过测试,linux下,延时需要大于100ms
|
||||
TIME_DELAY_AFTER_WRITE = 200
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Data []string `json:"data"`
|
||||
}
|
||||
|
||||
type MMLRequest struct {
|
||||
MML []string `json:"mml"`
|
||||
}
|
||||
|
||||
func GetFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostMMLToNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
params := r.URL.Query()
|
||||
neId := params["ne_id"]
|
||||
log.Debug("neType:", neType, "neId", neId)
|
||||
|
||||
neInfo := new(dborm.NeInfo)
|
||||
var err error
|
||||
if len(neId) == 0 {
|
||||
log.Error("ne_id NOT FOUND")
|
||||
services.ResponseBadRequest400WrongParamValue(w)
|
||||
return
|
||||
}
|
||||
neInfo, err = dborm.XormGetNeInfo(neType, neId[0])
|
||||
if err != nil {
|
||||
log.Error("dborm.XormGetNeInfo is failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
|
||||
var buf [8192]byte
|
||||
var n int
|
||||
var mmlResult []string
|
||||
|
||||
if neInfo != nil {
|
||||
hostMML := fmt.Sprintf("%s:%d", neInfo.Ip, config.GetYamlConfig().MML.Port)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err)
|
||||
log.Error(errMsg)
|
||||
mmlResult = append(mmlResult, errMsg)
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
|
||||
loginStr := fmt.Sprintf("%s\n%s\n", config.GetYamlConfig().MML.User, config.GetYamlConfig().MML.Password)
|
||||
n, err = conn.Write([]byte(loginStr))
|
||||
if err != nil {
|
||||
log.Errorf("Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Errorf("Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
log.Debug(string(buf[0:n]))
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
log.Debug("Body:", string(body))
|
||||
|
||||
mmlRequest := new(MMLRequest)
|
||||
_ = json.Unmarshal(body, mmlRequest)
|
||||
|
||||
for _, mml := range mmlRequest.MML {
|
||||
mmlCommand := fmt.Sprintf("%s\n", mml)
|
||||
log.Debug("mml command:", mmlCommand)
|
||||
n, err = conn.Write([]byte(mmlCommand))
|
||||
if err != nil {
|
||||
log.Errorf("Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * TIME_DELAY_AFTER_WRITE)
|
||||
|
||||
n, err = conn.Read(buf[0:])
|
||||
if err != nil {
|
||||
log.Errorf("Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
log.Debug(string(buf[0 : n-len(neType)-2]))
|
||||
mmlResult = append(mmlResult, string(buf[0:n-len(neType)-2]))
|
||||
}
|
||||
}
|
||||
|
||||
response := Response{mmlResult}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
58
lib/global/global.go
Normal file
58
lib/global/global.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package global
|
||||
|
||||
import "errors"
|
||||
|
||||
// 跨package引用的首字母大写
|
||||
const (
|
||||
RequestBodyMaxLen = 2000000
|
||||
ApiVersionV1 = "v1"
|
||||
ApiVersionV2 = "v2"
|
||||
LineBreak = "\n"
|
||||
)
|
||||
|
||||
const (
|
||||
DateTime = "2006-01-02 15:04:05"
|
||||
DateData = "20060102150405"
|
||||
DateHour = "2006010215"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxInt32Number = 2147483647
|
||||
)
|
||||
|
||||
const (
|
||||
MaxLimitData = 1000
|
||||
)
|
||||
|
||||
var (
|
||||
Version string
|
||||
BuildTime string
|
||||
GoVer string
|
||||
)
|
||||
|
||||
var (
|
||||
ErrParamsNotAdapted = errors.New("the number of params is not adapted")
|
||||
|
||||
// PM module error message
|
||||
ErrPMNotFoundData = errors.New("not found PM data")
|
||||
|
||||
// CM module error message
|
||||
ErrCMNotFoundTargetNE = errors.New("not found target NE")
|
||||
ErrCMCannotDeleteActiveNE = errors.New("can not delete an active NE")
|
||||
ErrCMInvalidBackupFile = errors.New("invalid backup file")
|
||||
ErrCMNotMatchMD5File = errors.New("md5 not match between file and url")
|
||||
ErrCMNotMatchSignFile = errors.New("digests signatures not match in the file")
|
||||
ErrCMExistSoftwareFile = errors.New("exist the same software package file")
|
||||
ErrCMNotFoundTargetSoftware = errors.New("not found the target software package")
|
||||
ErrCMNotFoundTargetNeVersion = errors.New("not found the target NE version")
|
||||
ErrCMNotFoundRollbackNeVersion = errors.New("not found the rollback NE version")
|
||||
|
||||
ErrCMNotFoundTargetBackupFile = errors.New("not found the target NE backup")
|
||||
|
||||
// TRACE module error message
|
||||
ErrTraceFailedDistributeToNEs = errors.New("failed to distribute trace task to target NEs")
|
||||
ErrTraceNotCarriedTaskID = errors.New("not carried task id in request url")
|
||||
|
||||
// MML module error define
|
||||
ErrMmlInvalidCommandFormat = errors.New("invalid mml command format")
|
||||
)
|
||||
479
lib/global/kits.go
Normal file
479
lib/global/kits.go
Normal file
@@ -0,0 +1,479 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
IsIPv4 = "IPv4"
|
||||
IsIPv6 = "IPv6"
|
||||
NonIP = "NonIp"
|
||||
)
|
||||
|
||||
type em struct{}
|
||||
|
||||
func GetPkgName() string {
|
||||
return reflect.TypeOf(em{}).PkgPath()
|
||||
}
|
||||
|
||||
// interface{} change to map[string]interface{}
|
||||
// interface{} data is []interface{}
|
||||
func ListToMap(list interface{}, key string) map[string]interface{} {
|
||||
res := make(map[string]interface{})
|
||||
arr := ToSlice(list)
|
||||
for _, row := range arr {
|
||||
immutable := reflect.ValueOf(row)
|
||||
val := immutable.FieldByName(key).String()
|
||||
res[val] = row
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// interface{} change to []interface{}
|
||||
func ToSlice(arr interface{}) []interface{} {
|
||||
ret := make([]interface{}, 0)
|
||||
v := reflect.ValueOf(arr)
|
||||
if v.Kind() != reflect.Slice {
|
||||
ret = append(ret, arr)
|
||||
return ret
|
||||
}
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
ret = append(ret, v.Index(i).Interface())
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var TodoList []Todo
|
||||
|
||||
type Todo struct {
|
||||
Id int64
|
||||
Item string
|
||||
}
|
||||
|
||||
// JSON序列化方式
|
||||
func jsonStructToMap(TodoList Todo) (map[string]interface{}, error) {
|
||||
// 结构体转json
|
||||
strRet, err := json.Marshal(TodoList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// json转map
|
||||
var mRet map[string]interface{}
|
||||
err1 := json.Unmarshal(strRet, &mRet)
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
return mRet, nil
|
||||
}
|
||||
|
||||
func IsContain(item string, items []string) bool {
|
||||
for _, e := range items {
|
||||
if e == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsContainP(item string, items *[]string, size int) bool {
|
||||
for i := 0; i < size; i++ {
|
||||
if (*items)[i] == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 将字符串 分割成 字符串数组
|
||||
// @s:分割符
|
||||
func SplitString(str string, s string) []string {
|
||||
sa := strings.Split(str, s)
|
||||
return sa
|
||||
}
|
||||
|
||||
// 合并字符串数组
|
||||
func MergeStringArr(a, b []string) []string {
|
||||
var arr []string
|
||||
for _, i := range a {
|
||||
arr = append(arr, i)
|
||||
}
|
||||
for _, j := range b {
|
||||
arr = append(arr, j)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
func UniqueStringArr(m []string) []string {
|
||||
d := make([]string, 0)
|
||||
tempMap := make(map[string]bool, len(m))
|
||||
for _, v := range m { // 以值作为键名
|
||||
if tempMap[v] == false {
|
||||
tempMap[v] = true
|
||||
d = append(d, v)
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// 合并整型数组
|
||||
func MergeArr(a, b []int) []int {
|
||||
var arr []int
|
||||
for _, i := range a {
|
||||
arr = append(arr, i)
|
||||
}
|
||||
for _, j := range b {
|
||||
arr = append(arr, j)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
func UniqueArr(m []int) []int {
|
||||
d := make([]int, 0)
|
||||
tempMap := make(map[int]bool, len(m))
|
||||
for _, v := range m { // 以值作为键名
|
||||
if tempMap[v] == false {
|
||||
tempMap[v] = true
|
||||
d = append(d, v)
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// 升序
|
||||
func AscArr(e []int) []int {
|
||||
sort.Ints(e[:])
|
||||
return e
|
||||
}
|
||||
|
||||
// 降序
|
||||
func DescArr(e []int) []int {
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(e)))
|
||||
return e
|
||||
}
|
||||
|
||||
func MatchRmUID(p string, s string) bool {
|
||||
match, _ := regexp.MatchString(p, s)
|
||||
return match
|
||||
}
|
||||
|
||||
type OrderedMap struct {
|
||||
Order []string
|
||||
Map map[string]interface{}
|
||||
}
|
||||
|
||||
func (om *OrderedMap) UnmarshalJson(b []byte) error {
|
||||
json.Unmarshal(b, &om.Map)
|
||||
|
||||
index := make(map[string]int)
|
||||
for key := range om.Map {
|
||||
om.Order = append(om.Order, key)
|
||||
esc, _ := json.Marshal(key) //Escape the key
|
||||
index[key] = bytes.Index(b, esc)
|
||||
}
|
||||
|
||||
sort.Slice(om.Order, func(i, j int) bool { return index[om.Order[i]] < index[om.Order[j]] })
|
||||
return nil
|
||||
}
|
||||
|
||||
func (om OrderedMap) MarshalJson() ([]byte, error) {
|
||||
var b []byte
|
||||
buf := bytes.NewBuffer(b)
|
||||
buf.WriteRune('{')
|
||||
l := len(om.Order)
|
||||
for i, key := range om.Order {
|
||||
km, err := json.Marshal(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(km)
|
||||
buf.WriteRune(':')
|
||||
vm, err := json.Marshal(om.Map[key])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.Write(vm)
|
||||
if i != l-1 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
fmt.Println(buf.String())
|
||||
}
|
||||
buf.WriteRune('}')
|
||||
fmt.Println(buf.String())
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func GetBodyCopy(r *http.Request) (*bytes.Buffer, error) {
|
||||
// If r.bodyBuf present, return the copy
|
||||
// if r.bodyBuf != nil {
|
||||
// return bytes.NewBuffer(r.bodyBuf.Bytes()), nil
|
||||
// }
|
||||
|
||||
// Maybe body is `io.Reader`.
|
||||
// Note: Resty user have to watchout for large body size of `io.Reader`
|
||||
if r.Body != nil {
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Restore the Body
|
||||
// close(r.Body)
|
||||
r.Body = io.NopCloser(bytes.NewReader(b))
|
||||
|
||||
// Return the Body bytes
|
||||
return bytes.NewBuffer(b), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func UnmarshalBody(r *http.Request, v *interface{}, maxLen int64) error {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, maxLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(body, v)
|
||||
}
|
||||
|
||||
func SetNotifyUrl(ip string, port uint16, uri string) string {
|
||||
return fmt.Sprintf("http://%s:%d%s", ip, port, uri)
|
||||
}
|
||||
|
||||
func GetIps() (ips []string, err error) {
|
||||
interfaceAddr, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return ips, err
|
||||
}
|
||||
|
||||
for _, address := range interfaceAddr {
|
||||
ipNet, isVailIpNet := address.(*net.IPNet)
|
||||
// 检查ip地址判断是否回环地址
|
||||
if isVailIpNet && !ipNet.IP.IsLoopback() {
|
||||
if ipNet.IP.To4() != nil {
|
||||
ips = append(ips, ipNet.IP.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func GetCurrentTimeSliceIndexByPeriod(t time.Time, period int) int {
|
||||
index := int((t.Hour()*60+t.Minute())/period) - 1
|
||||
if index < 0 {
|
||||
return int(24*60/period) - 1
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
var (
|
||||
cst *time.Location
|
||||
)
|
||||
|
||||
// RFC3339ToDateTime convert rfc3339 value to china standard time layout
|
||||
func RFC3339ToDateTime(value string) (string, error) {
|
||||
ts, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ts.In(cst).Format("2006-01-02 15:04:05"), nil
|
||||
}
|
||||
|
||||
// CreateTimeDir 根据当前时间格式来创建文件夹
|
||||
func CreateTimeDir(fmt string, path string) string {
|
||||
folderName := time.Now().Format(fmt)
|
||||
folderPath := filepath.Join(path, folderName)
|
||||
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
|
||||
// 必须分成两步:先创建文件夹、再修改权限
|
||||
os.Mkdir(folderPath, 0664) //0644也可以os.ModePerm
|
||||
os.Chmod(folderPath, 0664)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
// CreateDir 根据传入的目录名和路径来创建文件夹
|
||||
func CreateDir(folderName string, path string) string {
|
||||
folderPath := filepath.Join(path, folderName)
|
||||
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
|
||||
// 必须分成两步:先创建文件夹、再修改权限
|
||||
os.Mkdir(folderPath, 0664) //0644也可以os.ModePerm
|
||||
os.Chmod(folderPath, 0664)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
func GetFmtTimeString(srcFmt string, timeString string, dstFmt string) string {
|
||||
t, _ := time.ParseInLocation(srcFmt, timeString, time.Local)
|
||||
return t.Format(dstFmt)
|
||||
}
|
||||
|
||||
func GetFileMD5Sum(filePath string) (string, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
md5 := md5.New()
|
||||
_, err = io.Copy(md5, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
md5str := hex.EncodeToString(md5.Sum(nil))
|
||||
|
||||
return md5str, nil
|
||||
}
|
||||
|
||||
// PathExists check path is exist or no
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil { //文件或者目录存在
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func GetDayDuration(d1, d2 string) int64 {
|
||||
a, _ := time.Parse("2006-01-02", d1)
|
||||
b, _ := time.Parse("2006-01-02", d2)
|
||||
d := a.Sub(b)
|
||||
|
||||
return (int64)(d.Hours() / 24)
|
||||
}
|
||||
|
||||
func GetSecondsSinceDatetime(datetimeStr string) (int64, error) {
|
||||
loc1, _ := time.LoadLocation("Local")
|
||||
// 解析日期时间字符串为时间对象
|
||||
datetime, err := time.ParseInLocation(time.DateTime, datetimeStr, loc1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 计算时间差
|
||||
duration := time.Since(datetime)
|
||||
|
||||
// 获取时间差的秒数
|
||||
seconds := int64(duration.Seconds())
|
||||
|
||||
return seconds, nil
|
||||
}
|
||||
|
||||
// 0: invalid ip
|
||||
// 4: IPv4
|
||||
// 6: IPv6
|
||||
func ParseIP(s string) (net.IP, int) {
|
||||
ip := net.ParseIP(s)
|
||||
if ip == nil {
|
||||
return nil, 0
|
||||
}
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '.':
|
||||
return ip, 4
|
||||
case ':':
|
||||
return ip, 6
|
||||
}
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
func BytesCombine1(pBytes ...[]byte) []byte {
|
||||
return bytes.Join(pBytes, []byte(""))
|
||||
}
|
||||
|
||||
func BytesCombine(pBytes ...[]byte) []byte {
|
||||
length := len(pBytes)
|
||||
s := make([][]byte, length)
|
||||
for index := 0; index < length; index++ {
|
||||
s[index] = pBytes[index]
|
||||
}
|
||||
sep := []byte("")
|
||||
return bytes.Join(s, sep)
|
||||
}
|
||||
|
||||
func ParseIPAddr(ip string) string {
|
||||
ipAddr := net.ParseIP(ip)
|
||||
|
||||
if ipAddr != nil {
|
||||
if ipAddr.To4() != nil {
|
||||
return IsIPv4
|
||||
} else {
|
||||
return IsIPv6
|
||||
}
|
||||
}
|
||||
|
||||
return NonIP
|
||||
}
|
||||
|
||||
func CombineHostUri(ip string, port string) string {
|
||||
var hostUri string = ""
|
||||
ipType := ParseIPAddr(ip)
|
||||
if ipType == IsIPv4 {
|
||||
hostUri = fmt.Sprintf("http://%s:%v", ip, port)
|
||||
} else {
|
||||
hostUri = fmt.Sprintf("http://[%s]:%v", ip, port)
|
||||
}
|
||||
|
||||
return hostUri
|
||||
}
|
||||
|
||||
func StructToMap(obj interface{}) map[string]interface{} {
|
||||
objValue := reflect.ValueOf(obj)
|
||||
objType := objValue.Type()
|
||||
|
||||
m := make(map[string]interface{})
|
||||
|
||||
for i := 0; i < objValue.NumField(); i++ {
|
||||
field := objValue.Field(i)
|
||||
fieldName := objType.Field(i).Name
|
||||
|
||||
m[fieldName] = field.Interface()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// ToMap 结构体转为Map[string]interface{}
|
||||
func ToMap(in interface{}, tagName string) (map[string]interface{}, error) {
|
||||
out := make(map[string]interface{})
|
||||
|
||||
v := reflect.ValueOf(in)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct { // 非结构体返回错误提示
|
||||
return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v)
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
// 遍历结构体字段
|
||||
// 指定tagName值为map中key;字段值为map中value
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fi := t.Field(i)
|
||||
if tagValue := fi.Tag.Get(tagName); tagValue != "" {
|
||||
out[tagValue] = v.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
337
lib/log/logger.go
Normal file
337
lib/log/logger.go
Normal file
@@ -0,0 +1,337 @@
|
||||
// logger for omc/ems
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
// LogLevel defines a log level
|
||||
type LogLevel int
|
||||
|
||||
// enum all LogLevels
|
||||
const (
|
||||
// following level also match syslog.Priority value
|
||||
LOG_TRACE LogLevel = iota
|
||||
LOG_DEBUG
|
||||
LOG_INFO
|
||||
LOG_WARN
|
||||
LOG_ERROR
|
||||
LOG_FATAL
|
||||
LOG_OFF
|
||||
LOG_NODEF
|
||||
)
|
||||
|
||||
// default log options
|
||||
const (
|
||||
DEFAULT_LOG_PREFIX = "omc"
|
||||
DEFAULT_LOG_FLAG = log.Lshortfile | log.Ldate | log.Lmicroseconds
|
||||
DEFAULT_LOG_LEVEL = LOG_DEBUG
|
||||
DEFAULT_CALL_DEPTH = 3
|
||||
)
|
||||
|
||||
// Logger is a logger interface
|
||||
type Logger interface {
|
||||
Fatal(v ...interface{})
|
||||
Fatalf(format string, v ...interface{})
|
||||
Error(v ...interface{})
|
||||
Errorf(format string, v ...interface{})
|
||||
Warn(v ...interface{})
|
||||
Warnf(format string, v ...interface{})
|
||||
Info(v ...interface{})
|
||||
Infof(format string, v ...interface{})
|
||||
Debug(v ...interface{})
|
||||
Debugf(format string, v ...interface{})
|
||||
Trace(v ...interface{})
|
||||
Tracef(format string, v ...interface{})
|
||||
|
||||
Level() LogLevel
|
||||
LevelString() string
|
||||
SetLevel(l LogLevel)
|
||||
}
|
||||
|
||||
var _ Logger = DiscardLogger{}
|
||||
|
||||
// DiscardLogger don't log implementation for ILogger
|
||||
type DiscardLogger struct{}
|
||||
|
||||
// Trace empty implementation
|
||||
func (DiscardLogger) Trace(v ...interface{}) {}
|
||||
|
||||
// Tracef empty implementation
|
||||
func (DiscardLogger) Tracef(format string, v ...interface{}) {}
|
||||
|
||||
// Debug empty implementation
|
||||
func (DiscardLogger) Debug(v ...interface{}) {}
|
||||
|
||||
// Debugf empty implementation
|
||||
func (DiscardLogger) Debugf(format string, v ...interface{}) {}
|
||||
|
||||
// Info empty implementation
|
||||
func (DiscardLogger) Info(v ...interface{}) {}
|
||||
|
||||
// Infof empty implementation
|
||||
func (DiscardLogger) Infof(format string, v ...interface{}) {}
|
||||
|
||||
// Warn empty implementation
|
||||
func (DiscardLogger) Warn(v ...interface{}) {}
|
||||
|
||||
// Warnf empty implementation
|
||||
func (DiscardLogger) Warnf(format string, v ...interface{}) {}
|
||||
|
||||
// Error empty implementation
|
||||
func (DiscardLogger) Error(v ...interface{}) {}
|
||||
|
||||
// Errorf empty implementation
|
||||
func (DiscardLogger) Errorf(format string, v ...interface{}) {}
|
||||
|
||||
// Fatal empty implementation
|
||||
func (DiscardLogger) Fatal(v ...interface{}) {}
|
||||
|
||||
// Fatalf empty implementation
|
||||
func (DiscardLogger) Fatalf(format string, v ...interface{}) {}
|
||||
|
||||
// Level empty implementation
|
||||
func (DiscardLogger) Level() LogLevel {
|
||||
return LOG_NODEF
|
||||
}
|
||||
|
||||
// Level empty implementation
|
||||
func (DiscardLogger) LevelString() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetLevel empty implementation
|
||||
func (DiscardLogger) SetLevel(l LogLevel) {}
|
||||
|
||||
// EmsLogger is the default implment of ILogger
|
||||
type EmsLogger struct {
|
||||
TRACE *log.Logger
|
||||
DEBUG *log.Logger
|
||||
INFO *log.Logger
|
||||
WARN *log.Logger
|
||||
ERROR *log.Logger
|
||||
FATAL *log.Logger
|
||||
level LogLevel
|
||||
levelString []string
|
||||
depth int
|
||||
}
|
||||
|
||||
var _ Logger = &EmsLogger{}
|
||||
|
||||
// NewEmsLogger use a special io.Writer as logger output
|
||||
func NewEmsLogger(out io.Writer) *EmsLogger {
|
||||
return NewEmsLogger2(out, DEFAULT_LOG_PREFIX, DEFAULT_LOG_FLAG)
|
||||
}
|
||||
|
||||
// NewEmsLogger2 let you customrize your logger prefix and flag
|
||||
func NewEmsLogger2(out io.Writer, prefix string, flag int) *EmsLogger {
|
||||
return NewEmsLogger3(out, prefix, flag, DEFAULT_LOG_LEVEL)
|
||||
}
|
||||
|
||||
// NewEmsLogger3 let you customrize your logger prefix and flag and logLevel
|
||||
func NewEmsLogger3(out io.Writer, prefix string, flag int, l LogLevel) *EmsLogger {
|
||||
return &EmsLogger{
|
||||
TRACE: log.New(out, fmt.Sprintf("[%s] [trace] ", prefix), flag),
|
||||
DEBUG: log.New(out, fmt.Sprintf("[%s] [debug] ", prefix), flag),
|
||||
INFO: log.New(out, fmt.Sprintf("[%s] [info ] ", prefix), flag),
|
||||
WARN: log.New(out, fmt.Sprintf("[%s] [warn ] ", prefix), flag),
|
||||
ERROR: log.New(out, fmt.Sprintf("[%s] [error] ", prefix), flag),
|
||||
FATAL: log.New(out, fmt.Sprintf("[%s] [fatal] ", prefix), flag),
|
||||
level: l,
|
||||
levelString: []string{"trace", "debug", "info", "warn", "error", "fatal"},
|
||||
depth: DEFAULT_CALL_DEPTH,
|
||||
}
|
||||
}
|
||||
|
||||
// Trace implement ILogger
|
||||
func (s *EmsLogger) Trace(v ...interface{}) {
|
||||
if s.level <= LOG_TRACE {
|
||||
_ = s.TRACE.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Tracef implement ILogger
|
||||
func (s *EmsLogger) Tracef(format string, v ...interface{}) {
|
||||
if s.level <= LOG_TRACE {
|
||||
_ = s.TRACE.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Debug implement ILogger
|
||||
func (s *EmsLogger) Debug(v ...interface{}) {
|
||||
if s.level <= LOG_DEBUG {
|
||||
_ = s.DEBUG.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Debugf implement ILogger
|
||||
func (s *EmsLogger) Debugf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_DEBUG {
|
||||
_ = s.DEBUG.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Info implement ILogger
|
||||
func (s *EmsLogger) Info(v ...interface{}) {
|
||||
if s.level <= LOG_INFO {
|
||||
_ = s.INFO.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Infof implement ILogger
|
||||
func (s *EmsLogger) Infof(format string, v ...interface{}) {
|
||||
if s.level <= LOG_INFO {
|
||||
_ = s.INFO.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func (s *EmsLogger) Warn(v ...interface{}) {
|
||||
if s.level <= LOG_WARN {
|
||||
_ = s.WARN.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func (s *EmsLogger) Warnf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_WARN {
|
||||
_ = s.WARN.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Error implement ILogger
|
||||
func (s *EmsLogger) Error(v ...interface{}) {
|
||||
if s.level <= LOG_ERROR {
|
||||
_ = s.ERROR.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf implement ILogger
|
||||
func (s *EmsLogger) Errorf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_ERROR {
|
||||
_ = s.ERROR.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func (s *EmsLogger) Fatal(v ...interface{}) {
|
||||
if s.level <= LOG_FATAL {
|
||||
_ = s.FATAL.Output(s.depth, fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func (s *EmsLogger) Fatalf(format string, v ...interface{}) {
|
||||
if s.level <= LOG_FATAL {
|
||||
_ = s.FATAL.Output(s.depth, fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func (s *EmsLogger) Level() LogLevel {
|
||||
return s.level
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func (s *EmsLogger) LevelString() string {
|
||||
return s.levelString[s.level]
|
||||
}
|
||||
|
||||
// SetLevel implement ILogger
|
||||
func (s *EmsLogger) SetLevel(l LogLevel) {
|
||||
s.level = l
|
||||
}
|
||||
|
||||
var Elogger Logger
|
||||
|
||||
func InitLogger(logFile string, period int, count int, prefix string, logLevel LogLevel) {
|
||||
|
||||
/*
|
||||
logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
|
||||
logWriter := getLogWriter(logFile, period, count)
|
||||
Elogger = NewEmsLogger3(logWriter, prefix, DEFAULT_LOG_FLAG, logLevel)
|
||||
fmt.Printf("logFile=%s, period=%d, count=%d, prefix=%s, logLevel=%s\n", logFile, period, count, prefix, GetLevelString())
|
||||
}
|
||||
|
||||
// Trace implement ILogger
|
||||
func Trace(v ...interface{}) {
|
||||
Elogger.Trace(v...)
|
||||
}
|
||||
|
||||
// Tracef implement ILogger
|
||||
func Tracef(format string, v ...interface{}) {
|
||||
Elogger.Tracef(format, v...)
|
||||
}
|
||||
|
||||
// Debug implement ILogger
|
||||
func Debug(v ...interface{}) {
|
||||
Elogger.Debug(v...)
|
||||
}
|
||||
|
||||
// Debugf implement ILogger
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
Elogger.Debugf(format, v...)
|
||||
}
|
||||
|
||||
// Info implement ILogger
|
||||
func Info(v ...interface{}) {
|
||||
Elogger.Info(v...)
|
||||
}
|
||||
|
||||
// Infof implement ILogger
|
||||
func Infof(format string, v ...interface{}) {
|
||||
Elogger.Infof(format, v...)
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func Warn(v ...interface{}) {
|
||||
Elogger.Warn(v...)
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
Elogger.Warnf(format, v...)
|
||||
}
|
||||
|
||||
// Error implement ILogger
|
||||
func Error(v ...interface{}) {
|
||||
Elogger.Error(v...)
|
||||
}
|
||||
|
||||
// Errorf implement ILogger
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
Elogger.Errorf(format, v...)
|
||||
}
|
||||
|
||||
// Warn implement ILogger
|
||||
func Fatal(v ...interface{}) {
|
||||
Elogger.Fatal(v...)
|
||||
}
|
||||
|
||||
// Warnf implement ILogger
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
Elogger.Fatalf(format, v...)
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func GetLevel() LogLevel {
|
||||
return Elogger.Level()
|
||||
}
|
||||
|
||||
// Level implement ILogger
|
||||
func GetLevelString() string {
|
||||
return Elogger.LevelString()
|
||||
}
|
||||
|
||||
// SetLevel implement ILogger
|
||||
func SetLevel(l LogLevel) {
|
||||
Elogger.SetLevel(l)
|
||||
}
|
||||
71
lib/log/partition.go
Normal file
71
lib/log/partition.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
rotatelogs "github.com/lestrrat/go-file-rotatelogs"
|
||||
)
|
||||
|
||||
type WriteSyncer interface {
|
||||
io.Writer
|
||||
Sync() error
|
||||
}
|
||||
|
||||
// 得到LogWriter
|
||||
func getLogWriter(filePath string, period, count int) WriteSyncer {
|
||||
warnIoWriter := getWriter(filePath, period, count)
|
||||
return addSync(warnIoWriter)
|
||||
}
|
||||
|
||||
// 日志文件切割
|
||||
func getWriter(filename string, period, count int) io.Writer {
|
||||
// 保存日志count天,每period小时分割一次日志
|
||||
duration := time.Hour * time.Duration(period)
|
||||
var logfile string
|
||||
if period >= 24 {
|
||||
logfile = filename + "-%Y%m%d"
|
||||
} else {
|
||||
logfile = filename + "-%Y%m%d%H"
|
||||
}
|
||||
hook, err := rotatelogs.New(
|
||||
|
||||
logfile,
|
||||
rotatelogs.WithLinkName(filename),
|
||||
// rotatelogs.WithMaxAge(duration),
|
||||
rotatelogs.WithRotationCount(count),
|
||||
rotatelogs.WithRotationTime(duration),
|
||||
rotatelogs.WithLocation(time.Local),
|
||||
)
|
||||
|
||||
//保存日志30天,每1分钟分割一次日志
|
||||
/*
|
||||
hook, err := rotatelogs.New(
|
||||
filename+"_%Y%m%d%H%M.log",
|
||||
rotatelogs.WithLinkName(filename),
|
||||
rotatelogs.WithMaxAge(time.Hour*24*30),
|
||||
rotatelogs.WithRotationTime(time.Minute*1),
|
||||
)
|
||||
*/
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hook
|
||||
}
|
||||
|
||||
func addSync(w io.Writer) WriteSyncer {
|
||||
switch w := w.(type) {
|
||||
case WriteSyncer:
|
||||
return w
|
||||
default:
|
||||
return writerWrapper{w}
|
||||
}
|
||||
}
|
||||
|
||||
type writerWrapper struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (w writerWrapper) Sync() error {
|
||||
return nil
|
||||
}
|
||||
89
lib/log/syslogger.go.bak
Normal file
89
lib/log/syslogger.go.bak
Normal file
@@ -0,0 +1,89 @@
|
||||
//go:build !windows && !nacl && !plan9
|
||||
// +build !windows,!nacl,!plan9
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
)
|
||||
|
||||
var _ Logger = &SyslogLogger{}
|
||||
|
||||
// SyslogLogger will be depricated
|
||||
type SyslogLogger struct {
|
||||
w *syslog.Writer
|
||||
}
|
||||
|
||||
// NewSyslogLogger implements Logger
|
||||
func NewSyslogLogger(w *syslog.Writer) *SyslogLogger {
|
||||
return &SyslogLogger{w: w}
|
||||
}
|
||||
|
||||
// Trace log content as Trace
|
||||
func (s *SyslogLogger) Trace(v ...interface{}) {
|
||||
_ = s.w.Trace(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Tracef log content as Trace and format
|
||||
func (s *SyslogLogger) Tracef(format string, v ...interface{}) {
|
||||
_ = s.w.Trace(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Debug log content as Debug
|
||||
func (s *SyslogLogger) Debug(v ...interface{}) {
|
||||
_ = s.w.Debug(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Debugf log content as Debug and format
|
||||
func (s *SyslogLogger) Debugf(format string, v ...interface{}) {
|
||||
_ = s.w.Debug(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Error log content as Error
|
||||
func (s *SyslogLogger) Error(v ...interface{}) {
|
||||
_ = s.w.Err(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Errorf log content as Errorf and format
|
||||
func (s *SyslogLogger) Errorf(format string, v ...interface{}) {
|
||||
_ = s.w.Err(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Info log content as Info
|
||||
func (s *SyslogLogger) Info(v ...interface{}) {
|
||||
_ = s.w.Info(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Infof log content as Infof and format
|
||||
func (s *SyslogLogger) Infof(format string, v ...interface{}) {
|
||||
_ = s.w.Info(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Warn log content as Warn
|
||||
func (s *SyslogLogger) Warn(v ...interface{}) {
|
||||
_ = s.w.Warn(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Warnf log content as Warnf and format
|
||||
func (s *SyslogLogger) Warnf(format string, v ...interface{}) {
|
||||
_ = s.w.Warn(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Fatal log content as Fatal
|
||||
func (s *SyslogLogger) Fatal(v ...interface{}) {
|
||||
_ = s.w.Fatal(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Fatalf log content as Fatalf and format
|
||||
func (s *SyslogLogger) Fatalf(format string, v ...interface{}) {
|
||||
_ = s.w.Fatal(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Level shows log level
|
||||
func (s *SyslogLogger) Level() LogLevel {
|
||||
return LOG_NODEF
|
||||
}
|
||||
|
||||
// SetLevel always return error, as current log/syslog package doesn't allow to set priority level after syslog.Writer created
|
||||
func (s *SyslogLogger) SetLevel(l LogLevel) {}
|
||||
30
lib/midware/midhandle.go
Normal file
30
lib/midware/midhandle.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"ems.agt/lib/log"
|
||||
)
|
||||
|
||||
func LoggerTraceMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Do stuff here
|
||||
log.Trace("Http Trace Info:")
|
||||
log.Trace(" From Host:", r.RemoteAddr)
|
||||
log.Trace(" To Host:", r.Host)
|
||||
log.Debug(" RequestUri:", r.RequestURI)
|
||||
log.Trace(" Method:", r.Method)
|
||||
log.Trace(" Proto:", r.Proto)
|
||||
log.Trace(" ContentLength:", r.ContentLength)
|
||||
log.Trace(" User-Agent:", r.Header.Get("User-Agent"))
|
||||
log.Trace(" Content-Type:", r.Header.Get("Content-Type"))
|
||||
log.Trace(" AccessToken:", r.Header.Get("AccessToken"))
|
||||
log.Trace("Trace End=====")
|
||||
//body, _ := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
// nop-close to ready r.Body !!!
|
||||
//r.Body = ioutil.NopCloser(bytes.NewReader(body))
|
||||
//log.Trace("Body:", string(body))
|
||||
// Call the next handler, which can be another middleware in the chain, or the final handler.
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
900
lib/mmlp/parse.go
Normal file
900
lib/mmlp/parse.go
Normal file
@@ -0,0 +1,900 @@
|
||||
package mmlp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"ems.agt/lib/dborm"
|
||||
"ems.agt/lib/global"
|
||||
"ems.agt/lib/log"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
type Param struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type MmlCommand struct {
|
||||
Operation string `json:"operation"`
|
||||
Object string `json:"object"`
|
||||
Params []Param `json:"params"`
|
||||
PaList []string `json:"paList"`
|
||||
AaList []string `json:"aaList"`
|
||||
AaMap map[string]interface{} `json:"aaMap"`
|
||||
NaMap map[string]interface{} `json:"naMap"`
|
||||
AaUri []string `json:"aaUri"`
|
||||
AaLoc []string `json:"aaLoc"` // for loc parameter
|
||||
}
|
||||
|
||||
type MmlVar struct {
|
||||
Version string `json:"version"`
|
||||
Output string `json:"output"`
|
||||
Limit int `json:"limit"`
|
||||
User string `json:"user"`
|
||||
SessionToken string `josn:"sessionToken"`
|
||||
HttpUri string `json:"httpUri"`
|
||||
UserAgent string `json:"userAgent"`
|
||||
}
|
||||
|
||||
// func init() {
|
||||
// OmcMmlVar = &MmlVar{
|
||||
// Version: "16.1.1",
|
||||
// Output: DefaultFormatType,
|
||||
// Limit: 50,
|
||||
// }
|
||||
// }
|
||||
|
||||
// func SetOmcMmlVarOutput(output string) {
|
||||
// OmcMmlVar.Output = output
|
||||
// }
|
||||
|
||||
// func SetOmcMmlVarLimit(limit int) {
|
||||
// OmcMmlVar.Limit = limit
|
||||
// }
|
||||
|
||||
func splitByColon(str string) []string {
|
||||
return splitBy(str, ':')
|
||||
}
|
||||
|
||||
func splitByComma(str string) []string {
|
||||
return splitBy(str, ',')
|
||||
}
|
||||
|
||||
func splitBy(str string, sep rune) []string {
|
||||
var result []string
|
||||
var stack []string
|
||||
var current []rune
|
||||
var quotes, apoFlag bool = false, false
|
||||
|
||||
for _, c := range str {
|
||||
if c == '{' || c == '[' || (c == '\'' && apoFlag == false) || (c == '"' && quotes == false) { // "'"
|
||||
apoFlag = true
|
||||
quotes = true
|
||||
stack = append(stack, string(c))
|
||||
} else if c == '}' || c == ']' || (c == '\'' && apoFlag == true) || (c == '"' && quotes == true) {
|
||||
apoFlag = false
|
||||
quotes = false
|
||||
if len(stack) > 0 {
|
||||
stack = stack[:len(stack)-1]
|
||||
}
|
||||
}
|
||||
|
||||
if c == sep && len(stack) == 0 {
|
||||
result = append(result, string(current))
|
||||
current = []rune{}
|
||||
} else {
|
||||
current = append(current, c)
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, string(current))
|
||||
return result
|
||||
}
|
||||
|
||||
func ParseMMLCommand(mmlStr string, mmlComms *[]MmlCommand) error {
|
||||
log.Info("ParseMMLCommand processing ...")
|
||||
log.Debug("mmlStr: ", mmlStr)
|
||||
|
||||
mc := new(MmlCommand)
|
||||
reg := regexp.MustCompile(`\s*;\s*`)
|
||||
mmls := reg.Split(mmlStr, -1)
|
||||
for _, mml := range mmls {
|
||||
log.Trace("mml:", mml)
|
||||
if len(mml) == 0 {
|
||||
continue
|
||||
}
|
||||
//reg := regexp.MustCompile(`\s*:\s*`)
|
||||
//ms := reg.Split(mml, -1)
|
||||
ms := splitByColon(mml)
|
||||
if len(ms) < 1 || len(ms) > 2 {
|
||||
err := global.ErrMmlInvalidCommandFormat
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
if len(ms) == 2 {
|
||||
cmd := strings.Trim(ms[0], " ")
|
||||
reg = regexp.MustCompile(`\s+`)
|
||||
cs := reg.Split(cmd, -1)
|
||||
//cs := strings.Split(cmd, " ")
|
||||
if len(cs) == 2 {
|
||||
mc.Operation = cs[0]
|
||||
mc.Object = cs[1]
|
||||
} else {
|
||||
err := global.ErrMmlInvalidCommandFormat
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
//reg = regexp.MustCompile(`\s*,\s*`)
|
||||
//reg = regexp.MustCompile(`(?U)(?<!\{[^{}]*),(?![^{}]*\})|(?<!\"[^\"]*),(?![^\"]*\")|(?<!\[[^\[\]]*),(?![^\[\]]*\])`)
|
||||
//reg = regexp.MustCompile(`,[^'"\(\)]+`)
|
||||
//params := reg.Split(ms[1], -1)
|
||||
params := splitByComma(strings.Trim(ms[1], " "))
|
||||
//params := strings.Split(ms[1], ",")
|
||||
for _, p := range params {
|
||||
log.Trace("p:", p)
|
||||
if p == "" {
|
||||
continue
|
||||
}
|
||||
mc.PaList = append(mc.PaList, p)
|
||||
reg = regexp.MustCompile(`\s*=\s*`)
|
||||
pvs := reg.Split(p, -1)
|
||||
log.Trace("pvs:", pvs)
|
||||
if len(pvs) == 2 {
|
||||
mc.Params = append(mc.Params, Param{Name: pvs[0], Value: pvs[1]})
|
||||
} else {
|
||||
err := global.ErrMmlInvalidCommandFormat
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else if len(ms) == 1 {
|
||||
cmd := ms[0]
|
||||
reg = regexp.MustCompile(`\s+`)
|
||||
cs := reg.Split(cmd, -1)
|
||||
//cs := strings.Split(cmd, " ")
|
||||
if len(cs) == 2 {
|
||||
mc.Operation = cs[0]
|
||||
mc.Object = cs[1]
|
||||
} else {
|
||||
err := global.ErrMmlInvalidCommandFormat
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := global.ErrMmlInvalidCommandFormat
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
err := ParseMMLAlias(mc)
|
||||
if err != nil {
|
||||
err := global.ErrMmlInvalidCommandFormat
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
*mmlComms = append(*mmlComms, *mc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseMMLAlias(mml *MmlCommand) error {
|
||||
where := fmt.Sprintf("operation='%s' AND object='%s'", mml.Operation, mml.Object)
|
||||
mc, err := dborm.XormGetMmlCommand("mml_command", where)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetMmlCommand: ", err)
|
||||
return err
|
||||
}
|
||||
if mc == nil {
|
||||
err := errors.New("Not found mml map")
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
log.Debug("mml command: ", mc)
|
||||
aaMap := make(map[string]interface{})
|
||||
naMap := make(map[string]interface{})
|
||||
for _, pn := range mml.Params {
|
||||
log.Trace("pn: ", pn)
|
||||
for _, param := range mc.ParamJson {
|
||||
log.Trace("param: ", param)
|
||||
var pv string
|
||||
if pn.Name == param.Name {
|
||||
if param.Apostr == "true" {
|
||||
pv = fmt.Sprintf("'%v'", pn.Value)
|
||||
} else {
|
||||
pv = fmt.Sprintf("%v", pn.Value)
|
||||
}
|
||||
var aa, av string
|
||||
|
||||
if param.Alias != "" {
|
||||
aa = fmt.Sprintf("%s=%v", param.Alias, pv)
|
||||
av = fmt.Sprintf("%v", pv)
|
||||
switch param.Type {
|
||||
case "int":
|
||||
aaMap[param.Alias] = pn.Value
|
||||
naMap[param.Alias] = pn.Value
|
||||
default:
|
||||
aaMap[param.Alias] = pv
|
||||
naMap[param.Alias] = fmt.Sprintf("%v", pn.Value)
|
||||
}
|
||||
} else {
|
||||
aa = fmt.Sprintf("%s=%v", param.Name, pv)
|
||||
av = fmt.Sprintf("%v", pv)
|
||||
switch param.Type {
|
||||
case "int":
|
||||
aaMap[param.Name] = pn.Value
|
||||
naMap[param.Name] = pn.Value
|
||||
default:
|
||||
aaMap[param.Name] = pv
|
||||
naMap[param.Name] = fmt.Sprintf("%v", pn.Value)
|
||||
}
|
||||
}
|
||||
if param.Loc == "" || param.Loc == "true" {
|
||||
mml.AaLoc = append(mml.AaLoc, aa)
|
||||
mml.AaUri = append(mml.AaUri, av)
|
||||
}
|
||||
//mml.AaMap = append(mml.AaMap, aaMap)
|
||||
mml.AaList = append(mml.AaList, aa)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
mml.AaMap = aaMap
|
||||
mml.NaMap = naMap
|
||||
log.Trace("mml.AaMap: ", mml.AaMap)
|
||||
log.Trace("mml.NaMap: ", mml.NaMap)
|
||||
log.Trace("mml.AaList: ", mml.AaList)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseMMLParams(mmlComms *[]MmlCommand) error {
|
||||
for _, mml := range *mmlComms {
|
||||
where := fmt.Sprintf("operation='%s' AND object='%s'", mml.Operation, mml.Object)
|
||||
mc, err := dborm.XormGetMmlCommand("mml_command", where)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetMmlCommand: ", err)
|
||||
return err
|
||||
}
|
||||
if mc == nil {
|
||||
err := errors.New("Not found mml map")
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
log.Debug("mml command: ", mc)
|
||||
for _, pn := range mml.Params {
|
||||
log.Trace("pn: ", pn)
|
||||
for _, param := range mc.ParamJson {
|
||||
log.Trace("param: ", param)
|
||||
var pv string
|
||||
if pn.Name == param.Name {
|
||||
if param.Apostr == "true" {
|
||||
pv = fmt.Sprintf("'%v'", pn.Value)
|
||||
} else {
|
||||
pv = fmt.Sprintf("%v", pn.Value)
|
||||
}
|
||||
var aa string
|
||||
aaMap := make(map[string]interface{})
|
||||
if param.Alias != "" {
|
||||
aa = fmt.Sprintf("%s=%v", param.Alias, pv)
|
||||
switch param.Type {
|
||||
case "int":
|
||||
aaMap[param.Alias] = pn.Value
|
||||
case "string":
|
||||
aaMap[param.Alias] = pv
|
||||
}
|
||||
} else {
|
||||
aa = fmt.Sprintf("%s=%v", param.Name, pv)
|
||||
switch param.Type {
|
||||
case "int":
|
||||
aaMap[param.Name] = pn.Value
|
||||
case "string":
|
||||
aaMap[param.Name] = pv
|
||||
}
|
||||
}
|
||||
//mml.AaMap = append(mml.AaMap, aaMap)
|
||||
mml.AaList = append(mml.AaList, aa)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Trace("mml.AaMap: ", mml.AaMap)
|
||||
log.Trace("mml.AaList: ", mml.AaList)
|
||||
*mmlComms = append(*mmlComms, mml)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseRequestUri(httpUri string, mmlMap *dborm.MmlHttpMap, mml *MmlCommand) string {
|
||||
requestURI := fmt.Sprintf("%s%s", httpUri, mmlMap.URI)
|
||||
if mmlMap.ExtUri != "" && len(mml.AaUri) > 0 {
|
||||
extUri := strings.Join(mml.AaUri, "/")
|
||||
requestURI = requestURI + fmt.Sprintf(mmlMap.ExtUri, extUri)
|
||||
}
|
||||
if mmlMap.Params != "" {
|
||||
params := strings.Join(mml.AaLoc, "+and+")
|
||||
params = strings.ReplaceAll(params, " ", "+") // replace " " to "+"
|
||||
log.Trace("params:", params)
|
||||
if mmlMap.ParamTag == "SQL" && strings.TrimSpace(params) != "" {
|
||||
params = "+where+" + params
|
||||
}
|
||||
requestURI = fmt.Sprintf("%s%s%s", requestURI, mmlMap.Params, params)
|
||||
}
|
||||
return requestURI
|
||||
}
|
||||
|
||||
func TransMml2HttpReq(omcMmlVar *MmlVar, mml *MmlCommand) (*[]byte, error) {
|
||||
log.Info("TransMml2HttpReq processing ...")
|
||||
log.Debug("mml: ", mml)
|
||||
|
||||
where := fmt.Sprintf("operation='%s' AND object='%s'", mml.Operation, mml.Object)
|
||||
mmlMap, err := dborm.XormGetMmlHttpMap("mml_http_map", where)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetMmlHttpMap: ", err)
|
||||
return ParseErrorOutput(err), err
|
||||
}
|
||||
if mmlMap == nil {
|
||||
err := errors.New("Not found mml map")
|
||||
log.Error(err)
|
||||
return ParseErrorOutput(err), err
|
||||
}
|
||||
log.Trace("mmlMap: ", mmlMap)
|
||||
if mmlMap.Output == "" {
|
||||
mmlMap.Output = "{}"
|
||||
}
|
||||
outputJson := new(dborm.MmlOutput)
|
||||
err = json.Unmarshal([]byte(mmlMap.Output), outputJson)
|
||||
if err != nil {
|
||||
log.Error("Failed to Unmarshal:", err)
|
||||
return ParseErrorOutput(err), err
|
||||
}
|
||||
log.Trace("outputJson: ", outputJson)
|
||||
inputJson := new(dborm.MmlInput)
|
||||
log.Trace("mmlMap.Input: ", mmlMap.Input)
|
||||
if mmlMap.Input == "" {
|
||||
mmlMap.Input = "{}"
|
||||
}
|
||||
err = json.Unmarshal([]byte(mmlMap.Input), inputJson)
|
||||
if err != nil {
|
||||
log.Error("Failed to Unmarshal:", err)
|
||||
return ParseErrorOutput(err), err
|
||||
}
|
||||
log.Trace("inputJson: ", inputJson)
|
||||
|
||||
var requestURI string
|
||||
var output *[]byte
|
||||
client := resty.New()
|
||||
switch strings.ToLower(mmlMap.Method) {
|
||||
case "get":
|
||||
requestURI = parseRequestUri(omcMmlVar.HttpUri, mmlMap, mml)
|
||||
log.Debugf("method: Get requestURI: %s", requestURI)
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}).
|
||||
SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI)
|
||||
if err != nil {
|
||||
log.Error("Failed to Get:", err)
|
||||
output = ParseErrorOutput(err)
|
||||
} else {
|
||||
output = ParseOutputResponse(omcMmlVar, outputJson, response)
|
||||
}
|
||||
case "post":
|
||||
requestURI = parseRequestUri(omcMmlVar.HttpUri, mmlMap, mml)
|
||||
body := ParseInputBody(inputJson, mml)
|
||||
log.Debugf("method: Post requestURI: %s", requestURI)
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}).
|
||||
SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(*body).
|
||||
Post(requestURI)
|
||||
if err != nil {
|
||||
log.Error("Failed to Post:", err)
|
||||
output = ParseErrorOutput(err)
|
||||
} else {
|
||||
output = ParseOutputResponse(omcMmlVar, outputJson, response)
|
||||
}
|
||||
case "put":
|
||||
requestURI = parseRequestUri(omcMmlVar.HttpUri, mmlMap, mml)
|
||||
body := ParseInputBody(inputJson, mml)
|
||||
log.Debugf("method: Put requestURI: %s", requestURI)
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}).
|
||||
SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
SetBody(*body).
|
||||
Put(requestURI)
|
||||
if err != nil {
|
||||
log.Error("Failed to Put:", err)
|
||||
output = ParseErrorOutput(err)
|
||||
} else {
|
||||
output = ParseOutputResponse(omcMmlVar, outputJson, response)
|
||||
}
|
||||
case "delete":
|
||||
requestURI = parseRequestUri(omcMmlVar.HttpUri, mmlMap, mml)
|
||||
log.Debugf("method: Delete requestURI: %s", requestURI)
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}).
|
||||
SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Delete(requestURI)
|
||||
if err != nil {
|
||||
log.Error("Failed to Delete:", err)
|
||||
output = ParseErrorOutput(err)
|
||||
} else {
|
||||
output = ParseOutputResponse(omcMmlVar, outputJson, response)
|
||||
}
|
||||
case "patch":
|
||||
requestURI = parseRequestUri(omcMmlVar.HttpUri, mmlMap, mml)
|
||||
log.Debugf("method: patch requestURI: %s", requestURI)
|
||||
response, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"accessToken": omcMmlVar.SessionToken}).
|
||||
SetHeaders(map[string]string{"User-Agent": omcMmlVar.UserAgent}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Patch(requestURI)
|
||||
if err != nil {
|
||||
log.Error("Failed to Patch:", err)
|
||||
output = ParseErrorOutput(err)
|
||||
} else {
|
||||
output = ParseOutputResponse(omcMmlVar, outputJson, response)
|
||||
}
|
||||
default:
|
||||
err := errors.New("not found mml command")
|
||||
log.Error(err)
|
||||
output = ParseErrorOutput(err)
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
const (
|
||||
MaxMmlOutputBufferSize = 1000000
|
||||
FormatTypeJson = "json"
|
||||
FormatTypeTable = "table"
|
||||
DefaultFormatType = FormatTypeTable
|
||||
)
|
||||
|
||||
const (
|
||||
RetCodeSucceeded = 0
|
||||
RetCodeFailed = 0
|
||||
)
|
||||
|
||||
func ParseInputBody(inputJson *dborm.MmlInput, mml *MmlCommand) *[]byte {
|
||||
inputBody := make(map[string]interface{})
|
||||
log.Trace("mml.NaMap:", mml.NaMap)
|
||||
log.Trace("mml.AaMap:", mml.AaMap)
|
||||
if strings.ToLower(inputJson.BodyFmt) == "putdb" {
|
||||
for _, icol := range inputJson.Cols {
|
||||
log.Trace("icol:", icol)
|
||||
mml.NaMap[icol.Name] = icol.Value
|
||||
}
|
||||
inputBody[inputJson.BodyKey] = mml.NaMap
|
||||
} else {
|
||||
inputParams := make([]map[string]interface{}, 0)
|
||||
inputParams = append(inputParams, mml.NaMap)
|
||||
inputBody[inputJson.BodyKey] = inputParams
|
||||
}
|
||||
|
||||
body, err := json.Marshal(inputBody)
|
||||
if err != nil {
|
||||
log.Error("Failed to marshal:", err)
|
||||
}
|
||||
|
||||
log.Trace("inputBody:", inputBody)
|
||||
log.Trace("body:", string(body))
|
||||
return &body
|
||||
}
|
||||
|
||||
func ParseOutputResponse(omcMmlVar *MmlVar, outputJson *dborm.MmlOutput, response *resty.Response) *[]byte {
|
||||
var output []byte
|
||||
var str bytes.Buffer
|
||||
|
||||
switch response.StatusCode() {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
if omcMmlVar.Output == FormatTypeJson {
|
||||
code := fmt.Sprintf("StatusCode = %d status %s\n\n", response.StatusCode(), response.Status())
|
||||
title := formatTitle(outputJson.Title)
|
||||
|
||||
json.Indent(&str, response.Body(), "", " ")
|
||||
log.Trace(str.String())
|
||||
|
||||
output = global.BytesCombine1([]byte(code), []byte(title), str.Bytes(), []byte("\n"))
|
||||
} else {
|
||||
log.Trace("Body:", string(response.Body()))
|
||||
mapDatas := make(map[string]interface{}, 0)
|
||||
|
||||
err := json.Unmarshal(response.Body(), &mapDatas)
|
||||
if err != nil {
|
||||
log.Error("Failed to json.Unmarshal:", err)
|
||||
//output = *ParseErrorOutput(err)
|
||||
output = *ParseErrorOutput(string(response.Body()))
|
||||
return &output
|
||||
}
|
||||
log.Trace("mapDatas:", mapDatas)
|
||||
switch strings.ToLower(outputJson.RetFmt) {
|
||||
case "getdb":
|
||||
if len(mapDatas) > 0 {
|
||||
var data interface{}
|
||||
for _, data = range mapDatas {
|
||||
log.Trace("data:", data)
|
||||
break
|
||||
}
|
||||
if len(data.([]interface{})) > 0 {
|
||||
table := (data.([]interface{}))[0]
|
||||
log.Trace("table:", table)
|
||||
|
||||
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
|
||||
title := formatTitle(outputJson.Title)
|
||||
fmtResults := ParseTableOutput(outputJson, table)
|
||||
output = global.BytesCombine1([]byte(code), []byte(title), []byte(fmtResults))
|
||||
}
|
||||
}
|
||||
case "deletedb":
|
||||
var data interface{}
|
||||
for _, data = range mapDatas {
|
||||
log.Trace("data:", data)
|
||||
break
|
||||
}
|
||||
|
||||
if len(data.(map[string]interface{})) > 0 {
|
||||
table := data.(map[string]interface{})
|
||||
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
|
||||
fmtResults := ParseDBOperOutput(outputJson, table)
|
||||
output = global.BytesCombine1([]byte(code), []byte(fmtResults))
|
||||
}
|
||||
case "postdb":
|
||||
var data interface{}
|
||||
for _, data = range mapDatas {
|
||||
log.Trace("data:", data)
|
||||
break
|
||||
}
|
||||
|
||||
if len(data.(map[string]interface{})) > 0 {
|
||||
table := data.(map[string]interface{})
|
||||
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
|
||||
fmtResults := ParseDBOperOutput(outputJson, table)
|
||||
output = global.BytesCombine1([]byte(code), []byte(fmtResults))
|
||||
}
|
||||
case "putdb":
|
||||
var data interface{}
|
||||
for _, data = range mapDatas {
|
||||
log.Trace("data:", data)
|
||||
break
|
||||
}
|
||||
if len(data.(map[string]interface{})) > 0 {
|
||||
table := data.(map[string]interface{})
|
||||
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
|
||||
fmtResults := ParseDBOperOutput(outputJson, table)
|
||||
output = global.BytesCombine1([]byte(code), []byte(fmtResults))
|
||||
}
|
||||
case "getnf":
|
||||
if len(mapDatas) > 0 {
|
||||
var data interface{}
|
||||
for _, data = range mapDatas {
|
||||
log.Trace("data:", data)
|
||||
break
|
||||
}
|
||||
if len(data.([]interface{})) > 0 {
|
||||
//table := (data.([]interface{}))[0]
|
||||
//log.Trace("table:", table)
|
||||
|
||||
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
|
||||
title := formatTitle(outputJson.Title)
|
||||
fmtResults := ParseNFTableOutput(outputJson, data)
|
||||
output = global.BytesCombine1([]byte(code), []byte(title), []byte(fmtResults))
|
||||
}
|
||||
}
|
||||
default:
|
||||
code := fmt.Sprintf(outputJson.RetMsg, RetCodeSucceeded)
|
||||
output = global.BytesCombine1([]byte(code))
|
||||
}
|
||||
|
||||
}
|
||||
default:
|
||||
if omcMmlVar.Output == FormatTypeJson {
|
||||
code := fmt.Sprintf("StatusCode = %d status %s\n\n", response.StatusCode(), response.Status())
|
||||
//title := formatTitle("Network Element Information")
|
||||
|
||||
json.Indent(&str, response.Body(), "", " ")
|
||||
log.Trace(str.String())
|
||||
|
||||
output = global.BytesCombine1([]byte(code), str.Bytes(), []byte("\n"))
|
||||
} else {
|
||||
log.Trace("Body:", string(response.Body()))
|
||||
mapResults := make(map[string]interface{}, 0)
|
||||
|
||||
err := json.Unmarshal(response.Body(), &mapResults)
|
||||
if err != nil {
|
||||
log.Error("Failed to json.Unmarshal:", err)
|
||||
output = *ParseErrorOutput(string(response.Body()))
|
||||
} else {
|
||||
log.Trace("mapResults:", mapResults)
|
||||
errResult := mapResults["error"]
|
||||
log.Trace("errResult:", errResult)
|
||||
if len(errResult.(map[string]interface{})) > 0 {
|
||||
errCode, _ := strconv.Atoi(fmt.Sprintf("%v", errResult.(map[string]interface{})["errorCode"]))
|
||||
errorInfo := errResult.(map[string]interface{})["errorInfo"]
|
||||
output = []byte(fmt.Sprintf(outputJson.ErrMsg, errCode, errorInfo))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return &output
|
||||
}
|
||||
|
||||
func ParseDBOperOutput(outputJson *dborm.MmlOutput, cols any) string {
|
||||
var colOutput []dborm.ColOutput = outputJson.Cols
|
||||
var value, retFmtCols string
|
||||
if len(cols.(map[string]interface{})) > 0 {
|
||||
if len(colOutput) > 0 {
|
||||
coln := colOutput[0].Name
|
||||
value = fmt.Sprintf("%v", cols.(map[string]interface{})[coln])
|
||||
log.Tracef("coln:%s value:%s", coln, value)
|
||||
retFmtCols = colOutput[0].Display + " = " + value + "\n\n"
|
||||
}
|
||||
}
|
||||
|
||||
return retFmtCols
|
||||
}
|
||||
|
||||
func ParseNFTableOutput(outputJson *dborm.MmlOutput, cols any) string {
|
||||
var colOutput []dborm.ColOutput
|
||||
var fmtColName string
|
||||
var colName []string
|
||||
var spaceNum int = 1
|
||||
var alignmentM, alignmentSN, alignmentSV string = "Left", "Right", "Left"
|
||||
|
||||
if outputJson.SepSpaceNum != 0 {
|
||||
spaceNum = outputJson.SepSpaceNum
|
||||
}
|
||||
if outputJson.AlignmentM != "" {
|
||||
alignmentM = outputJson.AlignmentM
|
||||
}
|
||||
if outputJson.AlignmentSN != "" {
|
||||
alignmentSN = outputJson.AlignmentSN
|
||||
}
|
||||
if outputJson.AlignmentSV != "" {
|
||||
alignmentSV = outputJson.AlignmentSV
|
||||
}
|
||||
|
||||
maxLength := math.MinInt64
|
||||
for _, coln := range outputJson.Cols {
|
||||
log.Trace("coln:", coln)
|
||||
|
||||
if len(coln.Display) > maxLength {
|
||||
maxLength = len(coln.Display)
|
||||
}
|
||||
if coln.Length < len(coln.Display) {
|
||||
coln.Length = len(coln.Display)
|
||||
}
|
||||
|
||||
colName = append(colName, ParseAlignmentOutput(coln.Length, alignmentM, coln.Display))
|
||||
colOutput = append(colOutput, coln)
|
||||
}
|
||||
fmtColName = formatLineBySpace(&colName, spaceNum)
|
||||
log.Trace("fmtColName:", fmtColName)
|
||||
|
||||
var retFmtCols string
|
||||
var fmtColValues []string
|
||||
var numberResult int
|
||||
// for _, colnvs := range cols.([]interface{}) {
|
||||
// log.Trace("colnvs:", colnvs)
|
||||
// if colnvs == nil {
|
||||
// break
|
||||
// }
|
||||
numberResult = len(cols.([]interface{}))
|
||||
|
||||
if numberResult == 1 && outputJson.SingleList == true {
|
||||
colnv := cols.([]interface{})[0]
|
||||
log.Trace("colnv:", colnv)
|
||||
|
||||
var fmtNV []string
|
||||
for _, coln := range colOutput {
|
||||
fmtName := ParseAlignmentOutput(maxLength, alignmentSN, coln.Display)
|
||||
log.Tracef("alignmentSN:%s fmtName:%s", alignmentSN, fmtName)
|
||||
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
|
||||
fmtValue := ParseAlignmentOutput(coln.Length, alignmentSV, value)
|
||||
fmtNV = append(fmtNV, fmtName+": "+fmtValue)
|
||||
}
|
||||
|
||||
fmtResults := strings.Join(fmtNV, "\n")
|
||||
log.Tracef("fmtResults:\n%s", fmtResults)
|
||||
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
|
||||
retFmtCols = fmtResults + "\n\n" + fmtEnd
|
||||
log.Tracef("retFmtCols:\n%s", retFmtCols)
|
||||
return retFmtCols
|
||||
} else {
|
||||
for i := 0; i < numberResult; i++ {
|
||||
colnv := cols.([]interface{})[i]
|
||||
log.Trace("colnv:", colnv)
|
||||
var colValues []string
|
||||
var newVal []string
|
||||
for _, coln := range colOutput {
|
||||
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
|
||||
if len(coln.Alias) != 0 {
|
||||
enumVal, _ := strconv.Atoi(value)
|
||||
value = parseEnumAlias(&(coln.Alias), enumVal)
|
||||
}
|
||||
newVal = append(newVal, ParseAlignmentOutput(coln.Length, alignmentM, value))
|
||||
}
|
||||
colValues = append(colValues, formatLineBySpace(&newVal, spaceNum))
|
||||
log.Trace("colValues:", colValues)
|
||||
fmtColValues = append(fmtColValues, strings.Join(colValues, "\n"))
|
||||
log.Trace("fmtColValues:", fmtColValues)
|
||||
}
|
||||
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
|
||||
retFmtCols = fmtColName + "\n\n" + strings.Join(fmtColValues, "\n") + "\n\n" + fmtEnd
|
||||
log.Tracef("retFmtCols:\n%s", retFmtCols)
|
||||
return retFmtCols
|
||||
}
|
||||
}
|
||||
|
||||
func ParseTableOutput(outputJson *dborm.MmlOutput, cols any) string {
|
||||
var colOutput []dborm.ColOutput
|
||||
var fmtColName string
|
||||
var colName []string
|
||||
var spaceNum int = 1
|
||||
var alignmentM, alignmentSN, alignmentSV string = "Left", "Right", "Left"
|
||||
|
||||
if outputJson.SepSpaceNum != 0 {
|
||||
spaceNum = outputJson.SepSpaceNum
|
||||
}
|
||||
if outputJson.AlignmentM != "" {
|
||||
alignmentM = outputJson.AlignmentM
|
||||
}
|
||||
if outputJson.AlignmentSN != "" {
|
||||
alignmentSN = outputJson.AlignmentSN
|
||||
}
|
||||
if outputJson.AlignmentSV != "" {
|
||||
alignmentSV = outputJson.AlignmentSV
|
||||
}
|
||||
|
||||
maxLength := math.MinInt64
|
||||
for _, coln := range outputJson.Cols {
|
||||
log.Trace("coln:", coln)
|
||||
|
||||
if len(coln.Display) > maxLength {
|
||||
maxLength = len(coln.Display)
|
||||
}
|
||||
if coln.Length < len(coln.Display) {
|
||||
coln.Length = len(coln.Display)
|
||||
}
|
||||
|
||||
colName = append(colName, ParseAlignmentOutput(coln.Length, alignmentM, coln.Display))
|
||||
colOutput = append(colOutput, coln)
|
||||
}
|
||||
fmtColName = formatLineBySpace(&colName, spaceNum)
|
||||
log.Trace("fmtColName:", fmtColName)
|
||||
|
||||
var retFmtCols string
|
||||
var fmtColValues []string
|
||||
var numberResult int
|
||||
for _, colnvs := range cols.(map[string]interface{}) {
|
||||
log.Trace("colnvs:", colnvs)
|
||||
if colnvs == nil {
|
||||
break
|
||||
}
|
||||
numberResult = len(colnvs.([]interface{}))
|
||||
|
||||
if numberResult == 1 && outputJson.SingleList == true {
|
||||
colnv := colnvs.([]interface{})[0]
|
||||
log.Trace("colnv:", colnv)
|
||||
|
||||
var fmtNV []string
|
||||
for _, coln := range colOutput {
|
||||
fmtName := ParseAlignmentOutput(maxLength, alignmentSN, coln.Display)
|
||||
log.Tracef("alignmentSN:%s fmtName:%s", alignmentSN, fmtName)
|
||||
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
|
||||
fmtValue := ParseAlignmentOutput(coln.Length, alignmentSV, value)
|
||||
fmtNV = append(fmtNV, fmtName+": "+fmtValue)
|
||||
}
|
||||
|
||||
fmtResults := strings.Join(fmtNV, "\n")
|
||||
log.Tracef("fmtResults:\n%s", fmtResults)
|
||||
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
|
||||
retFmtCols = fmtResults + "\n\n" + fmtEnd
|
||||
log.Tracef("retFmtCols:\n%s", retFmtCols)
|
||||
return retFmtCols
|
||||
} else {
|
||||
for i := 0; i < numberResult; i++ {
|
||||
colnv := colnvs.([]interface{})[i]
|
||||
log.Trace("colnv:", colnv)
|
||||
var colValues []string
|
||||
var newVal []string
|
||||
for _, coln := range colOutput {
|
||||
value := fmt.Sprintf("%v", colnv.(map[string]interface{})[coln.Name])
|
||||
if len(coln.Alias) != 0 {
|
||||
enumVal, _ := strconv.Atoi(value)
|
||||
value = parseEnumAlias(&(coln.Alias), enumVal)
|
||||
}
|
||||
newVal = append(newVal, ParseAlignmentOutput(coln.Length, alignmentM, value))
|
||||
}
|
||||
colValues = append(colValues, formatLineBySpace(&newVal, spaceNum))
|
||||
log.Trace("colValues:", colValues)
|
||||
fmtColValues = append(fmtColValues, strings.Join(colValues, "\n"))
|
||||
log.Trace("fmtColValues:", fmtColValues)
|
||||
}
|
||||
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
|
||||
retFmtCols = fmtColName + "\n\n" + strings.Join(fmtColValues, "\n") + "\n\n" + fmtEnd
|
||||
log.Tracef("retFmtCols:\n%s", retFmtCols)
|
||||
return retFmtCols
|
||||
}
|
||||
}
|
||||
fmtEnd := fmt.Sprintf(outputJson.End, numberResult)
|
||||
retFmtCols = fmtColName + "\n" + strings.Join(fmtColValues, "\n") + "\n\n" + fmtEnd
|
||||
log.Tracef("retFmtCols:\n%s", retFmtCols)
|
||||
return retFmtCols
|
||||
}
|
||||
|
||||
func parseEnumAlias(alias *[]string, enumVal int) string {
|
||||
return (*alias)[enumVal]
|
||||
}
|
||||
|
||||
func formatLineBySpace(strArray *[]string, spaceNum int) string {
|
||||
space := strings.Repeat(" ", spaceNum)
|
||||
return strings.Join(*strArray, space)
|
||||
}
|
||||
|
||||
func ParseAlignmentOutput(length int, alignment string, str string) string {
|
||||
spaceLen := length - len(str)
|
||||
if spaceLen < 0 {
|
||||
log.Warnf("len(str=%s)=%d more length=%d", str, len(str), length)
|
||||
spaceLen = 0
|
||||
}
|
||||
var retStr string
|
||||
switch alignment {
|
||||
case "Left":
|
||||
suffix := strings.Repeat(" ", spaceLen)
|
||||
retStr = str + suffix
|
||||
case "Right":
|
||||
prefix := strings.Repeat(" ", spaceLen)
|
||||
retStr = prefix + str
|
||||
log.Tracef("retStr:%s", retStr)
|
||||
case "Middle":
|
||||
prefix := strings.Repeat(" ", int(math.Ceil(float64(spaceLen)/2)))
|
||||
suffix := strings.Repeat(" ", int(math.Floor(float64(spaceLen)/2)))
|
||||
retStr = prefix + str + suffix
|
||||
}
|
||||
log.Tracef("length=%d, spaceLne=%d, alignment=%s, str=%s, retStr=%s", length, spaceLen, alignment, str, retStr)
|
||||
return retStr
|
||||
}
|
||||
|
||||
func ParseErrorOutput(err any) *[]byte {
|
||||
var output []byte
|
||||
|
||||
var formatType string = DefaultFormatType
|
||||
if formatType == FormatTypeJson {
|
||||
output = []byte(fmt.Sprintf("ErrorCode = 1 Error message: %v\n\n", err))
|
||||
} else {
|
||||
output = []byte(fmt.Sprintf("RetCode = -1 operation failed: %v\n\n", err))
|
||||
}
|
||||
|
||||
return &output
|
||||
}
|
||||
|
||||
func formatTitle(title string) string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString(title)
|
||||
builder.WriteString("\n")
|
||||
for i := 0; i < len(title); i++ {
|
||||
builder.WriteString("-")
|
||||
}
|
||||
builder.WriteString("\n")
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
func formatTableOutput() {
|
||||
|
||||
}
|
||||
179
lib/oauth/oauth.go
Normal file
179
lib/oauth/oauth.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ems.agt/lib/log"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// GenToken 生成Token值
|
||||
func GenToken(mapClaims jwt.MapClaims) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, mapClaims)
|
||||
var nowDate = time.Now()
|
||||
var secret = fmt.Sprintf("%v%v", nowDate, "xxxx")
|
||||
return token.SignedString([]byte(secret))
|
||||
}
|
||||
|
||||
// GenerateToken 生成Token值
|
||||
func GenerateToken(mapClaims jwt.MapClaims, key string) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, mapClaims)
|
||||
return token.SignedString([]byte(key))
|
||||
}
|
||||
|
||||
// ParseToken: "解析token"
|
||||
func ParseToken(token string, secret string) (string, error) {
|
||||
claim, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(secret), nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return claim.Claims.(jwt.MapClaims)["cmd"].(string), nil
|
||||
}
|
||||
|
||||
func RandAccessToken(n int) (ret string) {
|
||||
allString := "52661fbd-6b84-4fc2-aa1e-17879a5c6c9b"
|
||||
ret = ""
|
||||
for i := 0; i < n; i++ {
|
||||
r := rand.Intn(len(allString))
|
||||
ret = ret + allString[r:r+1]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
const letterBytes = "abcdef0123456789"
|
||||
const (
|
||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||
)
|
||||
|
||||
var src = rand.NewSource(time.Now().UnixNano())
|
||||
|
||||
func RandStringBytes(n int) string {
|
||||
b := make([]byte, n)
|
||||
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
|
||||
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
|
||||
if remain == 0 {
|
||||
cache, remain = src.Int63(), letterIdxMax
|
||||
}
|
||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
||||
b[i] = letterBytes[idx]
|
||||
i--
|
||||
}
|
||||
cache >>= letterIdxBits
|
||||
remain--
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func GenRandToken() string {
|
||||
return RandStringBytes(8) + "-" + RandStringBytes(4) + "-" +
|
||||
RandStringBytes(4) + "-" + RandStringBytes(4) + "-" + RandStringBytes(12)
|
||||
}
|
||||
|
||||
type OAuthBody struct {
|
||||
GrantType string
|
||||
UserName string
|
||||
Value string
|
||||
}
|
||||
|
||||
/*
|
||||
func IsValidOAuthInfo(oAuthBody OAuthBody) bool {
|
||||
log.Debug("IsValidOAuthInfo processing... ")
|
||||
|
||||
conf := config.GetYamlConfig()
|
||||
for _, o := range conf.Auth {
|
||||
if oAuthBody.GrantType == o.Type && oAuthBody.UserName == o.User && oAuthBody.Value == o.Password {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
*/
|
||||
|
||||
func IsWrongOAuthInfo(oAuthBody OAuthBody) bool {
|
||||
log.Debug("IsWrongOAuthInfo processing... ")
|
||||
|
||||
if oAuthBody.GrantType == "" || strings.ToLower(oAuthBody.GrantType) != "password" ||
|
||||
oAuthBody.UserName == "" || oAuthBody.Value == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func GetTokenFromHttpRequest(r *http.Request) string {
|
||||
for k, v := range r.Header {
|
||||
log.Tracef("k:%s, v:%s", k, v)
|
||||
if strings.ToLower(k) == "accesstoken" && len(v) != 0 {
|
||||
log.Trace("AccessToken:", v[0])
|
||||
return v[0]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsCarriedToken check token is carried
|
||||
func IsCarriedToken(r *http.Request) (string, bool) {
|
||||
|
||||
token := GetTokenFromHttpRequest(r)
|
||||
if token == "" {
|
||||
return "", false
|
||||
}
|
||||
return token, true
|
||||
}
|
||||
|
||||
// Bcrypt Encrypt 加密明文密码
|
||||
func BcryptEncrypt(password string) (string, error) {
|
||||
hashedBytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
return string(hashedBytes), err
|
||||
}
|
||||
|
||||
// Bcrypt Compare 密文校验
|
||||
func BcryptCompare(hashedPassword, password string) error {
|
||||
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
|
||||
}
|
||||
|
||||
// sha256 crypt
|
||||
func GetSHA256HashCode(stringMessage string) string {
|
||||
message := []byte(stringMessage) //字符串转化字节数组
|
||||
//创建一个基于SHA256算法的hash.Hash接口的对象
|
||||
hash := sha256.New() //sha-256加密
|
||||
//输入数据
|
||||
hash.Write(message)
|
||||
//计算哈希值
|
||||
bytes := hash.Sum(nil)
|
||||
//将字符串编码为16进制格式,返回字符串
|
||||
hashCode := hex.EncodeToString(bytes)
|
||||
//返回哈希值
|
||||
return hashCode
|
||||
}
|
||||
|
||||
// sha512 crypt
|
||||
func GetSHA512HashCode(stringMessage string) string {
|
||||
message := []byte(stringMessage) //字符串转化字节数组
|
||||
//创建一个基于SHA256算法的hash.Hash接口的对象
|
||||
hash := sha512.New() //SHA-512加密
|
||||
//输入数据
|
||||
hash.Write(message)
|
||||
//计算哈希值
|
||||
bytes := hash.Sum(nil)
|
||||
//将字符串编码为16进制格式,返回字符串
|
||||
hashCode := hex.EncodeToString(bytes)
|
||||
//返回哈希值
|
||||
return hashCode
|
||||
}
|
||||
37
lib/pair/pair.go
Normal file
37
lib/pair/pair.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package pair
|
||||
|
||||
type Pair struct {
|
||||
Key int
|
||||
Value int
|
||||
}
|
||||
|
||||
type PairList []Pair
|
||||
|
||||
type Interface interface {
|
||||
// Len is the number of elements in the collection.
|
||||
Len() int
|
||||
|
||||
// Less reports whether the element with index i
|
||||
// must sort before the element with index j.
|
||||
//
|
||||
// If both Less(i, j) and Less(j, i) are false,
|
||||
// then the elements at index i and j are considered equal.
|
||||
// Sort may place equal elements in any order in the final result,
|
||||
// while Stable preserves the original input order of equal elements.
|
||||
//
|
||||
// Less must describe a transitive ordering:
|
||||
// - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
|
||||
// - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
|
||||
//
|
||||
// Note that floating-point comparison (the < operator on float32 or float64 values)
|
||||
// is not a transitive ordering when not-a-number (NaN) values are involved.
|
||||
// See Float64Slice.Less for a correct implementation for floating-point values.
|
||||
Less(i, j int) bool
|
||||
|
||||
// Swap swaps the elements with indexes i and j.
|
||||
Swap(i, j int)
|
||||
}
|
||||
|
||||
func (p PairList) Len() int { return len(p) }
|
||||
func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value }
|
||||
func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
252
lib/routes/routes.go
Normal file
252
lib/routes/routes.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
// "log"
|
||||
|
||||
"ems.agt/features/aaaa"
|
||||
"ems.agt/features/cm"
|
||||
"ems.agt/features/dbrest"
|
||||
"ems.agt/features/file"
|
||||
"ems.agt/features/fm"
|
||||
"ems.agt/features/maintenance"
|
||||
"ems.agt/features/mml"
|
||||
"ems.agt/features/nbi"
|
||||
"ems.agt/features/pm"
|
||||
"ems.agt/features/security"
|
||||
"ems.agt/features/state"
|
||||
"ems.agt/features/trace"
|
||||
"ems.agt/lib/midware"
|
||||
"ems.agt/lib/services"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
Method string
|
||||
Pattern string
|
||||
Handler http.HandlerFunc
|
||||
Middleware mux.MiddlewareFunc
|
||||
}
|
||||
|
||||
var routers []Router
|
||||
|
||||
// var (
|
||||
// commonUriPattern = config.UriPrefix + "/{apiCategory}/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
|
||||
|
||||
// getUriPattern = config.UriPrefix + "/resourceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/{objectTypeValue}"
|
||||
// getStatePattern = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/systemState"
|
||||
|
||||
// // // database management rest pattern, discard
|
||||
// // XormGetDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/elementType/{databaseName}/objectType/{tableName}"
|
||||
// // XormSelectDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/select/{databaseName}/{tableName}"
|
||||
// // XormInsertDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/insert/{databaseName}/{tableName}"
|
||||
// // XormUpdateDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/update/{databaseName}/{tableName}"
|
||||
// // XormDeleteDataUri = config.UriPrefix + "/databaseManagement/{apiVersion}/delete/{databaseName}/{tableName}"
|
||||
|
||||
// // XormCommonUri = config.UriPrefix + "/databaseManagement/{apiVersion}/{databaseName}/{tableName}"
|
||||
|
||||
// // alarm management
|
||||
// postAlarmPattern = config.UriPrefix + "/faultManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/alarms"
|
||||
|
||||
// // performance management
|
||||
// postPerformancePattern = config.UriPrefix + "/performanceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/kpiReport/{index}"
|
||||
// measureTaskUri = config.UriPrefix + "/performanceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/measureTask"
|
||||
// measureReportUri = config.UriPrefix + "/performanceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/measureReport"
|
||||
|
||||
// // parameter config management
|
||||
// paramConfigUri = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/config/{paraName}"
|
||||
|
||||
// // NE info
|
||||
// UriNeInfo = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/neInfo"
|
||||
// )
|
||||
|
||||
func init() {
|
||||
Register("POST", security.UriOauthToken, security.LoginFromOMC, nil)
|
||||
Register("POST", security.UriOauthHandshake, security.HandshakeFromOMC, nil)
|
||||
Register("DELETE", security.UriOauthToken, security.LogoutFromOMC, nil)
|
||||
|
||||
Register("OPTIONS", security.UriOauthToken, OptionsProc, nil)
|
||||
Register("OPTIONS", security.UriOauthHandshake, OptionsProc, nil)
|
||||
|
||||
// System state
|
||||
Register("GET", state.UriSysState, state.GetStateFromNF, nil)
|
||||
Register("OPTIONS", state.UriSysState, OptionsProc, nil)
|
||||
Register("GET", state.UriSysState2, state.GetStateFromNF, nil)
|
||||
Register("OPTIONS", state.UriSysState, OptionsProc, nil)
|
||||
Register("OPTIONS", state.UriSysState2, OptionsProc, nil)
|
||||
|
||||
Register("GET", state.UriSysInfoAll, state.GetAllSysinfoFromNF, nil)
|
||||
Register("GET", state.UriSysInfoOne, state.GetOneSysinfoFromNF, nil)
|
||||
Register("OPTIONS", state.UriSysInfoAll, OptionsProc, nil)
|
||||
Register("OPTIONS", state.UriSysInfoOne, OptionsProc, nil)
|
||||
|
||||
Register("GET", state.UriLicenseInfoAll, state.GetAllLicenseInfoFromNF, nil)
|
||||
Register("GET", state.UriLicenseInfoOne, state.GetOneLicenseInfoFromNF, nil)
|
||||
Register("OPTIONS", state.UriLicenseInfoAll, OptionsProc, nil)
|
||||
Register("OPTIONS", state.UriLicenseInfoOne, OptionsProc, nil)
|
||||
|
||||
// database management
|
||||
Register("GET", dbrest.XormGetDataUri, dbrest.DatabaseGetData, nil)
|
||||
Register("GET", dbrest.XormSelectDataUri, dbrest.DatabaseGetData, nil)
|
||||
Register("POST", dbrest.XormInsertDataUri, dbrest.DatabaseInsertData, nil)
|
||||
Register("PUT", dbrest.XormUpdateDataUri, dbrest.DatabaseUpdateData, nil)
|
||||
Register("DELETE", dbrest.XormDeleteDataUri, dbrest.DatabaseDeleteData, nil)
|
||||
// corss orgin domain
|
||||
Register("OPTIONS", dbrest.XormGetDataUri, OptionsProc, nil)
|
||||
Register("OPTIONS", dbrest.XormSelectDataUri, OptionsProc, nil)
|
||||
Register("OPTIONS", dbrest.XormInsertDataUri, OptionsProc, nil)
|
||||
Register("OPTIONS", dbrest.XormUpdateDataUri, OptionsProc, nil)
|
||||
Register("OPTIONS", dbrest.XormDeleteDataUri, OptionsProc, nil)
|
||||
|
||||
Register("GET", dbrest.XormCommonUri, dbrest.DatabaseGetData, nil)
|
||||
Register("POST", dbrest.XormCommonUri, dbrest.DatabaseInsertData, nil)
|
||||
Register("PUT", dbrest.XormCommonUri, dbrest.DatabaseUpdateData, nil)
|
||||
Register("DELETE", dbrest.XormCommonUri, dbrest.DatabaseDeleteData, nil)
|
||||
|
||||
Register("GET", dbrest.XormExtDataUri, dbrest.ExtDatabaseGetData, nil)
|
||||
Register("POST", dbrest.XormExtDataUri, dbrest.ExtDatabaseInsertData, nil)
|
||||
Register("PUT", dbrest.XormExtDataUri, dbrest.ExtDatabaseUpdateData, nil)
|
||||
Register("DELETE", dbrest.XormExtDataUri, dbrest.ExtDatabaseDeleteData, nil)
|
||||
|
||||
// corss orgin domain
|
||||
Register("OPTIONS", dbrest.XormInsertDataUri, OptionsProc, nil)
|
||||
Register("OPTIONS", dbrest.XormUpdateDataUri, OptionsProc, nil)
|
||||
Register("OPTIONS", dbrest.XormDeleteDataUri, OptionsProc, nil)
|
||||
|
||||
Register("OPTIONS", dbrest.XormCommonUri, OptionsProc, nil)
|
||||
|
||||
// alarm restful Register
|
||||
Register("POST", fm.UriAlarms, fm.PostAlarmFromNF, nil)
|
||||
Register("Get", fm.UriAlarms, fm.GetAlarmFromNF, nil)
|
||||
|
||||
Register("OPTIONS", fm.UriAlarms, OptionsProc, nil)
|
||||
|
||||
// performance restful Register
|
||||
Register("POST", pm.PostPerformancePattern, pm.PostKPIReportFromNF, nil)
|
||||
Register("POST", pm.MeasureTaskUri, pm.PostMeasureTaskToNF, nil)
|
||||
Register("PUT", pm.MeasureTaskUri, pm.PutMeasureTaskToNF, nil)
|
||||
Register("DELETE", pm.MeasureTaskUri, pm.DeleteMeasureTaskToNF, nil)
|
||||
Register("PATCH", pm.MeasureTaskUri, pm.PatchMeasureTaskToNF, nil)
|
||||
Register("POST", pm.MeasureReportUri, pm.PostMeasureReportFromNF, nil)
|
||||
|
||||
Register("POST", pm.MeasurementUri, pm.PostMeasurementFromNF, nil)
|
||||
Register("GET", pm.MeasurementUri, pm.GetMeasurementFromNF, nil)
|
||||
|
||||
Register("OPTIONS", pm.MeasureTaskUri, OptionsProc, nil)
|
||||
|
||||
// parameter config management
|
||||
Register("GET", cm.ParamConfigUri, cm.GetParamConfigFromNF, nil)
|
||||
Register("POST", cm.ParamConfigUri, cm.PostParamConfigToNF, nil)
|
||||
Register("PUT", cm.ParamConfigUri, cm.PutParamConfigToNF, nil)
|
||||
Register("DELETE", cm.ParamConfigUri, cm.DeleteParamConfigToNF, nil)
|
||||
|
||||
Register("OPTIONS", cm.ParamConfigUri, OptionsProc, nil)
|
||||
|
||||
// Get/Create/Modify/Delete NE info
|
||||
Register("GET", cm.UriNeInfo, cm.GetNeInfo, nil)
|
||||
Register("POST", cm.UriNeInfo, cm.PostNeInfo, nil)
|
||||
Register("PUT", cm.UriNeInfo, cm.PutNeInfo, nil)
|
||||
Register("DELETE", cm.UriNeInfo, cm.DeleteNeInfo, nil)
|
||||
Register("OPTIONS", cm.UriNeInfo, OptionsProc, nil)
|
||||
|
||||
// Post MML command to NF
|
||||
Register("POST", mml.UriMML, mml.PostMMLToNF, nil)
|
||||
Register("OPTIONS", mml.UriMML, OptionsProc, nil)
|
||||
|
||||
Register("POST", mml.UriOmMmlExt, mml.PostMMLToOMC, nil)
|
||||
Register("OPTIONS", mml.UriOmMmlExt, OptionsProc, nil)
|
||||
// Northbound Get NRM
|
||||
Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
|
||||
// Import/Export NF CM
|
||||
Register("GET", cm.NeCmUri, cm.ExportCmFromNF, nil)
|
||||
Register("POST", cm.NeCmUri, cm.ImportCmToNF, nil)
|
||||
|
||||
Register("OPTIONS", cm.NeCmUri, OptionsProc, nil)
|
||||
|
||||
Register("GET", cm.UriNeCmFile, cm.DownloadNeBackupFile, nil)
|
||||
Register("DELETE", cm.UriNeCmFile, cm.DeleteNeBackupFile, nil)
|
||||
|
||||
Register("OPTIONS", cm.UriNeCmFile, OptionsProc, nil)
|
||||
|
||||
// Software management
|
||||
Register("GET", cm.UriSoftware, cm.DownloadSoftwareFile, nil)
|
||||
Register("POST", cm.UriSoftware, cm.UploadSoftwareFile, nil)
|
||||
Register("DELETE", cm.UriSoftware, cm.DeleteSoftwareFile, nil)
|
||||
|
||||
Register("OPTIONS", cm.UriSoftware, OptionsProc, nil)
|
||||
|
||||
Register("POST", cm.UriSoftwareNE, cm.DistributeSoftwareToNF, nil)
|
||||
Register("PUT", cm.UriSoftwareNE, cm.ActiveSoftwareToNF, nil)
|
||||
Register("PATCH", cm.UriSoftwareNE, cm.RollBackSoftwareToNF, nil)
|
||||
|
||||
Register("OPTIONS", cm.UriSoftwareNE, OptionsProc, nil)
|
||||
|
||||
// License management
|
||||
Register("GET", cm.LicenseUri, cm.ExportCmFromNF, nil)
|
||||
Register("POST", cm.LicenseUri, cm.ImportCmToNF, nil)
|
||||
Register("DELETE", cm.LicenseUri, cm.ImportCmToNF, nil)
|
||||
|
||||
Register("OPTIONS", cm.LicenseUri, OptionsProc, nil)
|
||||
|
||||
Register("POST", cm.NeLicenseUri, cm.ExportCmFromNF, nil)
|
||||
Register("PUT", cm.NeLicenseUri, cm.ImportCmToNF, nil)
|
||||
Register("PATCH", cm.NeLicenseUri, cm.ImportCmToNF, nil)
|
||||
|
||||
Register("OPTIONS", cm.NeLicenseUri, OptionsProc, nil)
|
||||
|
||||
// Trace management
|
||||
Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, nil)
|
||||
Register("PUT", trace.UriTraceTask, trace.PutTraceTaskToNF, nil)
|
||||
Register("DELETE", trace.UriTraceTask, trace.DeleteTraceTaskToNF, nil)
|
||||
Register("OPTIONS", trace.UriTraceTask, OptionsProc, nil)
|
||||
// file management
|
||||
Register("POST", file.UriFile, file.UploadFile, nil)
|
||||
Register("GET", file.UriFile, file.DownloadFile, nil)
|
||||
Register("DELETE", file.UriFile, file.DeleteFile, nil)
|
||||
Register("OPTIONS", file.UriFile, OptionsProc, nil)
|
||||
|
||||
// AAAA
|
||||
Register("GET", aaaa.UriAAAASSO, aaaa.GetSSOFromAAAA, nil)
|
||||
|
||||
// 系统维护
|
||||
Register("GET", maintenance.Uri, maintenance.List, nil)
|
||||
Register("GET", maintenance.UriPref, maintenance.Pref, nil)
|
||||
Register("GET", maintenance.UriPrefLog, maintenance.PrefLog, nil)
|
||||
Register("GET", maintenance.UriSqlClient, maintenance.SqlClient, nil)
|
||||
Register("GET", maintenance.UriTop, maintenance.Top, nil)
|
||||
Register("PATCH", maintenance.UriTop, maintenance.TopOps, nil)
|
||||
|
||||
}
|
||||
|
||||
// To resolv rest POST/PUT/DELETE/PATCH cross domain
|
||||
func OptionsProc(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
func NewRouter() *mux.Router {
|
||||
r := mux.NewRouter()
|
||||
|
||||
// set custom handle for status 404/405
|
||||
r.NotFoundHandler = services.CustomResponseNotFound404Handler()
|
||||
r.MethodNotAllowedHandler = services.CustomResponseMethodNotAllowed405Handler()
|
||||
|
||||
r.Use(midware.LoggerTraceMiddleware)
|
||||
|
||||
for _, router := range routers {
|
||||
r.Methods(router.Method).
|
||||
Path(router.Pattern).
|
||||
Handler(router.Handler)
|
||||
if router.Middleware != nil {
|
||||
r.Use(router.Middleware)
|
||||
}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func Register(method, pattern string, handler http.HandlerFunc, middleware mux.MiddlewareFunc) {
|
||||
routers = append(routers, Router{method, pattern, handler, middleware})
|
||||
}
|
||||
356
lib/services/file.go
Normal file
356
lib/services/file.go
Normal file
@@ -0,0 +1,356 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"ems.agt/lib/log"
|
||||
)
|
||||
|
||||
const (
|
||||
RootPath = "uploads/"
|
||||
ChunkRootPath = "uploads_tmp/"
|
||||
)
|
||||
|
||||
var (
|
||||
// FilesMax 限制上传文件的大小为7 MB
|
||||
FilesMax int64 = 32 << 20
|
||||
// ValuesMax 限制POST字段内容的大小
|
||||
ValuesMax int64 = 512
|
||||
)
|
||||
|
||||
func GetPostFile(w http.ResponseWriter, r *http.Request) {
|
||||
//获取文件流,第三个返回值是错误对象
|
||||
file, header, _ := r.FormFile("file")
|
||||
//读取文件流为[]byte
|
||||
b, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
log.Error("Failed to ReadAll:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
//把文件保存到指定位置
|
||||
err = ioutil.WriteFile("./upload/test.zip", b, 0644)
|
||||
if err != nil {
|
||||
log.Error("Failed to WriteFile:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
//输出上传时文件名
|
||||
log.Debug("filename:", header.Filename)
|
||||
}
|
||||
|
||||
func GetUploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("GetUploadFile processing...")
|
||||
|
||||
file, err := os.Create("./test.zip")
|
||||
if err != nil {
|
||||
log.Error("Failed to Create:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
_, err = io.Copy(file, r.Body)
|
||||
if err != nil {
|
||||
log.Error("Failed to Copy:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func GetUploadFormFile(w http.ResponseWriter, r *http.Request) {
|
||||
// 设置最大的内存限制为32MB
|
||||
r.ParseMultipartForm(32 << 20)
|
||||
file, handler, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
log.Error("Failed to FormFile:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
log.Debug("Header:%v", handler.Header)
|
||||
f, err := os.OpenFile("./"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
|
||||
if err != nil {
|
||||
log.Error("Failed to OpenFile:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = io.Copy(f, file)
|
||||
if err != nil {
|
||||
log.Error("Failed to Copy:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Debug("File uploaded successfully:", handler.Filename)
|
||||
}
|
||||
|
||||
func HandleUploadFile(r *http.Request, path, newFileName string) (string, error) {
|
||||
var filePath, fileName string
|
||||
reader, err := r.MultipartReader()
|
||||
if err != nil {
|
||||
log.Error("Failed to MultipartReader:", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
for {
|
||||
part, err := reader.NextPart()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Error("Failed to NextPart:", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Debugf("FileName=[%s], FormName=[%s]", part.FileName(), part.FormName())
|
||||
if part.FileName() == "" { // this is FormData
|
||||
data, _ := ioutil.ReadAll(part)
|
||||
log.Debugf("FormData=[%s]", string(data))
|
||||
} else { // This is FileData
|
||||
|
||||
if newFileName != "" {
|
||||
fileName = newFileName
|
||||
} else {
|
||||
fileName = part.FileName()
|
||||
}
|
||||
|
||||
err := os.MkdirAll(path, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Error("Failed to Mkdir:", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
filePath = path + "/" + fileName
|
||||
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
log.Error("Failed to Create:", err)
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, part)
|
||||
if err != nil {
|
||||
log.Error("Failed to Copy:", err)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileName, nil
|
||||
}
|
||||
|
||||
func HandleUploadFormFile(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseMultipartForm(32 << 20)
|
||||
//mForm := r.MultipartForm
|
||||
|
||||
for k, _ := range r.MultipartForm.File {
|
||||
// k is the key of file part
|
||||
file, fileHeader, err := r.FormFile(k)
|
||||
if err != nil {
|
||||
fmt.Println("inovke FormFile error:", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
fmt.Printf("the uploaded file: name[%s], size[%d], header[%#v]\n",
|
||||
fileHeader.Filename, fileHeader.Size, fileHeader.Header)
|
||||
|
||||
// store uploaded file into local path
|
||||
localFileName := "./upload/" + fileHeader.Filename
|
||||
out, err := os.Create(localFileName)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to open the file %s for writing", localFileName)
|
||||
return
|
||||
}
|
||||
defer out.Close()
|
||||
_, err = io.Copy(out, file)
|
||||
if err != nil {
|
||||
fmt.Printf("copy file err:%s\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("file %s uploaded ok\n", fileHeader.Filename)
|
||||
}
|
||||
}
|
||||
|
||||
func PostFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("PostFileHandler processing... ")
|
||||
if !strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data") {
|
||||
// 不支持的 Content-Type 类型
|
||||
fmt.Println("Invalid Content-Type: ", r.Header.Get("Content-Type"))
|
||||
http.Error(w, " 不支持的 Content-Type 类型", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// 整个请求的主体大小设置为7.5Mb
|
||||
r.Body = http.MaxBytesReader(w, r.Body, FilesMax+ValuesMax)
|
||||
reader, err := r.MultipartReader()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
// A Part represents a single part in a multipart body.
|
||||
part, err := reader.NextPart()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
fileName := part.FileName()
|
||||
formName := part.FormName()
|
||||
var buf = &bytes.Buffer{}
|
||||
// 非文件字段部分大小限制验证(非文件字段,go中filename会是空)
|
||||
if fileName == "" {
|
||||
var limitError = "请求主体中非文件字段" + formName + "超出大小限制"
|
||||
err = uploadSizeLimit(buf, part, ValuesMax, limitError)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// 文件字段部分大小限制验证
|
||||
var limitError = "请求主体中文件字段" + fileName + "超出大小限制"
|
||||
err = uploadSizeLimit(buf, part, FilesMax, limitError)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// 文件创建部分
|
||||
if err := uploadFileHandle(r.Header, fileName, buf); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// 非逻辑内容,仅为测试使用
|
||||
var chunkNumber = r.Header.Get("chunk-number")
|
||||
if chunkNumber == "" {
|
||||
http.Error(w, "文件"+fileName+"上传成功", http.StatusOK)
|
||||
} else {
|
||||
http.Error(w, "分片文件"+fileName+chunkNumber+"上传成功", http.StatusOK)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
// 上传内容大小限制
|
||||
func uploadSizeLimit(buf *bytes.Buffer, part *multipart.Part, maxLimit int64, limitError string) error {
|
||||
n, err := io.CopyN(buf, part, maxLimit+1)
|
||||
if err != nil && err != io.EOF {
|
||||
fmt.Println("PostFileHandler:", err)
|
||||
return err
|
||||
}
|
||||
maxLimit -= n
|
||||
if maxLimit < 0 {
|
||||
return errors.New(limitError)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// uploadFileHandle handle upload file
|
||||
func uploadFileHandle(header http.Header, fileName string, buf *bytes.Buffer) error {
|
||||
var chunkNumberStr = header.Get("chunk-number")
|
||||
// 1.普通文件上传处理
|
||||
if chunkNumberStr == "" {
|
||||
//创建文件并写入文件内容
|
||||
return createFile(RootPath+fileName, buf.Bytes())
|
||||
}
|
||||
// 2.分片文件上传处理
|
||||
//2.1读取分片编号
|
||||
chunkNumber, err := strconv.Atoi(chunkNumberStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//2.2创建分片文件并写入分片内容
|
||||
if err := createFile(fmt.Sprintf(ChunkRootPath+fileName+"%d.chunk", chunkNumber), buf.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
//2.3确认是否上传完毕
|
||||
if header.Get("chunk-final") == "true" {
|
||||
//2.4合并文件
|
||||
if err := mergeChunkFiles(fileName); err != nil {
|
||||
return err
|
||||
}
|
||||
//2.5删除分片
|
||||
for i := 0; ; i++ {
|
||||
chunFileName := fmt.Sprintf(ChunkRootPath+fileName+"%d.chunk", i)
|
||||
err := os.Remove(chunFileName)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 创建文件并写入内容
|
||||
func createFile(fileName string, res []byte) error {
|
||||
newFile, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = newFile.Close()
|
||||
}()
|
||||
bufferedWriter := bufio.NewWriter(newFile)
|
||||
_, err = bufferedWriter.Write(res)
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
return bufferedWriter.Flush()
|
||||
}
|
||||
|
||||
// 合并分片文件
|
||||
func mergeChunkFiles(fileName string) error {
|
||||
var (
|
||||
n int64
|
||||
err error
|
||||
)
|
||||
finalFile, err := os.Create(RootPath + fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer finalFile.Close()
|
||||
// 将分片内容写入最终文件
|
||||
for i := 0; ; i++ {
|
||||
chunFile, err := os.Open(fmt.Sprintf(ChunkRootPath+fileName+"%d.chunk", i))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
n, err = io.Copy(finalFile, chunFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = chunFile.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n < 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
45
lib/services/requset.go
Normal file
45
lib/services/requset.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"ems.agt/lib/global"
|
||||
)
|
||||
|
||||
// 读取json请求结构团体
|
||||
func JSONBody(r *http.Request, args any) error {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(body, args)
|
||||
return err
|
||||
}
|
||||
|
||||
// Get 查詢分頁值
|
||||
func GetPageNumSize(r *http.Request) (int, int) {
|
||||
pageNumStr := r.URL.Query().Get("pageNum")
|
||||
num := 1
|
||||
if v, err := strconv.Atoi(pageNumStr); err == nil && v > 0 {
|
||||
if v >= 100 {
|
||||
num = 100
|
||||
} else {
|
||||
num = v
|
||||
}
|
||||
}
|
||||
|
||||
pageSizeStr := r.URL.Query().Get("pageSize")
|
||||
size := 0
|
||||
if v, err := strconv.Atoi(pageSizeStr); err == nil && v > 0 {
|
||||
if v >= 60 {
|
||||
size = 60
|
||||
} else {
|
||||
size = v
|
||||
}
|
||||
}
|
||||
|
||||
return num, size
|
||||
}
|
||||
936
lib/services/services.go
Normal file
936
lib/services/services.go
Normal file
@@ -0,0 +1,936 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
// "log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"ems.agt/lib/dborm"
|
||||
"ems.agt/lib/global"
|
||||
"ems.agt/lib/log"
|
||||
"ems.agt/lib/oauth"
|
||||
"ems.agt/restagent/config"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type NameValue struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type NameOid struct {
|
||||
Name string
|
||||
Oid string
|
||||
}
|
||||
|
||||
type DataResponse struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type NullResponse struct {
|
||||
nil interface{}
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
Error interface{} `json:"error"`
|
||||
}
|
||||
|
||||
type ErrorMessage struct {
|
||||
ErrorCode string `json:"errorCode"`
|
||||
ErrorInfo string `json:"errorInfo"`
|
||||
}
|
||||
|
||||
type SucceedOAuthResponse struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
Expires string `json:"expires"`
|
||||
// Enum: "0": 不需要修改密码, "1": "FirstLogin",首次登录, "2": PasswordAboutToExpire, 密码即将过期
|
||||
ChangePasswordFlag int `json:"changePasswordFlag"`
|
||||
GroupName string `json:"groupName"`
|
||||
}
|
||||
|
||||
type ServiceResponse struct {
|
||||
}
|
||||
|
||||
func GetUriParamString(r *http.Request, paramName string, sep string, brackets bool, apostr bool) string {
|
||||
vars := r.URL.Query()
|
||||
s, ok := vars[paramName]
|
||||
if !ok {
|
||||
log.Infof("Parameter Name is not exist, %s", paramName)
|
||||
return ""
|
||||
}
|
||||
if apostr {
|
||||
for i := 0; i < len(s); i++ {
|
||||
s[i] = "'" + s[i] + "'"
|
||||
}
|
||||
}
|
||||
pn := strings.Join(s, sep)
|
||||
if brackets {
|
||||
pn = fmt.Sprintf("(%s)", pn)
|
||||
}
|
||||
|
||||
return pn
|
||||
}
|
||||
|
||||
func GetUriWhereString(r *http.Request) string {
|
||||
return GetUriParamString(r, "WHERE", " and ", false, false)
|
||||
}
|
||||
|
||||
func GetUriLocString(r *http.Request) string {
|
||||
return GetUriParamString(r, "loc", " and ", false, false)
|
||||
}
|
||||
|
||||
func GetUriPageLimitString(r *http.Request) string {
|
||||
vars := r.URL.Query()
|
||||
p, ok := vars["PAGE"]
|
||||
if !ok {
|
||||
log.Info("page param is not exist")
|
||||
return ""
|
||||
}
|
||||
|
||||
l, ok := vars["LIMIT"]
|
||||
if !ok {
|
||||
log.Info("limit param is not exist")
|
||||
return ""
|
||||
}
|
||||
li, _ := strconv.Atoi(l[0])
|
||||
pi, _ := strconv.Atoi(p[0])
|
||||
ls := fmt.Sprintf("limit %d, %d", li*(pi-1), li)
|
||||
|
||||
log.Debug("Limit array:", ls)
|
||||
return ls
|
||||
}
|
||||
|
||||
func ExtGetUriPageLimitString(r *http.Request) string {
|
||||
vars := r.URL.Query()
|
||||
p, ok := vars["page"]
|
||||
if !ok {
|
||||
log.Info("page param is not exist")
|
||||
p = append(p, "1")
|
||||
}
|
||||
|
||||
l, ok := vars["limit"]
|
||||
if !ok {
|
||||
log.Info("limit param is not exist")
|
||||
l = append(l, strconv.Itoa(global.MaxLimitData))
|
||||
}
|
||||
limit, _ := strconv.Atoi(l[0])
|
||||
if limit > global.MaxLimitData {
|
||||
limit = global.MaxLimitData
|
||||
}
|
||||
page, _ := strconv.Atoi(p[0])
|
||||
limitStr := fmt.Sprintf("limit %d, %d", limit*(page-1), limit)
|
||||
|
||||
log.Debug("limitStr:", limitStr)
|
||||
return limitStr
|
||||
}
|
||||
|
||||
func IsJsonContentType(r *http.Request) bool {
|
||||
if strings.Contains(r.Header.Get("Content-Type"), "application/json") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsValidOAuthUri(r *http.Request) bool {
|
||||
vars := mux.Vars(r)
|
||||
apiVer := vars["apiVersion"] // 获取Uri
|
||||
if apiVer != "v1" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func IsVallidContentType(r *http.Request, checkFlag bool) bool {
|
||||
log.Debug("IsVallidContentType processing ...")
|
||||
/*
|
||||
ctype := r.Header["Content-Type"]
|
||||
log.Debug("ctype:", ctype)
|
||||
if len(ctype) != 0 && !strings.Contains(ctype[0], "application/json") {
|
||||
return false
|
||||
}
|
||||
*/
|
||||
if strings.Contains(r.Header.Get("Content-Type"), "application/json") || checkFlag == false {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func CheckParameterName(r *http.Request) []string {
|
||||
var errorParams []string
|
||||
vars := r.URL.Query()
|
||||
for k, v := range vars {
|
||||
log.Debug("vars:", k, v)
|
||||
if k != "rmUIDs" && k != "fields" {
|
||||
errorParams = append(errorParams, k)
|
||||
}
|
||||
}
|
||||
|
||||
return errorParams
|
||||
}
|
||||
|
||||
func GetRmUIDArr(r *http.Request) []string {
|
||||
vars := r.URL.Query()
|
||||
rmUIDs, ok := vars["rmUIDs"]
|
||||
if !ok {
|
||||
log.Info("rmUIDs is not exist")
|
||||
return nil
|
||||
}
|
||||
|
||||
var rmUIDValues []string
|
||||
for _, r := range rmUIDs {
|
||||
if r != "" {
|
||||
rmUIDValues = global.MergeStringArr(rmUIDValues, strings.Split(r, `,`))
|
||||
}
|
||||
}
|
||||
|
||||
return rmUIDValues
|
||||
}
|
||||
|
||||
func GetAttrNameArr(r *http.Request) []string {
|
||||
vars := r.URL.Query()
|
||||
fields, ok := vars["fields"]
|
||||
if !ok {
|
||||
log.Info("attributeNames does not exist")
|
||||
return nil
|
||||
}
|
||||
var attrNames []string
|
||||
for _, a := range fields {
|
||||
if a != "" {
|
||||
attrNames = global.MergeStringArr(attrNames, strings.Split(a, `,`))
|
||||
}
|
||||
}
|
||||
|
||||
return attrNames
|
||||
}
|
||||
|
||||
func CheckValidRmUID(rmUIDs []string) []string {
|
||||
log.Debug("CheckValidRmUID processing... ")
|
||||
|
||||
var invalidRmUIDs []string
|
||||
for _, r := range rmUIDs {
|
||||
if !global.MatchRmUID(config.GetRmUIDRegexpFromConfig(), r) {
|
||||
invalidRmUIDs = append(invalidRmUIDs, r)
|
||||
}
|
||||
}
|
||||
|
||||
return invalidRmUIDs
|
||||
}
|
||||
|
||||
func CheckLocalRmUID(rmUIDs []string) string {
|
||||
log.Debug("GetLocalRmUID processing... ")
|
||||
|
||||
rmUID := config.GetRmUIDFromConfig()
|
||||
for _, r := range rmUIDs {
|
||||
if r == rmUID {
|
||||
return rmUID
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetParamsArrByName(paramName string, r *http.Request) []string {
|
||||
vars := r.URL.Query()
|
||||
pns, ok := vars[paramName]
|
||||
if !ok {
|
||||
log.Infof("%s is not exist", paramName)
|
||||
return nil
|
||||
}
|
||||
|
||||
var pnArr []string
|
||||
for _, pn := range pns {
|
||||
if pn != "" {
|
||||
pnArr = global.MergeStringArr(pnArr, strings.Split(pn, `,`))
|
||||
}
|
||||
}
|
||||
|
||||
return pnArr
|
||||
}
|
||||
|
||||
func GetOperationTypeFromHttpRequest(r *http.Request) string {
|
||||
for k, v := range r.Header {
|
||||
log.Tracef("k:%s, v:%s", k, v)
|
||||
if strings.ToLower(k) == "operationtype" && len(v) != 0 {
|
||||
log.Trace("OperationType:", v[0])
|
||||
return v[0]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func CheckNorthboundValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||
log.Debug("CheckNorthboundValidRequest processing... ")
|
||||
|
||||
var token string = ""
|
||||
var err error
|
||||
var ret bool
|
||||
// response 414-4 uri too long ? (optional)
|
||||
// todo ... ?
|
||||
if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
|
||||
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
|
||||
ResponseRequestURITooLong414UriTooLong(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
// response 415-1
|
||||
if !IsJsonContentType(r) {
|
||||
log.Error("Invalid Content-Type")
|
||||
ResponseUnsupportedMediaType415(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
token, ret = oauth.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
log.Error("AccessToken is not carried")
|
||||
ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// 401-2 response
|
||||
if dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) == false {
|
||||
log.Error("AccessToken fails or does not exist")
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
|
||||
_, err = dborm.XormUpdateSessionShakeTime(token)
|
||||
if err != nil {
|
||||
log.Error("Failed to update session table:", err)
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != global.ApiVersionV1 {
|
||||
log.Error("Uri is invalid")
|
||||
ResponseNotFound404UriNotExist(w, r)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// response 406-1
|
||||
rmUIDValues := GetRmUIDArr(r)
|
||||
if rmUIDValues == nil {
|
||||
log.Error("missing parameter: rmUIDs")
|
||||
ResponseNotAcceptable406MissingParam(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// response 406-2
|
||||
errorParams := CheckParameterName(r)
|
||||
if errorParams != nil {
|
||||
log.Error("parameter name error: ", errorParams)
|
||||
ResponseNotAcceptable406ParamError(w, errorParams)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// response 400-5
|
||||
if len(rmUIDValues) == 0 {
|
||||
log.Error("rmUIDs is wrong or NULL")
|
||||
ResponseBadRequest400WrongParamValue(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// response 414-1
|
||||
if len(rmUIDValues) > config.GetYamlConfig().Params.RmUIDMaxNum {
|
||||
log.Error("rmUID greater than", config.GetYamlConfig().Params.RmUIDMaxNum)
|
||||
ResponseRequestURITooLong414NRMNumExceed(w, config.GetYamlConfig().Params.RmUIDMaxNum)
|
||||
return token, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func CheckCommonValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||
log.Debug("CheckCommonValidRequest processing... ")
|
||||
|
||||
var token string = ""
|
||||
var err error
|
||||
var ret bool
|
||||
// response 414-4 uri too long ? (optional)
|
||||
// todo ... ?
|
||||
if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
|
||||
log.Error("Request Uri too long:", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
|
||||
ResponseRequestURITooLong414UriTooLong(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// check media type(content type) only support "application/json"
|
||||
// response 415-1
|
||||
if !IsJsonContentType(r) {
|
||||
log.Error("Invalid Content-Type")
|
||||
ResponseUnsupportedMediaType415(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
token, ret = oauth.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
log.Error("AccessToken is not carried")
|
||||
ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// 401-2 response
|
||||
if dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) == false {
|
||||
log.Error("AccessToken fails or does not exist")
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
|
||||
_, err = dborm.XormUpdateSessionShakeTime(token)
|
||||
if err != nil {
|
||||
log.Error("Failed to update session table:", err)
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != global.ApiVersionV1 {
|
||||
log.Error("Uri is invalid")
|
||||
ResponseNotFound404UriNotExist(w, r)
|
||||
return token, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func IsLocalhost(host string) bool {
|
||||
if strings.Contains(host, "127.0.0.1") || strings.Contains(host, "::1") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func CheckFrontValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||
log.Debug("CheckFrontValidRequest processing... ")
|
||||
|
||||
var token string = ""
|
||||
var err error
|
||||
var ret bool
|
||||
// response 414-4 uri too long ? (optional)
|
||||
// todo ... ?
|
||||
if bytes.Count([]byte(r.RequestURI), nil) > config.GetUriMaxLenFromConfig() {
|
||||
err = errors.New("Request Uri too long")
|
||||
log.Errorf("Request Uri too long: bytes=%d, MaxLen=%d", bytes.Count([]byte(r.RequestURI), nil), config.GetUriMaxLenFromConfig())
|
||||
ResponseRequestURITooLong414UriTooLong(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
/*
|
||||
// check media type(content type) only support "application/json"
|
||||
// response 415-1
|
||||
if !IsVallidContentType(r) {
|
||||
err := errors.New("Invalid Content-Type")
|
||||
log.Error(err)
|
||||
ResponseUnsupportedMediaType415(w)
|
||||
return err
|
||||
}
|
||||
*/
|
||||
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
if config.GetYamlConfig().Auth.Token && IsLocalhost(r.RemoteAddr) == false {
|
||||
token, ret = oauth.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
err = errors.New("AccessToken is not carried")
|
||||
log.Error(err)
|
||||
ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// 401-2 response
|
||||
if dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) == false {
|
||||
err = errors.New("AccessToken fails or does not exist")
|
||||
log.Error(err)
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
|
||||
_, err = dborm.XormUpdateSessionShakeTime(token)
|
||||
if err != nil {
|
||||
log.Error("Failed to update session table:", err)
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
// response 403 Forbidden, permissions deny
|
||||
// todo...
|
||||
plist := globalSession.GetPermissionFromSession(token)
|
||||
log.Debug("permission list:", plist)
|
||||
if len(plist) == 0 || plist[0] == false {
|
||||
log.Debug("User permission deny")
|
||||
ResponseForbidden403NotPermission(w)
|
||||
return
|
||||
}
|
||||
*/
|
||||
vars := mux.Vars(r)
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != global.ApiVersionV1 {
|
||||
err = errors.New("Uri is invalid")
|
||||
log.Error(err)
|
||||
ResponseNotFound404UriNotExist(w, r)
|
||||
return token, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func CheckExtValidRequest(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||
log.Debug("CheckExtValidRequest processing... ")
|
||||
|
||||
var token string = ""
|
||||
var err error
|
||||
var ret bool
|
||||
// error processing ...
|
||||
// 401-1 response
|
||||
if config.GetYamlConfig().Auth.Token {
|
||||
token, ret = oauth.IsCarriedToken(r)
|
||||
if ret == false {
|
||||
err = errors.New("AccessToken is not carried")
|
||||
log.Error(err)
|
||||
ResponseUnauthorized401AccessTokenNotCarried(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// 401-2 response
|
||||
if dborm.XormExistValidToken(token, config.GetExpiresFromConfig()) == false {
|
||||
err = errors.New("AccessToken fails or does not exist")
|
||||
log.Error(err)
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
|
||||
if operType := GetOperationTypeFromHttpRequest(r); operType != "auto" {
|
||||
_, err = dborm.XormUpdateSessionShakeTime(token)
|
||||
if err != nil {
|
||||
log.Error("Failed to update session table:", err)
|
||||
ResponseUnauthorized401AccessTokenNotExist(w)
|
||||
return token, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != global.ApiVersionV1 {
|
||||
err = errors.New("Uri is invalid")
|
||||
log.Error(err)
|
||||
ResponseNotFound404UriNotExist(w, r)
|
||||
return token, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func ResponseStatusOK200Login(w http.ResponseWriter, token string, user *dborm.User) {
|
||||
var oAuthResponse SucceedOAuthResponse
|
||||
oAuthResponse.AccessToken = token
|
||||
oAuthResponse.Expires = strconv.Itoa((int)(config.GetExpiresFromConfig()))
|
||||
oAuthResponse.ChangePasswordFlag = user.ChangePasswordFlag
|
||||
oAuthResponse.GroupName = user.GroupName
|
||||
ResponseWithJson(w, http.StatusOK, oAuthResponse)
|
||||
}
|
||||
|
||||
func ResponseStatusOK200Null(w http.ResponseWriter) {
|
||||
response := NullResponse{""}
|
||||
ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func ResponseStatusOK204NoContent(w http.ResponseWriter) {
|
||||
ResponseWithJson(w, http.StatusNoContent, "")
|
||||
}
|
||||
|
||||
func ResponseRedirect(w http.ResponseWriter, redirectUrl string) {
|
||||
w.Header().Set("Cache-Control", "must-revalidate, no-store")
|
||||
w.Header().Set("Content-Type", " text/html;charset=UTF-8")
|
||||
w.Header().Set("Location", redirectUrl) //跳转地址设置
|
||||
w.WriteHeader(http.StatusTemporaryRedirect) //重定向!
|
||||
}
|
||||
|
||||
func ResponseBadRequest400RmUIDsIsInvalid(w http.ResponseWriter, rmUIDs []string) {
|
||||
errorMessage := ErrorMessage{"1", "rmUIDs is invalid:" + strings.Join(rmUIDs, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseBadRequest400DuplicateSubId(w http.ResponseWriter, SubIds string) {
|
||||
errorMessage := ErrorMessage{"2", "Duplicate with resource subscription id:" + SubIds}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseBadRequest400DuplicateAlarmId(w http.ResponseWriter, AlarmIds string) {
|
||||
errorMessage := ErrorMessage{"3", "Duplicate with alarm subscription id: " + AlarmIds}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseBadRequest400IncorrectLogin(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"4", "Incorrect username and password"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseBadRequest400WrongParamValue(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"5", "Wrong parameter value"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseBadRequest400CMCALoginError(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"6", "CMCA centralized authentication login error"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseBadRequest400InvalidJson(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"7", "Invalid json format"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusUnauthorized, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseUnauthorized401AccessTokenNotCarried(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"1", "AccessToken is not carried"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusUnauthorized, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseUnauthorized401AccessTokenNotExist(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"2", "AccessToken fails or does not exist"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusUnauthorized, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseForbidden403NotPermission(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"1", "Do not have the operation permissions"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusForbidden, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseForbidden403MultiLoginNotAllowed(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"2", "Multiple logins are not allowed"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusForbidden, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404UriNotExist(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := ErrorMessage{"1", "The requested URI does not exist"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404UriNotExistExt(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"1", "The requested URI does not exist"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func CustomResponseNotFound404Handler() http.Handler {
|
||||
return http.HandlerFunc(ResponseNotFound404UriNotExist)
|
||||
}
|
||||
|
||||
func ResponseNotFound404NRMNotExist(w http.ResponseWriter, rmUIDs []string) {
|
||||
errorMessage := ErrorMessage{"2", "rmUIDs does not exist: " + strings.Join(rmUIDs, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404PMNotExist(w http.ResponseWriter, rmUIDs []string) {
|
||||
errorMessage := ErrorMessage{"3", "rmUIDs does not exist: " + strings.Join(rmUIDs, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404AlarmNotExist(w http.ResponseWriter, AlarmIds []string) {
|
||||
errorMessage := ErrorMessage{"4", "AlarmIds does not exist: " + strings.Join(AlarmIds, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404GetSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
|
||||
errorMessage := ErrorMessage{"5", "Subscription id does not exist: " + strings.Join(SubIds, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404DeleteSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
|
||||
errorMessage := ErrorMessage{"6", "Subscription id does not exist: " + strings.Join(SubIds, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404GetAlarmSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
|
||||
errorMessage := ErrorMessage{"7", "Subscription id does not exist: " + strings.Join(SubIds, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotFound404DeleteAlarmSubscriptionNotExist(w http.ResponseWriter, SubIds []string) {
|
||||
errorMessage := ErrorMessage{"8", "Subscription id does not exist: " + strings.Join(SubIds, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotFound, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseMethodNotAllowed405(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := ErrorMessage{"1", "Method not allowed"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusMethodNotAllowed, errorResponse)
|
||||
}
|
||||
|
||||
func CustomResponseMethodNotAllowed405Handler() http.Handler {
|
||||
return http.HandlerFunc(ResponseMethodNotAllowed405)
|
||||
}
|
||||
|
||||
func ResponseNotAcceptable406MissingParam(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"1", "Missing parameter: rmUIDs"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotAcceptable, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotAcceptable406ParamError(w http.ResponseWriter, errorParamsName []string) {
|
||||
errorMessage := ErrorMessage{"2", "Parameter name error: " + strings.Join(errorParamsName, ",")}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotAcceptable, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseNotAcceptable406QuerySQLError(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"3", "Wrong or non-query SQL statement"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusNotAcceptable, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseRequestEntityTooLarge413SubscriptionExceed(w http.ResponseWriter, num int) {
|
||||
errorMessage := ErrorMessage{"1", "The number of subscriptions greater than " + strconv.Itoa(num)}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusRequestEntityTooLarge, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseRequestEntityTooLarge413BodyToLarge(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"2", "The request entity too large"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusRequestEntityTooLarge, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseRequestURITooLong414NRMNumExceed(w http.ResponseWriter, num int) {
|
||||
errorMessage := ErrorMessage{"1", "The number of NRM rmUIDs greater than " + strconv.Itoa(num)}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseRequestURITooLong414AlarmNumExceed(w http.ResponseWriter, num int) {
|
||||
errorMessage := ErrorMessage{"2", "The number of alarmIds greater than " + strconv.Itoa(num)}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseRequestURITooLong414PMNumExceed(w http.ResponseWriter, num int) {
|
||||
errorMessage := ErrorMessage{"3", "The number of PM rmUIDs greater than " + strconv.Itoa(num)}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseRequestURITooLong414UriTooLong(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"3", "Request URI too long"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusRequestURITooLong, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseUnsupportedMediaType415(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"1", "Unsupported media type"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusUnsupportedMediaType, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseInternalServerError500NFConnectRefused(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"1", "Internal server error, NF connnect refused"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusInternalServerError, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseInternalServerError500DatabaseOperationFailed(w http.ResponseWriter) {
|
||||
errorMessage := ErrorMessage{"2", "Internal server error, database opration failed"}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusInternalServerError, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseInternalServerError500ProcessError(w http.ResponseWriter, err error) {
|
||||
em := fmt.Sprintf("Internal server error: %v", err)
|
||||
errorMessage := ErrorMessage{"3", em}
|
||||
errorResponse := ErrorResponse{errorMessage}
|
||||
ResponseWithJson(w, http.StatusInternalServerError, errorResponse)
|
||||
}
|
||||
|
||||
func ResponseWithJson(w http.ResponseWriter, code int, payload interface{}) {
|
||||
log.Trace("payload: ", payload)
|
||||
|
||||
response, _ := json.Marshal(payload)
|
||||
SetResponseHeader(w)
|
||||
w.WriteHeader(code)
|
||||
w.Write(response)
|
||||
log.Trace("Response Code:", code)
|
||||
log.Trace("Response Body:", string(response))
|
||||
}
|
||||
|
||||
func ResponseWithZip(w http.ResponseWriter, payload interface{}) {
|
||||
response, _ := json.Marshal(payload)
|
||||
SetResponseHeader(w)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(response)
|
||||
log.Trace("Response Body:", string(response))
|
||||
}
|
||||
|
||||
func TransportResponse(w http.ResponseWriter, code int, payload []byte) {
|
||||
var tempBody, transBody interface{}
|
||||
switch code {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
json.Unmarshal(payload, &tempBody)
|
||||
transBody = DataResponse{tempBody}
|
||||
default:
|
||||
json.Unmarshal(payload, &tempBody)
|
||||
transBody = ErrorResponse{tempBody}
|
||||
}
|
||||
response, _ := json.Marshal(transBody)
|
||||
log.Trace("transBody: ", transBody)
|
||||
SetResponseHeader(w)
|
||||
w.WriteHeader(code)
|
||||
w.Write(response)
|
||||
log.Trace("response: ", string(response))
|
||||
}
|
||||
|
||||
func ResponseWithUnsortJson(w http.ResponseWriter, code int, payload map[string]interface{}) {
|
||||
var om global.OrderedMap
|
||||
om.Map = payload
|
||||
response, _ := om.MarshalJson()
|
||||
log.Trace("payload: ", payload)
|
||||
SetResponseHeader(w)
|
||||
w.WriteHeader(code)
|
||||
w.Write(response)
|
||||
log.Trace("response: ", string(response))
|
||||
}
|
||||
|
||||
func ResponseErrorWithJson(w http.ResponseWriter, code int, nameValue interface{}) {
|
||||
response := make(map[string]interface{})
|
||||
response["error"] = nameValue
|
||||
ResponseWithJson(w, code, response)
|
||||
}
|
||||
|
||||
func SetCommonResponseHeader(w http.ResponseWriter) {
|
||||
// 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")
|
||||
}
|
||||
|
||||
func SetResponseHeader(w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||
SetCommonResponseHeader(w)
|
||||
}
|
||||
|
||||
// Creates a new file upload http request with optional extra params
|
||||
func ResponseUploadFile(w http.ResponseWriter, code int, params map[string]string, paramName, path string) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to open: %v", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
part, err := writer.CreateFormFile(paramName, filepath.Base(path))
|
||||
if err != nil {
|
||||
log.Error("Failed to CreateFormFile:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
_, err = io.Copy(part, file)
|
||||
if err != nil {
|
||||
log.Error("Failed to Copy:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
for key, val := range params {
|
||||
_ = writer.WriteField(key, val)
|
||||
}
|
||||
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
log.Error("Failed to Close:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
SetCommonResponseHeader(w)
|
||||
w.Header().Set("Content-Type", writer.FormDataContentType())
|
||||
w.WriteHeader(code)
|
||||
w.Write(body.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
func ResponseFile(w http.ResponseWriter, code int, filePath string) {
|
||||
fileBytes, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
log.Error("Failed to ReadFile:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
SetCommonResponseHeader(w)
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.WriteHeader(code)
|
||||
w.Write(fileBytes)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func ResponseFileWithNameAndMD5(w http.ResponseWriter, code int, fileName, path, md5Sum string) {
|
||||
filePath := path + "/" + fileName
|
||||
fileBytes, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
log.Error("Failed to ReadFile:", err)
|
||||
ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
SetCommonResponseHeader(w)
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("User-File", fileName)
|
||||
w.Header().Set("MD5-Sum", md5Sum)
|
||||
w.WriteHeader(code)
|
||||
w.Write(fileBytes)
|
||||
|
||||
return
|
||||
}
|
||||
169
lib/session/session.go
Normal file
169
lib/session/session.go
Normal file
@@ -0,0 +1,169 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"ems.agt/lib/log"
|
||||
"ems.agt/lib/oauth"
|
||||
"ems.agt/restagent/config"
|
||||
)
|
||||
|
||||
// SessionMgr session manager
|
||||
type SessManager struct {
|
||||
name string
|
||||
expires int64
|
||||
lock sync.RWMutex
|
||||
sessions map[string]*Session
|
||||
}
|
||||
|
||||
// Session
|
||||
type Session struct {
|
||||
token string
|
||||
time time.Time
|
||||
permission []bool
|
||||
values map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewSessionMgr create session manager
|
||||
func NewSessManager(name string) *SessManager {
|
||||
smgr := &SessManager{name: name, expires: (int64)(config.GetExpiresFromConfig()), sessions: make(map[string]*Session)}
|
||||
go smgr.SessionGC()
|
||||
return smgr
|
||||
}
|
||||
|
||||
// NewSession create session
|
||||
func (smgr *SessManager) NewSession(w http.ResponseWriter, r *http.Request, plist []bool) string {
|
||||
smgr.lock.Lock()
|
||||
defer smgr.lock.Unlock()
|
||||
token := oauth.GenRandToken() // Generate new token to session ID
|
||||
session := &Session{token: token, time: time.Now(), permission: plist, values: make(map[interface{}]interface{})}
|
||||
smgr.sessions[token] = session
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
// EndSession
|
||||
func (smgr *SessManager) EndSession(w http.ResponseWriter, r *http.Request) {
|
||||
token := smgr.GetTokenFromHttpRequest(r)
|
||||
|
||||
smgr.lock.Lock()
|
||||
defer smgr.lock.Unlock()
|
||||
delete(smgr.sessions, token)
|
||||
}
|
||||
|
||||
// Handshake session, restart session
|
||||
func (smgr *SessManager) ShakeSession(token string) bool {
|
||||
|
||||
smgr.lock.Lock()
|
||||
defer smgr.lock.Unlock()
|
||||
for _, s := range smgr.sessions {
|
||||
if token == s.token {
|
||||
log.Debug("session time:", s.time)
|
||||
s.time = time.Now()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// EndSessionByID end the session by session ID
|
||||
func (smgr *SessManager) DeleteSession(token string) {
|
||||
smgr.lock.Lock()
|
||||
defer smgr.lock.Unlock()
|
||||
delete(smgr.sessions, token)
|
||||
}
|
||||
|
||||
// SetSessionValue set value fo session
|
||||
func (smgr *SessManager) SetSessionValue(token string, key interface{}, value interface{}) error {
|
||||
smgr.lock.Lock()
|
||||
defer smgr.lock.Unlock()
|
||||
if session, ok := smgr.sessions[token]; ok {
|
||||
session.values[key] = value
|
||||
return nil
|
||||
}
|
||||
return errors.New("invalid session ID")
|
||||
}
|
||||
|
||||
// GetSessionValue get value fo session
|
||||
func (smgr *SessManager) GetSessionValue(token string, key interface{}) (interface{}, error) {
|
||||
smgr.lock.RLock()
|
||||
defer smgr.lock.RUnlock()
|
||||
if session, ok := smgr.sessions[token]; ok {
|
||||
if val, ok := session.values[key]; ok {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("invalid session ID")
|
||||
}
|
||||
|
||||
func (smgr *SessManager) GetTokenFromHttpRequest(r *http.Request) string {
|
||||
for k, v := range r.Header {
|
||||
if strings.ToLower(k) == "accesstoken" && len(v) != 0 {
|
||||
log.Debug("AccessToken:", v[0])
|
||||
return v[0]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsValidToken check token is valid or not
|
||||
func (smgr *SessManager) IsValidToken(token string) bool {
|
||||
|
||||
smgr.lock.Lock()
|
||||
defer smgr.lock.Unlock()
|
||||
if _, ok := smgr.sessions[token]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCarriedToken check token is carried
|
||||
func (smgr *SessManager) IsCarriedToken(r *http.Request) (string, bool) {
|
||||
|
||||
token := smgr.GetTokenFromHttpRequest(r)
|
||||
if token == "" {
|
||||
return "", false
|
||||
}
|
||||
return token, true
|
||||
}
|
||||
|
||||
// GetPermissionFromSession get permission from session by token
|
||||
func (smgr *SessManager) GetPermissionFromSession(token string) []bool {
|
||||
|
||||
if s, ok := smgr.sessions[token]; ok {
|
||||
return s.permission
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SessionGC maintain session
|
||||
func (smgr *SessManager) SessionGC() {
|
||||
smgr.lock.Lock()
|
||||
defer smgr.lock.Unlock()
|
||||
for token, session := range smgr.sessions {
|
||||
if session.time.Unix()+smgr.expires < time.Now().Unix() {
|
||||
delete(smgr.sessions, token)
|
||||
}
|
||||
}
|
||||
|
||||
time.AfterFunc(time.Duration(smgr.expires)*time.Second, func() { smgr.SessionGC() })
|
||||
}
|
||||
|
||||
// NewSessionID generate unique ID
|
||||
func (smgr *SessManager) NewSessionID() string {
|
||||
b := make([]byte, 32)
|
||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||||
nano := time.Now().UnixNano()
|
||||
return strconv.FormatInt(nano, 10)
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(b)
|
||||
}
|
||||
45
lib/websocket/client.go
Normal file
45
lib/websocket/client.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
ID string
|
||||
Socket *websocket.Conn
|
||||
Msg chan []byte
|
||||
}
|
||||
|
||||
func NewWsClient(ID string, socket *websocket.Conn) *Client {
|
||||
return &Client{
|
||||
ID: ID,
|
||||
Socket: socket,
|
||||
Msg: make(chan []byte, 100),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Read() {
|
||||
defer func() {
|
||||
close(c.Msg)
|
||||
}()
|
||||
for {
|
||||
_, message, err := c.Socket.ReadMessage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ProcessData(c, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Write() {
|
||||
defer func() {
|
||||
c.Socket.Close()
|
||||
}()
|
||||
for {
|
||||
message, ok := <-c.Msg
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_ = c.Socket.WriteMessage(websocket.TextMessage, message)
|
||||
}
|
||||
}
|
||||
405
lib/websocket/process_data.go
Normal file
405
lib/websocket/process_data.go
Normal file
@@ -0,0 +1,405 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"ems.agt/lib/cache"
|
||||
"ems.agt/lib/log"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
)
|
||||
|
||||
type WsInput struct {
|
||||
Type string `json:"type"`
|
||||
DownloadProgress
|
||||
PsProcessConfig
|
||||
SSHSessionConfig
|
||||
NetConfig
|
||||
}
|
||||
|
||||
type DownloadProgress struct {
|
||||
Keys []string `json:"keys"`
|
||||
}
|
||||
|
||||
type PsProcessConfig struct {
|
||||
Pid int32 `json:"pid"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type SSHSessionConfig struct {
|
||||
LoginUser string `json:"loginUser"`
|
||||
LoginIP string `json:"loginIP"`
|
||||
}
|
||||
|
||||
type NetConfig struct {
|
||||
Port uint32 `json:"port"`
|
||||
ProcessName string `json:"processName"`
|
||||
ProcessID int32 `json:"processID"`
|
||||
}
|
||||
|
||||
type PsProcessData struct {
|
||||
PID int32 `json:"PID"`
|
||||
Name string `json:"name"`
|
||||
PPID int32 `json:"PPID"`
|
||||
Username string `json:"username"`
|
||||
Status string `json:"status"`
|
||||
StartTime string `json:"startTime"`
|
||||
NumThreads int32 `json:"numThreads"`
|
||||
NumConnections int `json:"numConnections"`
|
||||
CpuPercent string `json:"cpuPercent"`
|
||||
|
||||
DiskRead string `json:"diskRead"`
|
||||
DiskWrite string `json:"diskWrite"`
|
||||
CmdLine string `json:"cmdLine"`
|
||||
|
||||
Rss string `json:"rss"`
|
||||
VMS string `json:"vms"`
|
||||
HWM string `json:"hwm"`
|
||||
Data string `json:"data"`
|
||||
Stack string `json:"stack"`
|
||||
Locked string `json:"locked"`
|
||||
Swap string `json:"swap"`
|
||||
|
||||
CpuValue float64 `json:"cpuValue"`
|
||||
RssValue uint64 `json:"rssValue"`
|
||||
|
||||
Envs []string `json:"envs"`
|
||||
|
||||
OpenFiles []process.OpenFilesStat `json:"openFiles"`
|
||||
Connects []processConnect `json:"connects"`
|
||||
}
|
||||
|
||||
type processConnect struct {
|
||||
Type string `json:"type"`
|
||||
Status string `json:"status"`
|
||||
Laddr net.Addr `json:"localaddr"`
|
||||
Raddr net.Addr `json:"remoteaddr"`
|
||||
PID int32 `json:"PID"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ProcessConnects []processConnect
|
||||
|
||||
func (p ProcessConnects) Len() int {
|
||||
return len(p)
|
||||
}
|
||||
|
||||
func (p ProcessConnects) Less(i, j int) bool {
|
||||
return p[i].PID < p[j].PID
|
||||
}
|
||||
|
||||
func (p ProcessConnects) Swap(i, j int) {
|
||||
p[i], p[j] = p[j], p[i]
|
||||
}
|
||||
|
||||
type sshSession struct {
|
||||
Username string `json:"username"`
|
||||
PID int32 `json:"PID"`
|
||||
Terminal string `json:"terminal"`
|
||||
Host string `json:"host"`
|
||||
LoginTime string `json:"loginTime"`
|
||||
}
|
||||
|
||||
func ProcessData(c *Client, inputMsg []byte) {
|
||||
wsInput := &WsInput{}
|
||||
err := json.Unmarshal(inputMsg, wsInput)
|
||||
if err != nil {
|
||||
log.Errorf("unmarshal wsInput error,err %s", err.Error())
|
||||
return
|
||||
}
|
||||
switch wsInput.Type {
|
||||
case "wget":
|
||||
res, err := getDownloadProcess(wsInput.DownloadProgress)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
case "ps":
|
||||
res, err := getProcessData(wsInput.PsProcessConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
case "ssh":
|
||||
res, err := getSSHSessions(wsInput.SSHSessionConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
case "net":
|
||||
res, err := getNetConnections(wsInput.NetConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type Process struct {
|
||||
Total uint64 `json:"total"`
|
||||
Written uint64 `json:"written"`
|
||||
Percent float64 `json:"percent"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func getDownloadProcess(progress DownloadProgress) (res []byte, err error) {
|
||||
var result []Process
|
||||
for _, k := range progress.Keys {
|
||||
value, err := cache.CACHE.Get(k)
|
||||
if err != nil {
|
||||
log.Errorf("get cache error,err %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
downloadProcess := &Process{}
|
||||
_ = json.Unmarshal(value, downloadProcess)
|
||||
result = append(result, *downloadProcess)
|
||||
}
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
|
||||
const (
|
||||
b = uint64(1)
|
||||
kb = 1024 * b
|
||||
mb = 1024 * kb
|
||||
gb = 1024 * mb
|
||||
)
|
||||
|
||||
func formatBytes(bytes uint64) string {
|
||||
switch {
|
||||
case bytes < kb:
|
||||
return fmt.Sprintf("%dB", bytes)
|
||||
case bytes < mb:
|
||||
return fmt.Sprintf("%.2fKB", float64(bytes)/float64(kb))
|
||||
case bytes < gb:
|
||||
return fmt.Sprintf("%.2fMB", float64(bytes)/float64(mb))
|
||||
default:
|
||||
return fmt.Sprintf("%.2fGB", float64(bytes)/float64(gb))
|
||||
}
|
||||
}
|
||||
|
||||
func getProcessData(processConfig PsProcessConfig) (res []byte, err error) {
|
||||
var processes []*process.Process
|
||||
processes, err = process.Processes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
result []PsProcessData
|
||||
resultMutex sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
numWorkers = 4
|
||||
)
|
||||
|
||||
handleData := func(proc *process.Process) {
|
||||
procData := PsProcessData{
|
||||
PID: proc.Pid,
|
||||
}
|
||||
if processConfig.Pid > 0 && processConfig.Pid != proc.Pid {
|
||||
return
|
||||
}
|
||||
if procName, err := proc.Name(); err == nil {
|
||||
procData.Name = procName
|
||||
} else {
|
||||
procData.Name = "<UNKNOWN>"
|
||||
}
|
||||
if processConfig.Name != "" && !strings.Contains(procData.Name, processConfig.Name) {
|
||||
return
|
||||
}
|
||||
if username, err := proc.Username(); err == nil {
|
||||
procData.Username = username
|
||||
}
|
||||
if processConfig.Username != "" && !strings.Contains(procData.Username, processConfig.Username) {
|
||||
return
|
||||
}
|
||||
procData.PPID, _ = proc.Ppid()
|
||||
statusArray, _ := proc.Status()
|
||||
if len(statusArray) > 0 {
|
||||
procData.Status = strings.Join(statusArray, ",")
|
||||
}
|
||||
createTime, procErr := proc.CreateTime()
|
||||
if procErr == nil {
|
||||
t := time.Unix(createTime/1000, 0)
|
||||
procData.StartTime = t.Format("2006-1-2 15:04:05")
|
||||
}
|
||||
procData.NumThreads, _ = proc.NumThreads()
|
||||
connections, procErr := proc.Connections()
|
||||
if procErr == nil {
|
||||
procData.NumConnections = len(connections)
|
||||
for _, conn := range connections {
|
||||
if conn.Laddr.IP != "" || conn.Raddr.IP != "" {
|
||||
procData.Connects = append(procData.Connects, processConnect{
|
||||
Status: conn.Status,
|
||||
Laddr: conn.Laddr,
|
||||
Raddr: conn.Raddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
procData.CpuValue, _ = proc.CPUPercent()
|
||||
procData.CpuPercent = fmt.Sprintf("%.2f", procData.CpuValue) + "%"
|
||||
menInfo, procErr := proc.MemoryInfo()
|
||||
if procErr == nil {
|
||||
procData.Rss = formatBytes(menInfo.RSS)
|
||||
procData.RssValue = menInfo.RSS
|
||||
procData.Data = formatBytes(menInfo.Data)
|
||||
procData.VMS = formatBytes(menInfo.VMS)
|
||||
procData.HWM = formatBytes(menInfo.HWM)
|
||||
procData.Stack = formatBytes(menInfo.Stack)
|
||||
procData.Locked = formatBytes(menInfo.Locked)
|
||||
procData.Swap = formatBytes(menInfo.Swap)
|
||||
} else {
|
||||
procData.Rss = "--"
|
||||
procData.Data = "--"
|
||||
procData.VMS = "--"
|
||||
procData.HWM = "--"
|
||||
procData.Stack = "--"
|
||||
procData.Locked = "--"
|
||||
procData.Swap = "--"
|
||||
|
||||
procData.RssValue = 0
|
||||
}
|
||||
ioStat, procErr := proc.IOCounters()
|
||||
if procErr == nil {
|
||||
procData.DiskWrite = formatBytes(ioStat.WriteBytes)
|
||||
procData.DiskRead = formatBytes(ioStat.ReadBytes)
|
||||
} else {
|
||||
procData.DiskWrite = "--"
|
||||
procData.DiskRead = "--"
|
||||
}
|
||||
procData.CmdLine, _ = proc.Cmdline()
|
||||
procData.OpenFiles, _ = proc.OpenFiles()
|
||||
procData.Envs, _ = proc.Environ()
|
||||
|
||||
resultMutex.Lock()
|
||||
result = append(result, procData)
|
||||
resultMutex.Unlock()
|
||||
}
|
||||
|
||||
chunkSize := (len(processes) + numWorkers - 1) / numWorkers
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
wg.Add(1)
|
||||
start := i * chunkSize
|
||||
end := (i + 1) * chunkSize
|
||||
if end > len(processes) {
|
||||
end = len(processes)
|
||||
}
|
||||
|
||||
go func(start, end int) {
|
||||
defer wg.Done()
|
||||
for j := start; j < end; j++ {
|
||||
handleData(processes[j])
|
||||
}
|
||||
}(start, end)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].PID < result[j].PID
|
||||
})
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
|
||||
func getSSHSessions(config SSHSessionConfig) (res []byte, err error) {
|
||||
var (
|
||||
result []sshSession
|
||||
users []host.UserStat
|
||||
processes []*process.Process
|
||||
)
|
||||
processes, err = process.Processes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users, err = host.Users()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, proc := range processes {
|
||||
name, _ := proc.Name()
|
||||
if name != "sshd" || proc.Pid == 0 {
|
||||
continue
|
||||
}
|
||||
connections, _ := proc.Connections()
|
||||
for _, conn := range connections {
|
||||
for _, user := range users {
|
||||
if user.Host == "" {
|
||||
continue
|
||||
}
|
||||
if conn.Raddr.IP == user.Host {
|
||||
if config.LoginUser != "" && !strings.Contains(user.User, config.LoginUser) {
|
||||
continue
|
||||
}
|
||||
if config.LoginIP != "" && !strings.Contains(user.Host, config.LoginIP) {
|
||||
continue
|
||||
}
|
||||
if terminal, err := proc.Cmdline(); err == nil {
|
||||
if strings.Contains(terminal, user.Terminal) {
|
||||
session := sshSession{
|
||||
Username: user.User,
|
||||
Host: user.Host,
|
||||
Terminal: user.Terminal,
|
||||
PID: proc.Pid,
|
||||
}
|
||||
t := time.Unix(int64(user.Started), 0)
|
||||
session.LoginTime = t.Format("2006-1-2 15:04:05")
|
||||
result = append(result, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
|
||||
var netTypes = [...]string{"tcp", "udp"}
|
||||
|
||||
func getNetConnections(config NetConfig) (res []byte, err error) {
|
||||
var (
|
||||
result []processConnect
|
||||
proc *process.Process
|
||||
)
|
||||
for _, netType := range netTypes {
|
||||
connections, _ := net.Connections(netType)
|
||||
if err == nil {
|
||||
for _, conn := range connections {
|
||||
if config.ProcessID > 0 && config.ProcessID != conn.Pid {
|
||||
continue
|
||||
}
|
||||
proc, err = process.NewProcess(conn.Pid)
|
||||
if err == nil {
|
||||
name, _ := proc.Name()
|
||||
if name != "" && config.ProcessName != "" && !strings.Contains(name, config.ProcessName) {
|
||||
continue
|
||||
}
|
||||
if config.Port > 0 && config.Port != conn.Laddr.Port && config.Port != conn.Raddr.Port {
|
||||
continue
|
||||
}
|
||||
result = append(result, processConnect{
|
||||
Type: netType,
|
||||
Status: conn.Status,
|
||||
Laddr: conn.Laddr,
|
||||
Raddr: conn.Raddr,
|
||||
PID: conn.Pid,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user