cdn.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
  7. "github.com/go-nunu/nunu-layout-advanced/internal/repository"
  8. "github.com/spf13/viper"
  9. "strings"
  10. )
  11. type CdnService interface {
  12. // GetToken 获取token
  13. GetToken(ctx context.Context) (string, error)
  14. // AddUser 注册用户
  15. AddUser(ctx context.Context, req v1.User) (int64, error)
  16. CreateGroup(ctx context.Context, req v1.Group) (int64, error)
  17. BindPlan(ctx context.Context, req v1.Plan) (int64, error)
  18. RenewPlan(ctx context.Context, req v1.RenewalPlan) error
  19. CreateWebsite(ctx context.Context, req v1.Website) (int64, error)
  20. EditServerType(ctx context.Context, req v1.EditWebsite, apiType string) error
  21. EditProtocol(ctx context.Context, req v1.ProxyJson, action string) error
  22. CreateOrigin(ctx context.Context, req v1.Origin) (int64, error)
  23. EditOrigin(ctx context.Context, req v1.Origin) error
  24. AddServerOrigin(ctx context.Context, serverId int64, originId int64) error
  25. EditOriginIsOn(ctx context.Context, originId int64, isOn bool) error
  26. // 修改网站基本信息
  27. EditServerBasic(ctx context.Context, serverId int64, name string,nodeId int64) error
  28. // 从网站中删除某个源站
  29. DelServerOrigin(ctx context.Context, serverId int64, originId int64) error
  30. // 删除网站
  31. DelServer(ctx context.Context, serverId int64) error
  32. // 添加ssl证书
  33. AddSSLCert(ctx context.Context, req v1.SSlCert) (int64, error)
  34. // 修改网站域名
  35. EditServerName(ctx context.Context, req v1.EditServerNames) error
  36. // 添加ssl策略
  37. AddSSLPolicy(ctx context.Context, req v1.AddSSLPolicy) (int64, error)
  38. DelSSLCert(ctx context.Context, sslCertId int64) error
  39. EditSSLCert(ctx context.Context, req v1.SSlCert) error
  40. EditSSLPolicy(ctx context.Context, req v1.SSLPolicy) error
  41. }
  42. func NewCdnService(
  43. service *Service,
  44. conf *viper.Viper,
  45. request RequestService,
  46. cdnRepository repository.CdnRepository,
  47. ) CdnService {
  48. return &cdnService{
  49. Service: service,
  50. Url: conf.GetString("flexCdn.Url"),
  51. AccessKeyID: conf.GetString("flexCdn.AccessKeyID"),
  52. AccessKeySecret: conf.GetString("flexCdn.AccessKeySecret"),
  53. request: request,
  54. cdnRepository: cdnRepository,
  55. maxRetryCount: 3, // 可以配置最大重试次数
  56. retryDelaySeconds: 2, // 可以配置重试间隔
  57. }
  58. }
  59. type cdnService struct {
  60. *Service
  61. Url string
  62. AccessKeyID string
  63. AccessKeySecret string
  64. request RequestService
  65. cdnRepository repository.CdnRepository
  66. maxRetryCount int
  67. retryDelaySeconds int
  68. }
  69. // SendData 是一个通用的请求发送方法,它封装了 token 过期重试的逻辑
  70. func (s *cdnService) sendDataWithTokenRetry(ctx context.Context, formData map[string]interface{}, apiUrl string) ([]byte, error) {
  71. var resBody []byte
  72. for i := 0; i < s.maxRetryCount; i++ {
  73. token, err := s.Token(ctx) // 确保使用最新的 token
  74. if err != nil {
  75. return nil, fmt.Errorf("获取或刷新 token 失败: %w", err)
  76. }
  77. resBody, err = s.request.Request(ctx, formData, apiUrl, "X-Cloud-Access-Token", token)
  78. if err != nil {
  79. // 检查错误是否是由于 token 无效引起的
  80. if s.isTokenInvalidError(resBody, err) { // 判断是否是 token 无效错误
  81. _, getTokenErr := s.GetToken(ctx)
  82. if getTokenErr != nil {
  83. return nil, fmt.Errorf("刷新 token 失败: %w", getTokenErr)
  84. }
  85. continue // 继续下一次循环,使用新的 token
  86. }
  87. return nil, fmt.Errorf("请求失败: %w", err)
  88. }
  89. // 成功获取到响应,处理响应体
  90. var generalResponse v1.GeneralResponse[any]
  91. if err := json.Unmarshal(resBody, &generalResponse); err != nil {
  92. return nil, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  93. }
  94. // 检查 API 返回的 code 和 message
  95. if generalResponse.Code == 400 && generalResponse.Message == "invalid access token" {
  96. fmt.Printf("尝试 %d/%d:API 返回无效 token 错误,准备刷新并重试...\n", i+1, s.maxRetryCount)
  97. _, getTokenErr := s.GetToken(ctx)
  98. if getTokenErr != nil {
  99. return nil, fmt.Errorf("刷新 token 失败: %w", getTokenErr)
  100. }
  101. continue // 继续下一次循环,使用新的 token
  102. }
  103. // 成功处理,返回结果
  104. return resBody, nil
  105. }
  106. // 如果循环结束仍未成功,则返回最终错误
  107. return nil, fmt.Errorf("达到最大重试次数后请求仍然失败")
  108. }
  109. // isTokenInvalidError 是一个辅助函数,用于判断错误是否是由于 token 无效引起的。
  110. // 你需要根据你的 request.Request 实现来具体实现这个函数。
  111. // 例如,你可以检查 resBody 是否包含特定的错误信息。
  112. func (s *cdnService) isTokenInvalidError(resBody []byte, err error) bool {
  113. // 示例:如果请求本身就返回了非 200 的错误,并且响应体中有特定信息
  114. if err != nil {
  115. // 尝试从 resBody 中解析出错误信息,判断是否是 token 无效
  116. var generalResponse v1.GeneralResponse[any]
  117. if parseErr := json.Unmarshal(resBody, &generalResponse); parseErr == nil {
  118. if generalResponse.Code == 400 && generalResponse.Message == "invalid access token" {
  119. return true
  120. }
  121. }
  122. // 或者检查 err 本身是否有相关的错误信息
  123. // if strings.Contains(err.Error(), "invalid access token") {
  124. // return true
  125. // }
  126. }
  127. return false
  128. }
  129. func (s *cdnService) GetToken(ctx context.Context) (string, error) {
  130. formData := map[string]interface{}{
  131. "type": "admin",
  132. "accessKeyId": s.AccessKeyID,
  133. "accessKey": s.AccessKeySecret,
  134. }
  135. apiUrl := s.Url + "APIAccessTokenService/getAPIAccessToken"
  136. resBody, err := s.request.Request(ctx, formData, apiUrl, "X-Cloud-Access-Token", "")
  137. if err != nil {
  138. return "", err
  139. }
  140. var res v1.GeneralResponse[v1.FlexCdnTokenResponse]
  141. if err := json.Unmarshal(resBody, &res); err != nil {
  142. return "", fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  143. }
  144. if res.Code != 200 {
  145. return "", fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  146. }
  147. err = s.cdnRepository.PutToken(ctx, res.Data.Token)
  148. if err != nil {
  149. return "", err
  150. }
  151. return res.Data.Token, nil
  152. }
  153. func (s *cdnService) Token(ctx context.Context) (string, error) {
  154. token, err := s.cdnRepository.GetToken(ctx)
  155. if err != nil {
  156. return "", err
  157. }
  158. if token == "" {
  159. token, err = s.GetToken(ctx)
  160. if err != nil {
  161. return "", err
  162. }
  163. }
  164. return token, nil
  165. }
  166. // 注册用户
  167. func (s *cdnService) AddUser(ctx context.Context, req v1.User) (int64, error) {
  168. formData := map[string]interface{}{
  169. "id": req.ID,
  170. "username": req.Username,
  171. "password": "a7fKiKujgAzzsJ6", // 这个密码应该被妥善管理,而不是硬编码
  172. "fullname": req.Fullname,
  173. "mobile": req.Mobile,
  174. "tel": req.Tel,
  175. "email": req.Email,
  176. "remark": req.Remark,
  177. "source": req.Source,
  178. "nodeClusterId": 1,
  179. }
  180. apiUrl := s.Url + "UserService/createUser"
  181. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  182. if err != nil {
  183. return 0, err
  184. }
  185. type DataStr struct {
  186. UserId int64 `json:"userId" form:"userId"`
  187. }
  188. var res v1.GeneralResponse[DataStr]
  189. if err := json.Unmarshal(resBody, &res); err != nil {
  190. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  191. }
  192. if res.Code != 200 {
  193. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  194. }
  195. if res.Data.UserId == 0 {
  196. return 0, fmt.Errorf("添加用户失败")
  197. }
  198. return res.Data.UserId, nil
  199. }
  200. // 创建规则分组
  201. func (s *cdnService) CreateGroup(ctx context.Context, req v1.Group) (int64, error) {
  202. formData := map[string]interface{}{
  203. "name": req.Name,
  204. }
  205. apiUrl := s.Url + "ServerGroupService/createServerGroup"
  206. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  207. if err != nil {
  208. return 0, err
  209. }
  210. type DataStr struct {
  211. ServerGroupId int64 `json:"serverGroupId" form:"serverGroupId"`
  212. }
  213. var res v1.GeneralResponse[DataStr]
  214. if err := json.Unmarshal(resBody, &res); err != nil {
  215. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  216. }
  217. if res.Code != 200 {
  218. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  219. }
  220. if res.Data.ServerGroupId == 0 {
  221. return 0, fmt.Errorf("创建规则分组失败")
  222. }
  223. return res.Data.ServerGroupId, nil
  224. }
  225. // 分配套餐
  226. func (s *cdnService) BindPlan(ctx context.Context, req v1.Plan) (int64, error) {
  227. formData := map[string]interface{}{
  228. "userId": req.UserId,
  229. "planId": req.PlanId,
  230. "dayTo": req.DayTo,
  231. "period": req.Period,
  232. "countPeriod": req.CountPeriod,
  233. "name": req.Name,
  234. "isFree": req.IsFree,
  235. "periodDayTo": req.PeriodDayTo,
  236. }
  237. apiUrl := s.Url + "UserPlanService/buyUserPlan"
  238. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  239. if err != nil {
  240. return 0, err
  241. }
  242. type DataStr struct {
  243. UserPlanId int64 `json:"userPlanId" form:"userPlanId"`
  244. }
  245. var res v1.GeneralResponse[DataStr]
  246. if err := json.Unmarshal(resBody, &res); err != nil {
  247. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  248. }
  249. if res.Code != 200 {
  250. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  251. }
  252. if res.Data.UserPlanId == 0 {
  253. return 0, fmt.Errorf("分配套餐失败")
  254. }
  255. return res.Data.UserPlanId, nil
  256. }
  257. // 续费套餐
  258. func (s *cdnService) RenewPlan(ctx context.Context, req v1.RenewalPlan) error {
  259. formData := map[string]interface{}{
  260. "userPlanId": req.UserPlanId,
  261. "dayTo": req.DayTo,
  262. "period": req.Period,
  263. "countPeriod": req.CountPeriod,
  264. "isFree": req.IsFree,
  265. "periodDayTo": req.PeriodDayTo,
  266. }
  267. apiUrl := s.Url + "UserPlanService/renewUserPlan"
  268. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  269. if err != nil {
  270. return err
  271. }
  272. var res v1.GeneralResponse[any]
  273. if err := json.Unmarshal(resBody, &res); err != nil {
  274. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  275. }
  276. if res.Code != 200 {
  277. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  278. }
  279. return nil
  280. }
  281. // 创建网站
  282. func (s *cdnService) CreateWebsite(ctx context.Context, req v1.Website) (int64, error) {
  283. formData := map[string]interface{}{
  284. "userId": req.UserId,
  285. "type": req.Type,
  286. "name": req.Name,
  287. "description": req.Description,
  288. "serverNamesJSON": req.ServerNamesJSON,
  289. "httpJSON": req.HttpJSON,
  290. "httpsJSON": req.HttpsJSON,
  291. "tcpJSON": req.TcpJSON,
  292. "tlsJSON": req.TlsJSON,
  293. "udpJSON": req.UdpJSON,
  294. "webId": req.WebId,
  295. "reverseProxyJSON": req.ReverseProxyJSON,
  296. "serverGroupIds": req.ServerGroupIds,
  297. "userPlanId": req.UserPlanId,
  298. "nodeClusterId": req.NodeClusterId,
  299. }
  300. apiUrl := s.Url + "ServerService/createServer"
  301. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  302. if err != nil {
  303. return 0, err
  304. }
  305. type DataStr struct {
  306. ServerId int64 `json:"serverId" form:"serverId"`
  307. }
  308. var res v1.GeneralResponse[DataStr]
  309. if err := json.Unmarshal(resBody, &res); err != nil {
  310. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  311. }
  312. if res.Code != 200 {
  313. return 0, fmt.Errorf("创建网站API 错误: code %d, msg '%s'", res.Code, res.Message)
  314. }
  315. if res.Data.ServerId == 0 {
  316. return 0, fmt.Errorf("创建网站失败")
  317. }
  318. return res.Data.ServerId, nil
  319. }
  320. func (s *cdnService) EditProtocol(ctx context.Context, req v1.ProxyJson, action string) error {
  321. formData := map[string]interface{}{
  322. "serverId": req.ServerId,
  323. }
  324. var apiUrl string
  325. switch action {
  326. case "tcp":
  327. formData["tcpJSON"] = req.JSON
  328. apiUrl = s.Url + "ServerService/updateServerTCP"
  329. case "tls":
  330. formData["tlsJSON"] = req.JSON
  331. apiUrl = s.Url + "ServerService/updateServerTLS"
  332. case "udp":
  333. formData["udpJSON"] = req.JSON
  334. apiUrl = s.Url + "ServerService/updateServerUDP"
  335. case "http":
  336. formData["httpJSON"] = req.JSON
  337. apiUrl = s.Url + "ServerService/updateServerHTTP"
  338. case "https":
  339. formData["httpsJSON"] = req.JSON
  340. apiUrl = s.Url + "ServerService/updateServerHTTPS"
  341. default:
  342. return fmt.Errorf("不支持的协议类型")
  343. }
  344. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  345. if err != nil {
  346. return err
  347. }
  348. var res v1.GeneralResponse[any]
  349. if err := json.Unmarshal(resBody, &res); err != nil {
  350. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  351. }
  352. if res.Code != 200 {
  353. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  354. }
  355. return nil
  356. }
  357. func (s *cdnService) CreateOrigin(ctx context.Context, req v1.Origin) (int64, error) {
  358. formData := map[string]interface{}{
  359. "name": req.Name,
  360. "addr": req.Addr,
  361. "ossJSON": req.OssJSON,
  362. "description": req.Description,
  363. "weight": req.Weight,
  364. "isOn": req.IsOn,
  365. "domains": req.Domains,
  366. "certRefJSON": req.CertRefJSON,
  367. "host": req.Host,
  368. "followPort": req.FollowPort,
  369. "http2Enabled": req.Http2Enabled,
  370. "tlsSecurityVerifyMode": req.TlsSecurityVerifyMode,
  371. }
  372. apiUrl := s.Url + "OriginService/createOrigin"
  373. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  374. if err != nil {
  375. return 0, err
  376. }
  377. type DataStr struct {
  378. OriginId int64 `json:"originId" form:"originId"`
  379. }
  380. var res v1.GeneralResponse[DataStr]
  381. if err := json.Unmarshal(resBody, &res); err != nil {
  382. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  383. }
  384. if res.Code != 200 {
  385. return 0, fmt.Errorf("添加源站API 错误: code %d, msg '%s'", res.Code, res.Message)
  386. }
  387. if res.Data.OriginId == 0 {
  388. return 0, fmt.Errorf("创建源站失败")
  389. }
  390. return res.Data.OriginId, nil
  391. }
  392. func (s *cdnService) EditServerType(ctx context.Context, req v1.EditWebsite, apiType string) error {
  393. typeName := apiType + "JSON"
  394. formData := map[string]interface{}{
  395. "serverId": req.Id,
  396. typeName: req.TypeJSON,
  397. }
  398. apiUrl := s.Url + "ServerService/updateServer" + strings.ToUpper(apiType)
  399. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  400. if err != nil {
  401. return err
  402. }
  403. var res v1.GeneralResponse[any]
  404. if err := json.Unmarshal(resBody, &res); err != nil {
  405. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  406. }
  407. if res.Code != 200 {
  408. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  409. }
  410. return nil
  411. }
  412. // EditOrigin 编辑源站
  413. func (s *cdnService) EditOrigin(ctx context.Context, req v1.Origin) error {
  414. formData := map[string]interface{}{
  415. "originId": req.OriginId,
  416. "name": req.Name,
  417. "addr": req.Addr,
  418. "ossJSON": req.OssJSON,
  419. "description": req.Description,
  420. "weight": req.Weight,
  421. "isOn": req.IsOn,
  422. "domains": req.Domains,
  423. "certRefJSON": req.CertRefJSON,
  424. "host": req.Host,
  425. "followPort": req.FollowPort,
  426. "http2Enabled": req.Http2Enabled,
  427. "tlsSecurityVerifyMode": req.TlsSecurityVerifyMode,
  428. }
  429. apiUrl := s.Url + "OriginService/updateOrigin"
  430. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  431. if err != nil {
  432. return err
  433. }
  434. var res v1.GeneralResponse[any]
  435. if err := json.Unmarshal(resBody, &res); err != nil {
  436. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  437. }
  438. if res.Code != 200 {
  439. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  440. }
  441. return nil
  442. }
  443. // AddServerOrigin 网站绑定源站
  444. func (s *cdnService) AddServerOrigin(ctx context.Context, serverId int64, originId int64) error {
  445. formData := map[string]interface{}{
  446. "serverId": serverId,
  447. "originId": originId,
  448. "isPrimary": true,
  449. }
  450. apiUrl := s.Url + "ServerService/addServerOrigin"
  451. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  452. if err != nil {
  453. return err
  454. }
  455. var res v1.GeneralResponse[any]
  456. if err := json.Unmarshal(resBody, &res); err != nil {
  457. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  458. }
  459. if res.Code != 200 {
  460. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  461. }
  462. return nil
  463. }
  464. // EditOriginIsOn 编辑源站是否开启
  465. func (s *cdnService) EditOriginIsOn(ctx context.Context, originId int64, isOn bool) error {
  466. formData := map[string]interface{}{
  467. "originId": originId,
  468. "isOn": isOn,
  469. }
  470. apiUrl := s.Url + "OriginService/updateOriginIsOn"
  471. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  472. if err != nil {
  473. return err
  474. }
  475. var res v1.GeneralResponse[any]
  476. if err := json.Unmarshal(resBody, &res); err != nil {
  477. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  478. }
  479. if res.Code != 200 {
  480. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  481. }
  482. return nil
  483. }
  484. // EditServerBasic 修改网站基本信息
  485. func (s *cdnService) EditServerBasic(ctx context.Context, serverId int64, name string,nodeId int64) error {
  486. formData := map[string]interface{}{
  487. "serverId": serverId,
  488. "name": name,
  489. "nodeClusterId": nodeId,
  490. "isOn": true,
  491. }
  492. apiUrl := s.Url + "ServerService/updateServerBasic"
  493. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  494. if err != nil {
  495. return err
  496. }
  497. var res v1.GeneralResponse[any]
  498. if err := json.Unmarshal(resBody, &res); err != nil {
  499. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  500. }
  501. if res.Code != 200 {
  502. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  503. }
  504. return nil
  505. }
  506. // DelServerOrigin 从网站中删除某个源站
  507. func (s *cdnService) DelServerOrigin(ctx context.Context, serverId int64, originId int64) error {
  508. formData := map[string]interface{}{
  509. "serverId": serverId,
  510. "originId": originId,
  511. }
  512. apiUrl := s.Url + "ServerService/deleteServerOrigin"
  513. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  514. if err != nil {
  515. return err
  516. }
  517. var res v1.GeneralResponse[any]
  518. if err := json.Unmarshal(resBody, &res); err != nil {
  519. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  520. }
  521. if res.Code != 200 {
  522. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  523. }
  524. return nil
  525. }
  526. func (s *cdnService) DelServer(ctx context.Context, serverId int64) error {
  527. formData := map[string]interface{}{
  528. "serverId": serverId,
  529. }
  530. apiUrl := s.Url + "ServerService/deleteServer"
  531. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  532. if err != nil {
  533. return err
  534. }
  535. var res v1.GeneralResponse[any]
  536. if err := json.Unmarshal(resBody, &res); err != nil {
  537. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  538. }
  539. if res.Code != 200 {
  540. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  541. }
  542. return nil
  543. }
  544. // AddSSLCert 添加证书
  545. func (s *cdnService) AddSSLCert(ctx context.Context, req v1.SSlCert) (int64, error) {
  546. formData := map[string]interface{}{
  547. "isOn": req.IsOn,
  548. "userId": req.UserId,
  549. "name": req.Name,
  550. "serverName": req.ServerName,
  551. "description": req.Description,
  552. "isCA": req.IsCA,
  553. "certData": req.CertData,
  554. "keyData": req.KeyData,
  555. "timeBeginAt": req.TimeBeginAt,
  556. "timeEndAt": req.TimeEndAt,
  557. "dnsNames": req.DnsNames,
  558. "commonNames": req.CommonNames,
  559. "isSelfSigned": req.IsSelfSigned,
  560. }
  561. apiUrl := s.Url + "SSLCertService/createSSLCert"
  562. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  563. if err != nil {
  564. return 0, err
  565. }
  566. type DataStr struct {
  567. SslCertId int64 `json:"sslCertId" form:"sslCertId"`
  568. }
  569. var res v1.GeneralResponse[DataStr]
  570. if err := json.Unmarshal(resBody, &res); err != nil {
  571. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  572. }
  573. if res.Code != 200 {
  574. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  575. }
  576. return res.Data.SslCertId, nil
  577. }
  578. // 修改网站域名
  579. func (s *cdnService) EditServerName(ctx context.Context, req v1.EditServerNames) error {
  580. formData := map[string]interface{}{
  581. "serverId": req.ServerId,
  582. "serverNamesJSON": req.ServerNamesJSON,
  583. }
  584. apiUrl := s.Url + "ServerService/updateServerNames"
  585. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  586. if err != nil {
  587. return err
  588. }
  589. var res v1.GeneralResponse[any]
  590. if err := json.Unmarshal(resBody, &res); err != nil {
  591. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  592. }
  593. if res.Code != 200 {
  594. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  595. }
  596. return nil
  597. }
  598. // 添加ssl策略
  599. func (s *cdnService) AddSSLPolicy(ctx context.Context, req v1.AddSSLPolicy) (int64, error) {
  600. formData := map[string]interface{}{
  601. "http2Enabled": req.Http2Enabled,
  602. "http3Enabled": req.Http3Enabled,
  603. "minVersion": req.MinVersion,
  604. "sslCertsJSON": req.SslCertsJSON,
  605. "hstsJSON": req.HstsJSON,
  606. "clientAuthType": req.ClientAuthType,
  607. "cipherSuites": req.CipherSuites,
  608. "cipherSuitesIsOn": req.CipherSuitesIsOn,
  609. "ocspIsOn": req.OcspIsOn,
  610. }
  611. apiUrl := s.Url + "SSLPolicyService/createSSLPolicy"
  612. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  613. if err != nil {
  614. return 0, err
  615. }
  616. type DataStr struct {
  617. SslPolicyId int64 `json:"sslPolicyId" form:"sslPolicyId"`
  618. }
  619. var res v1.GeneralResponse[DataStr]
  620. if err := json.Unmarshal(resBody, &res); err != nil {
  621. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  622. }
  623. if res.Code != 200 {
  624. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  625. }
  626. return res.Data.SslPolicyId, nil
  627. }
  628. func (s *cdnService) DelSSLCert(ctx context.Context, sslCertId int64) error {
  629. formData := map[string]interface{}{
  630. "sslCertId": sslCertId,
  631. }
  632. apiUrl := s.Url + "SSLCertService/deleteSSLCert"
  633. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  634. if err != nil {
  635. return err
  636. }
  637. var res v1.GeneralResponse[any]
  638. if err := json.Unmarshal(resBody, &res); err != nil {
  639. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  640. }
  641. if res.Code != 200 {
  642. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  643. }
  644. return nil
  645. }
  646. func (s *cdnService) GetSSLPolicy(ctx context.Context, sslPolicyId int64) (v1.SSLPolicy, error) {
  647. formData := map[string]interface{}{
  648. "sslPolicyId": sslPolicyId,
  649. "ignoreData": true,
  650. }
  651. apiUrl := s.Url + "SSLPolicyService/findEnabledSSLPolicyConfig"
  652. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  653. if err != nil {
  654. return v1.SSLPolicy{}, err
  655. }
  656. var res v1.GeneralResponse[v1.SSLPolicy]
  657. if err := json.Unmarshal(resBody, &res); err != nil {
  658. return v1.SSLPolicy{}, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  659. }
  660. if res.Code != 200 {
  661. return v1.SSLPolicy{}, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  662. }
  663. return res.Data, nil
  664. }
  665. func (s *cdnService) EditSSLCert(ctx context.Context, req v1.SSlCert) error {
  666. formData := map[string]interface{}{
  667. "sslCertId": req.SslCertId,
  668. "userId": req.UserId,
  669. "isOn": req.IsOn,
  670. "name": req.Name,
  671. "description": req.Description,
  672. "isCA": req.IsCA,
  673. "certData": req.CertData,
  674. "keyData": req.KeyData,
  675. "timeBeginAt": req.TimeBeginAt,
  676. "timeEndAt": req.TimeEndAt,
  677. "dnsNames": req.DnsNames,
  678. "commonNames": req.CommonNames,
  679. "isSelfSigned": req.IsSelfSigned,
  680. }
  681. apiUrl := s.Url + "SSLCertService/createSSLCert"
  682. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  683. if err != nil {
  684. return err
  685. }
  686. var res v1.GeneralResponse[any]
  687. if err := json.Unmarshal(resBody, &res); err != nil {
  688. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  689. }
  690. if res.Code != 200 {
  691. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  692. }
  693. return nil
  694. }
  695. func (s *cdnService) EditSSLPolicy(ctx context.Context, req v1.SSLPolicy) error {
  696. formData := map[string]interface{}{
  697. "sslPolicyId": req.SslPolicyId,
  698. "http2Enabled": req.Http2Enabled,
  699. "http3Enabled": req.Http3Enabled,
  700. "minVersion": req.MinVersion,
  701. "sslCertsJSON": req.SslCertsJSON,
  702. "hstsJSON": req.HstsJSON,
  703. "clientAuthType": req.ClientAuthType,
  704. "cipherSuites": req.CipherSuites,
  705. "cipherSuitesIsOn": req.CipherSuitesIsOn,
  706. }
  707. apiUrl := s.Url + "SSLPolicyService/updateSSLPolicy"
  708. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  709. if err != nil {
  710. return err
  711. }
  712. var res v1.GeneralResponse[any]
  713. if err := json.Unmarshal(resBody, &res); err != nil {
  714. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  715. }
  716. if res.Code != 200 {
  717. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  718. }
  719. return nil
  720. }