Przeglądaj źródła

feat(service): 添加 CDN 服务和请求服务

- 新增 RequestService 接口和实现,用于发送 HTTP 请求
- 新增 CdnService 接口和实现,用于获取 CDN 令牌
- 在 gatewaygroupip 服务中集成请求服务,实现 IP 相关操作- 重构 gatewaygroupip 服务中的方法,优化错误处理和逻辑
fusu 1 miesiąc temu
rodzic
commit
045dfc81e3

+ 1 - 1
api/v1/request.go

@@ -1,6 +1,6 @@
 package v1
 
-type FlexCdnResponse[T any] struct {
+type GeneralResponse[T any] struct {
 	Code    int    `json:"code" form:"code"`
 	Message string `json:"message" form:"message"`
 	Data    T  `json:"data" form:"data"`

+ 5 - 3
internal/repository/gatewaygroupip.go

@@ -33,9 +33,11 @@ type gateWayGroupIpRepository struct {
 }
 
 func (r *gateWayGroupIpRepository) GetGateWayGroupIp(ctx context.Context, id int64) (*model.GateWayGroupIp, error) {
-	var gateWayGroupIp model.GateWayGroupIp
-
-	return &gateWayGroupIp, nil
+	var res model.GateWayGroupIp
+	if err := r.DB(ctx).Where("id = ?", id).First(&res).Error; err != nil {
+		return nil, err
+	}
+	return &res, nil
 }
 
 func (r *gateWayGroupIpRepository) AddGateWayGroupIp(ctx context.Context, req *model.GateWayGroupIp) error {

+ 60 - 0
internal/service/cdn.go

@@ -0,0 +1,60 @@
+package service
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/spf13/viper"
+)
+
+type CdnService interface {
+	GetToken(ctx context.Context) (string, error)
+}
+func NewCdnService(
+    service *Service,
+	conf *viper.Viper,
+	request RequestService,
+) CdnService {
+	return &cdnService{
+		Service:        service,
+		Url:             conf.GetString("flexCdn.Url"),
+		AccessKeyID:     conf.GetString("flexCdn.AccessKeyID"),
+		AccessKeySecret: conf.GetString("flexCdn.AccessKeySecret"),
+		request:         request,
+	}
+}
+
+type cdnService struct {
+	*Service
+	Url             string
+	AccessKeyID     string
+	AccessKeySecret string
+	request         RequestService
+}
+
+func (s *cdnService) GetToken(ctx context.Context) (string, error) {
+	formData := map[string]interface{}{
+		"type":        "admin",
+		"accessKeyId": s.AccessKeyID,
+		"accessKey":   s.AccessKeySecret,
+	}
+	apiUrl := s.Url + "APIAccessTokenService/getAPIAccessToken"
+	resBody, err := s.request.Request(ctx, formData, apiUrl, "\"X-Cloud-Access-Token\"", "")
+	if err != nil {
+		return "", err
+	}
+
+	var res v1.GeneralResponse[v1.FlexCdnTokenResponse]
+	if err := json.Unmarshal(resBody, &res); err != nil {
+		return "", fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
+	}
+
+	if res.Code != 200 {
+		return "", fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
+	}
+
+	return res.Data.Token, nil
+}
+
+

+ 60 - 2
internal/service/gatewaygroupip.go

@@ -2,8 +2,9 @@ package service
 
 import (
 	"context"
+	"encoding/json"
+	"fmt"
 	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
-
 	"github.com/go-nunu/nunu-layout-advanced/internal/model"
 	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
 )
@@ -20,20 +21,27 @@ type GateWayGroupIpService interface {
 func NewGateWayGroupIpService(
 	service *Service,
 	gateWayGroupIpRepository repository.GateWayGroupIpRepository,
+	request RequestService,
 ) GateWayGroupIpService {
 	return &gateWayGroupIpService{
 		Service:                  service,
 		gateWayGroupIpRepository: gateWayGroupIpRepository,
+		request: request,
 	}
 }
 
 type gateWayGroupIpService struct {
 	*Service
 	gateWayGroupIpRepository repository.GateWayGroupIpRepository
+	request RequestService
 }
 
 func (s *gateWayGroupIpService) GetGateWayGroupIp(ctx context.Context, id int64) (*model.GateWayGroupIp, error) {
-	return s.gateWayGroupIpRepository.GetGateWayGroupIp(ctx, id)
+	res, err := s.gateWayGroupIpRepository.GetGateWayGroupIp(ctx, id)
+	if err != nil {
+		return nil, err
+	}
+	return res, nil
 }
 
 func (s *gateWayGroupIpService) GetGateWayGroupIpByGatewayGroupId(ctx context.Context, gatewayGroupId int) (*[]model.GateWayGroupIp, error) {
@@ -45,6 +53,9 @@ func (s *gateWayGroupIpService) GetGateWayGroupIpByGatewayGroupId(ctx context.Co
 }
 
 func (s *gateWayGroupIpService) AddGateWayGroupIp(ctx context.Context, req *v1.GateWayGroupIpRequest) error {
+	if err := s.sendIp(ctx, req.Ip, "add"); err != nil {
+		return err
+	}
 	if err := s.gateWayGroupIpRepository.AddGateWayGroupIp(ctx, &model.GateWayGroupIp{
 		GatewayGroupId: req.GatewayGroupId,
 		Ip:             req.Ip,
@@ -58,6 +69,18 @@ func (s *gateWayGroupIpService) AddGateWayGroupIp(ctx context.Context, req *v1.G
 }
 
 func (s *gateWayGroupIpService) EditGateWayGroupIp(ctx context.Context, req *v1.GateWayGroupIpRequest) error {
+	oldIp, err := s.GetGateWayGroupIp(ctx, int64(req.Id))
+	if err != nil {
+		return err
+	}
+	if oldIp.Ip != req.Ip {
+		if err := s.sendIp(ctx, oldIp.Ip, "delete"); err != nil {
+			return err
+		}
+		if err := s.sendIp(ctx, req.Ip, "add"); err != nil {
+			return err
+		}
+	}
 	if err := s.gateWayGroupIpRepository.EditGateWayGroupIp(ctx, &model.GateWayGroupIp{
 		Id:             req.Id,
 		GatewayGroupId: req.GatewayGroupId,
@@ -72,6 +95,13 @@ func (s *gateWayGroupIpService) EditGateWayGroupIp(ctx context.Context, req *v1.
 }
 
 func (s *gateWayGroupIpService) DeleteGateWayGroupIp(ctx context.Context, req *v1.DeleteGateWayGroupIpRequest) error {
+	oldIp, err := s.GetGateWayGroupIp(ctx, int64(req.Id))
+	if err != nil {
+		return err
+	}
+	if err := s.sendIp(ctx, oldIp.Ip, "delete"); err != nil {
+		return err
+	}
 	if err := s.gateWayGroupIpRepository.DeleteGateWayGroupIp(ctx, &model.GateWayGroupIp{
 		Id: req.Id,
 	}); err != nil {
@@ -87,4 +117,32 @@ func (s *gateWayGroupIpService) GetGateWayGroupIpAdmin(ctx context.Context,req *
 	}
 	return res, nil
 
+}
+
+func (s *gateWayGroupIpService) sendIp(ctx context.Context, ip string, action string) error  {
+	var apiUrl string
+	switch action {
+	case "add":
+		apiUrl = ""
+	case "delete":
+
+		apiUrl = ""
+	}
+	formData := map[string]interface{}{
+		"ip": ip,
+	}
+	resBody, err := s.request.Request(ctx, formData, apiUrl, "", "")
+	if err != nil {
+		return err
+	}
+	var res v1.GeneralResponse[string]
+	err = json.Unmarshal(resBody, &res)
+	if err != nil {
+		return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
+	}
+	if res.Code != 0 {
+		return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
+	}
+	return nil
+
 }

+ 76 - 0
internal/service/request.go

@@ -0,0 +1,76 @@
+package service
+
+import (
+	"bytes"
+	"context"
+	"crypto/tls"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"time"
+)
+
+type RequestService interface {
+	Request(ctx context.Context, formData map[string]interface{},apiUrl string, tokenName string,token string) ([]byte, error)
+}
+
+func NewRequestService(
+	service *Service,
+) RequestService {
+	httpClient := &http.Client{
+		Transport: &http.Transport{
+			TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
+			MaxIdleConns:        500,              // 最大空闲连接数
+			MaxIdleConnsPerHost: 300,              // 每个主机的最大空闲连接数
+			IdleConnTimeout:     90 * time.Second, // 空闲连接超时时间
+		},
+		Timeout: 30 * time.Second, // 请求超时时间
+	}
+
+	return &requestService{
+		Service:         service,
+		httpClient:      httpClient,
+	}
+}
+
+type requestService struct {
+	*Service
+	httpClient      *http.Client
+}
+
+func (s *requestService) Request(ctx context.Context, formData map[string]interface{},apiUrl string, tokenName string,token string) ([]byte, error) {
+	jsonData, err := json.Marshal(formData)
+	if err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequestWithContext(ctx, "POST", apiUrl, bytes.NewBuffer(jsonData))
+	if err != nil {
+		return nil, fmt.Errorf("创建 HTTP 请求失败: %w", err)
+	}
+	req.Header.Set("Content-Type", "application/json")
+
+	if token != "" {
+		req.Header.Set(tokenName, token)
+	}
+
+	resp, err := s.httpClient.Do(req)
+	if err != nil {
+		return nil, fmt.Errorf("发送 HTTP 请求失败 (isSmall: %t): %w", err)
+	}
+	defer resp.Body.Close()
+
+	body, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return nil, fmt.Errorf("读取响应体失败 (isSmall: %t): %w", err)
+	}
+
+	if resp.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("HTTP 错误 (isSmall: %t): 状态码 %d, 响应: %s", resp.StatusCode, string(body))
+	}
+
+	return body, nil
+
+}
+