|
@@ -10,18 +10,64 @@ import (
|
|
|
adminRep "github.com/go-nunu/nunu-layout-advanced/internal/repository/admin"
|
|
|
"github.com/go-nunu/nunu-layout-advanced/internal/repository/api/waf"
|
|
|
"github.com/go-nunu/nunu-layout-advanced/internal/service"
|
|
|
+ "github.com/go-nunu/nunu-layout-advanced/pkg/excel"
|
|
|
"github.com/go-nunu/nunu-layout-advanced/pkg/rabbitmq"
|
|
|
amqp "github.com/rabbitmq/amqp091-go"
|
|
|
"go.uber.org/zap"
|
|
|
+ "net/http"
|
|
|
"strings"
|
|
|
+ "time"
|
|
|
)
|
|
|
|
|
|
+// ApiDescriptionMap API描述映射
|
|
|
+var ApiDescriptionMap = map[string]string{
|
|
|
+ "/webForward/get": "获取web详情",
|
|
|
+ "/webForward/getList": "获取web列表",
|
|
|
+ "/webForward/add": "添加web",
|
|
|
+ "/webForward/edit": "修改web",
|
|
|
+ "/webForward/delete": "删除web",
|
|
|
+
|
|
|
+ "/tcpForward/add": "添加tcp",
|
|
|
+ "/tcpForward/edit": "修改tcp",
|
|
|
+ "/tcpForward/delete": "删除tcp",
|
|
|
+ "/tcpForward/getList": "获取tcp列表",
|
|
|
+ "/tcpForward/get": "获取tcp详情",
|
|
|
+
|
|
|
+ "/udpForward/add": "添加udp",
|
|
|
+ "/udpForward/edit": "修改udp",
|
|
|
+ "/udpForward/delete": "删除udp",
|
|
|
+ "/udpForward/getList": "获取udp列表",
|
|
|
+ "/udpForward/get": "获取udp详情",
|
|
|
+
|
|
|
+ "/globalLimit/add": "添加实例",
|
|
|
+ "/globalLimit/edit": "修改实例",
|
|
|
+ "/globalLimit/delete": "删除实例",
|
|
|
+
|
|
|
+ "/allowAndDeny/get": "获取黑白名单详情",
|
|
|
+ "/allowAndDeny/getList": "获取黑白名单列表",
|
|
|
+ "/allowAndDeny/add": "添加黑白名单",
|
|
|
+ "/allowAndDeny/edit": "修改黑白名单",
|
|
|
+ "/allowAndDeny/delete": "删除黑白名单",
|
|
|
+
|
|
|
+ "/cc/getList": "获取CC列表",
|
|
|
+ "/cc/editState": "删除CC黑名单",
|
|
|
+
|
|
|
+ "/ccIpList/getList": "获取CC白名单列表",
|
|
|
+ "/ccIpList/add": "添加CC白名单",
|
|
|
+ "/ccIpList/edit": "修改CC白名单",
|
|
|
+ "/ccIpList/delete": "删除CC白名单",
|
|
|
+
|
|
|
+ "分配网关组": "分配网关组",
|
|
|
+}
|
|
|
+
|
|
|
type WafLogService interface {
|
|
|
GetWafLog(ctx context.Context, id int64) (*model.WafLog, error)
|
|
|
GetWafLogList(ctx context.Context, req adminApi.SearchWafLogParams) (*v1.PaginatedResponse[model.WafLog], error)
|
|
|
AddWafLog(ctx context.Context, req adminApi.WafLog) error
|
|
|
BatchAddWafLog(ctx context.Context, reqs []*adminApi.WafLog) error
|
|
|
PublishIpWafLogTask(ctx context.Context, req adminApi.WafLog)
|
|
|
+ SmartExportWafLog(ctx context.Context, req adminApi.ExportWafLog, w http.ResponseWriter) error
|
|
|
+ GetApiDescriptions(ctx context.Context) map[string]string
|
|
|
}
|
|
|
func NewWafLogService(
|
|
|
service *service.Service,
|
|
@@ -43,48 +89,6 @@ type wafLogService struct {
|
|
|
globalLimitRepository waf.GlobalLimitRepository
|
|
|
mq *rabbitmq.RabbitMQ
|
|
|
}
|
|
|
-
|
|
|
-var ApiDescriptionMap = map[string]string{
|
|
|
-
|
|
|
- "/webForward/get": "获取web详情",
|
|
|
- "/webForward/getList" : "获取web列表",
|
|
|
- "/webForward/add" : "添加web",
|
|
|
- "/webForward/edit" : "修改web",
|
|
|
- "/webForward/delete" : "删除web",
|
|
|
-
|
|
|
- "/tcpForward/add" : "添加tcp",
|
|
|
- "/tcpForward/edit" : "修改tcp",
|
|
|
- "/tcpForward/delete" : "删除tcp",
|
|
|
- "/tcpForward/getList" : "获取tcp列表",
|
|
|
- "/tcpForward/get" : "获取tcp详情",
|
|
|
-
|
|
|
- "/udpForward/add" : "添加udp",
|
|
|
- "/udpForward/edit" : "修改udp",
|
|
|
- "/udpForward/delete" : "删除udp",
|
|
|
- "/udpForward/getList" : "获取udp列表",
|
|
|
- "/udpForward/get" : "获取udp详情",
|
|
|
-
|
|
|
- "/globalLimit/add" : "添加实例",
|
|
|
- "/globalLimit/edit" : "修改实例",
|
|
|
- "/globalLimit/delete" : "删除实例",
|
|
|
-
|
|
|
- "/allowAndDeny/get" : "获取黑白名单详情",
|
|
|
- "/allowAndDeny/getList" : "获取黑白名单列表",
|
|
|
- "/allowAndDeny/add" : "添加黑白名单",
|
|
|
- "/allowAndDeny/edit" : "修改黑白名单",
|
|
|
- "/allowAndDeny/delete" : "删除黑白名单",
|
|
|
-
|
|
|
- "/cc/getList" : "获取CC列表",
|
|
|
- "/cc/editState" : "删除CC黑名单",
|
|
|
-
|
|
|
- "/ccIpList/getList" : "获取CC白名单列表",
|
|
|
- "/ccIpList/add" : "添加CC白名单",
|
|
|
- "/ccIpList/edit" : "修改CC白名单",
|
|
|
- "/ccIpList/delete" : "删除CC白名单",
|
|
|
-
|
|
|
- "分配网关组" : "分配网关组",
|
|
|
-
|
|
|
-}
|
|
|
func (s *wafLogService) getFirstPathSegment(path string) (segment []string, ok bool) {
|
|
|
// 1. 为了统一处理,先去掉路径最前面的 "/"
|
|
|
// 这样 "/v1/admin" 会变成 "v1/admin",而 "v1/admin" 保持不变
|
|
@@ -247,30 +251,262 @@ func (s *wafLogService) PublishIpWafLogTask(ctx context.Context, req adminApi.Wa
|
|
|
}
|
|
|
|
|
|
func (s *wafLogService) ExPortWafLog(ctx context.Context, req adminApi.ExportWafLog) ([]adminApi.ExportWafLogRes, error) {
|
|
|
+ // 获取原始数据
|
|
|
data, err := s.wafLogRepository.ExportWafLog(ctx, req)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
+ // 使用优化后的转换方法,避免N+1查询
|
|
|
+ return s.convertRawDataToExportResults(ctx, data)
|
|
|
+}
|
|
|
+
|
|
|
+// SmartExportWafLog 智能导出WAF日志为Excel
|
|
|
+func (s *wafLogService) SmartExportWafLog(ctx context.Context, req adminApi.ExportWafLog, w http.ResponseWriter) error {
|
|
|
+ // 1. 先获取总数量用于智能选择传输方式
|
|
|
+ count, err := s.wafLogRepository.GetWafLogExportCount(ctx, req)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("获取导出数据总数失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 智能选择导出方式
|
|
|
+ // 估算每行数据大小约200字节(包含用户名、IP、API名称、域名等字段)
|
|
|
+ exportType := excel.SmartExport(count, 200)
|
|
|
+
|
|
|
+ // 3. 设置Excel表头映射
|
|
|
+ headers := []string{"name", "request_ip", "host_id", "api_name", "addr_backend_list", "domain", "comment", "custom_host", "expose_addr", "created_at"}
|
|
|
+ headerMap := map[string]string{
|
|
|
+ "name": "用户名",
|
|
|
+ "request_ip": "请求IP",
|
|
|
+ "host_id": "主机ID",
|
|
|
+ "api_name": "API名称",
|
|
|
+ "addr_backend_list": "后端地址",
|
|
|
+ "domain": "域名",
|
|
|
+ "comment": "备注",
|
|
|
+ "custom_host": "自定义主机",
|
|
|
+ "expose_addr": "暴露地址",
|
|
|
+ "created_at": "创建时间",
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 创建Excel生成器
|
|
|
+ generator := excel.NewExcelGenerator("WAF日志", headers, headerMap)
|
|
|
+ if err := generator.WriteHeaders(); err != nil {
|
|
|
+ return fmt.Errorf("写入Excel表头失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 根据导出类型选择不同的处理方式
|
|
|
+ switch exportType {
|
|
|
+ case excel.ExportTypeNormal:
|
|
|
+ return s.normalExportWafLog(ctx, req, generator, w)
|
|
|
+ case excel.ExportTypeStream:
|
|
|
+ return s.streamExportWafLog(ctx, req, generator, w)
|
|
|
+ case excel.ExportTypeChunk:
|
|
|
+ return s.chunkExportWafLog(ctx, req, w, count)
|
|
|
+ default:
|
|
|
+ return s.normalExportWafLog(ctx, req, generator, w)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// normalExportWafLog 普通导出(小文件)
|
|
|
+func (s *wafLogService) normalExportWafLog(ctx context.Context, req adminApi.ExportWafLog, generator *excel.ExcelGenerator, w http.ResponseWriter) error {
|
|
|
+ // 获取所有数据(已经优化了批量查询)
|
|
|
+ exportData, err := s.ExPortWafLog(ctx, req)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("获取导出数据失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换数据格式
|
|
|
+ data := make([]map[string]interface{}, 0, len(exportData))
|
|
|
+ for _, item := range exportData {
|
|
|
+ row := map[string]interface{}{
|
|
|
+ "name": item.Name,
|
|
|
+ "request_ip": item.RequestIp,
|
|
|
+ "host_id": item.HostId,
|
|
|
+ "api_name": item.ApiName,
|
|
|
+ "addr_backend_list": s.formatBackendList(item.AddrBackendList),
|
|
|
+ "domain": item.Domain,
|
|
|
+ "comment": item.Comment,
|
|
|
+ "custom_host": item.CustomHost,
|
|
|
+ "expose_addr": s.formatExposeAddr(item.ExposeAddr),
|
|
|
+ "created_at": item.CreatedAt,
|
|
|
+ }
|
|
|
+ data = append(data, row)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 写入数据
|
|
|
+ if err := generator.WriteRows(data); err != nil {
|
|
|
+ return fmt.Errorf("写入Excel数据失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 普通导出
|
|
|
+ fileName := fmt.Sprintf("waf_logs_%s.xlsx", time.Now().Format("20060102_150405"))
|
|
|
+ return excel.NormalExport(generator, w, excel.TransferOption{
|
|
|
+ FileName: fileName,
|
|
|
+ ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// streamExportWafLog 流式导出(大文件)
|
|
|
+func (s *wafLogService) streamExportWafLog(ctx context.Context, req adminApi.ExportWafLog, generator *excel.ExcelGenerator, w http.ResponseWriter) error {
|
|
|
+ fileName := fmt.Sprintf("waf_logs_%s.xlsx", time.Now().Format("20060102_150405"))
|
|
|
+
|
|
|
+ // 设置响应头
|
|
|
+ w.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
|
|
+ w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
|
|
|
+ w.Header().Set("Transfer-Encoding", "chunked")
|
|
|
+
|
|
|
+ // 分批处理数据,每批1000条
|
|
|
+ pageSize := 1000
|
|
|
+ page := 1
|
|
|
+
|
|
|
+ for {
|
|
|
+ // 使用分页导出方法
|
|
|
+ exportData, err := s.wafLogRepository.ExportWafLogWithPagination(ctx, req, page, pageSize)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("获取第%d页数据失败: %w", page, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换为导出格式(复用原有的ExPortWafLog逻辑)
|
|
|
+ exportResults, err := s.convertRawDataToExportResults(ctx, exportData)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("转换导出数据失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(exportResults) == 0 {
|
|
|
+ break // 没有更多数据
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换并写入当前批次数据
|
|
|
+ for _, item := range exportResults {
|
|
|
+ row := map[string]interface{}{
|
|
|
+ "name": item.Name,
|
|
|
+ "request_ip": item.RequestIp,
|
|
|
+ "host_id": item.HostId,
|
|
|
+ "api_name": item.ApiName,
|
|
|
+ "addr_backend_list": s.formatBackendList(item.AddrBackendList),
|
|
|
+ "domain": item.Domain,
|
|
|
+ "comment": item.Comment,
|
|
|
+ "custom_host": item.CustomHost,
|
|
|
+ "expose_addr": s.formatExposeAddr(item.ExposeAddr),
|
|
|
+ "created_at": item.CreatedAt,
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := generator.WriteRow(row); err != nil {
|
|
|
+ return fmt.Errorf("写入第%d页数据失败: %w", page, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果当前批次数据少于页大小,说明已经是最后一页
|
|
|
+ if len(exportResults) < pageSize {
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ page++
|
|
|
+ }
|
|
|
+
|
|
|
+ // 流式导出
|
|
|
+ return excel.StreamExport(generator, w, excel.TransferOption{
|
|
|
+ FileName: fileName,
|
|
|
+ ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// chunkExportWafLog 分块导出(超大文件)
|
|
|
+func (s *wafLogService) chunkExportWafLog(ctx context.Context, req adminApi.ExportWafLog, w http.ResponseWriter, totalRecords int) error {
|
|
|
+ fileName := fmt.Sprintf("waf_logs_%s.xlsx", time.Now().Format("20060102_150405"))
|
|
|
+ pageSize := 5000 // 每个分块5000条记录
|
|
|
+
|
|
|
+ // 分块导出需要前端配合实现
|
|
|
+ excel.ChunkExport(w, excel.TransferOption{
|
|
|
+ FileName: fileName,
|
|
|
+ ContentType: "application/json", // 返回分块信息
|
|
|
+ }, totalRecords, pageSize)
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// formatBackendList 格式化后端地址列表
|
|
|
+func (s *wafLogService) formatBackendList(backendList interface{}) string {
|
|
|
+ if backendList == nil {
|
|
|
+ return ""
|
|
|
+ }
|
|
|
+
|
|
|
+ switch v := backendList.(type) {
|
|
|
+ case string:
|
|
|
+ return v
|
|
|
+ case []string:
|
|
|
+ return strings.Join(v, ", ")
|
|
|
+ default:
|
|
|
+ return fmt.Sprintf("%v", v)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// formatExposeAddr 格式化暴露地址
|
|
|
+func (s *wafLogService) formatExposeAddr(exposeAddr []string) string {
|
|
|
+ if len(exposeAddr) == 0 {
|
|
|
+ return ""
|
|
|
+ }
|
|
|
+ return strings.Join(exposeAddr, ", ")
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// convertRawDataToExportResults 将原始数据转换为导出结果(复用原有的ExPortWafLog逻辑)
|
|
|
+func (s *wafLogService) convertRawDataToExportResults(ctx context.Context, rawData []model.WafLog) ([]adminApi.ExportWafLogRes, error) {
|
|
|
+ if len(rawData) == 0 {
|
|
|
+ return []adminApi.ExportWafLogRes{}, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ // 收集所有需要查询的hostId和uid,用于批量获取网关组
|
|
|
+ hostIds := make([]int64, 0, len(rawData))
|
|
|
+ uids := make([]int64, 0, len(rawData))
|
|
|
+ maxCreatedAt := time.Time{}
|
|
|
+
|
|
|
+ for _, v := range rawData {
|
|
|
+ hostIds = append(hostIds, int64(v.HostId))
|
|
|
+ uids = append(uids, int64(v.Uid))
|
|
|
+ if v.CreatedAt.After(maxCreatedAt) {
|
|
|
+ maxCreatedAt = v.CreatedAt
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量获取网关组数据
|
|
|
+ gatewayMap, err := s.wafLogRepository.BatchGetWafLogGateWayIps(ctx, hostIds, uids, maxCreatedAt)
|
|
|
+ if err != nil {
|
|
|
+ s.Logger.Warn("批量获取网关组失败,降级为单个查询", zap.Error(err))
|
|
|
+ gatewayMap = make(map[string]model.WafLog) // 空map,后续会降级处理
|
|
|
+ }
|
|
|
+
|
|
|
var res []adminApi.ExportWafLogRes
|
|
|
- for _, v := range data {
|
|
|
+ for _, v := range rawData {
|
|
|
var AddrBackendList interface{}
|
|
|
var customHost string
|
|
|
var port string
|
|
|
var domain string
|
|
|
var comment string
|
|
|
|
|
|
-
|
|
|
var mapData map[string]interface{}
|
|
|
err := json.Unmarshal(v.ExtraData, &mapData)
|
|
|
if err != nil {
|
|
|
- return nil, err
|
|
|
+ // 尝试解析为数组格式
|
|
|
+ var arrayData []interface{}
|
|
|
+ if arrayErr := json.Unmarshal(v.ExtraData, &arrayData); arrayErr != nil {
|
|
|
+ // 如果不是符合的JSON格式,直接把原始值作为字符串处理
|
|
|
+ s.Logger.Warn("额外数据不是有效JSON格式,使用原始值", zap.Error(err), zap.Int("id", v.Id),
|
|
|
+ zap.String("extra_data", string(v.ExtraData)))
|
|
|
+ mapData = map[string]interface{}{
|
|
|
+ "raw_data": string(v.ExtraData),
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果是数组格式,将数组作为值存储
|
|
|
+ s.Logger.Warn("额外数据为数组格式,保存为数组值", zap.Int("id", v.Id))
|
|
|
+ mapData = map[string]interface{}{
|
|
|
+ "array_data": arrayData,
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
if strings.Contains(v.ApiName, "tcp") || strings.Contains(v.ApiName, "udp") || strings.Contains(v.ApiName, "web") {
|
|
|
-
|
|
|
if mapData["port"] != nil {
|
|
|
port = mapData["port"].(string)
|
|
|
}
|
|
@@ -278,22 +514,22 @@ func (s *wafLogService) ExPortWafLog(ctx context.Context, req adminApi.ExportWaf
|
|
|
domain = mapData["domain"].(string)
|
|
|
}
|
|
|
if mapData["backend_list"] != nil {
|
|
|
-
|
|
|
if strings.Contains(v.ApiName, "web") {
|
|
|
var backendList []map[string]interface{}
|
|
|
err := json.Unmarshal([]byte(mapData["backend_list"].(string)), &backendList)
|
|
|
if err != nil {
|
|
|
- return nil, err
|
|
|
+ s.Logger.Error("解析后端列表失败", zap.Error(err))
|
|
|
+ continue
|
|
|
}
|
|
|
- for _, v := range backendList {
|
|
|
- if v["addr"] != nil {
|
|
|
- AddrBackendList = v["addr"]
|
|
|
+ for _, backend := range backendList {
|
|
|
+ if backend["addr"] != nil {
|
|
|
+ AddrBackendList = backend["addr"]
|
|
|
}
|
|
|
- if v["customHost"] != nil {
|
|
|
- customHost = v["customHost"].(string)
|
|
|
+ if backend["customHost"] != nil {
|
|
|
+ customHost = backend["customHost"].(string)
|
|
|
}
|
|
|
}
|
|
|
- }else {
|
|
|
+ } else {
|
|
|
AddrBackendList = mapData["backend_list"]
|
|
|
}
|
|
|
}
|
|
@@ -303,36 +539,51 @@ func (s *wafLogService) ExPortWafLog(ctx context.Context, req adminApi.ExportWaf
|
|
|
comment = mapData["comment"].(string)
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- gateWayIpModel, err := s.wafLogRepository.GetWafLogGateWayIp(ctx, int64(v.HostId), int64(v.Uid),v.CreatedAt)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- var gateWayIps []string
|
|
|
- if err := json.Unmarshal(gateWayIpModel.ExtraData, &gateWayIps); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
+ // 优化:从批量获取的网关组数据中查找
|
|
|
var exposeAddr []string
|
|
|
- if len(gateWayIps) > 0 {
|
|
|
- for _, v := range gateWayIps {
|
|
|
- exposeAddr = append(exposeAddr, v + ":" + port)
|
|
|
+ key := fmt.Sprintf("%d_%d", v.HostId, v.Uid)
|
|
|
+ if gatewayModel, exists := gatewayMap[key]; exists {
|
|
|
+ var gateWayIps []string
|
|
|
+ if err := json.Unmarshal(gatewayModel.ExtraData, &gateWayIps); err == nil {
|
|
|
+ if len(gateWayIps) > 0 && port != "" {
|
|
|
+ for _, ip := range gateWayIps {
|
|
|
+ exposeAddr = append(exposeAddr, ip+":"+port)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 降级:单个查询
|
|
|
+ gateWayIpModel, err := s.wafLogRepository.GetWafLogGateWayIp(ctx, int64(v.HostId), int64(v.Uid), v.CreatedAt)
|
|
|
+ if err == nil {
|
|
|
+ var gateWayIps []string
|
|
|
+ if err := json.Unmarshal(gateWayIpModel.ExtraData, &gateWayIps); err == nil {
|
|
|
+ if len(gateWayIps) > 0 && port != "" {
|
|
|
+ for _, ip := range gateWayIps {
|
|
|
+ exposeAddr = append(exposeAddr, ip+":"+port)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
res = append(res, adminApi.ExportWafLogRes{
|
|
|
- Name: v.Name,
|
|
|
- RequestIp: v.RequestIp,
|
|
|
- HostId: v.HostId,
|
|
|
- ApiName: v.ApiName,
|
|
|
- AddrBackendList: AddrBackendList,
|
|
|
- Domain: domain,
|
|
|
- Comment: comment,
|
|
|
- CustomHost: customHost,
|
|
|
- ExposeAddr: exposeAddr,
|
|
|
- CreatedAt: v.CreatedAt,
|
|
|
+ Name: v.Name,
|
|
|
+ RequestIp: v.RequestIp,
|
|
|
+ HostId: v.HostId,
|
|
|
+ ApiName: v.ApiName,
|
|
|
+ AddrBackendList: AddrBackendList,
|
|
|
+ Domain: domain,
|
|
|
+ Comment: comment,
|
|
|
+ CustomHost: customHost,
|
|
|
+ ExposeAddr: exposeAddr,
|
|
|
+ CreatedAt: v.CreatedAt,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
return res, nil
|
|
|
+}
|
|
|
|
|
|
+// GetApiDescriptions 获取API描述映射
|
|
|
+func (s *wafLogService) GetApiDescriptions(ctx context.Context) map[string]string {
|
|
|
+ return ApiDescriptionMap
|
|
|
}
|