cdn.go 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. package flexCdn
  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/api/flexCdn"
  8. "github.com/go-nunu/nunu-layout-advanced/internal/service"
  9. "github.com/spf13/viper"
  10. "strings"
  11. )
  12. type CdnService interface {
  13. // GetToken 获取token
  14. GetToken(ctx context.Context) (string, error)
  15. // AddUser 注册用户
  16. AddUser(ctx context.Context, req v1.User) (int64, error)
  17. CreateGroup(ctx context.Context, req v1.Group) (int64, error)
  18. BindPlan(ctx context.Context, req v1.Plan) (int64, error)
  19. // 续费套餐
  20. RenewPlan(ctx context.Context, req v1.RenewalPlan) error
  21. CreateWebsite(ctx context.Context, req v1.WebsiteSend) (int64, error)
  22. EditServerType(ctx context.Context, req v1.EditWebsite, apiType string) error
  23. EditProtocol(ctx context.Context, req v1.ProxyJson, action string) error
  24. CreateOrigin(ctx context.Context, req v1.Origin) (int64, error)
  25. EditOrigin(ctx context.Context, req v1.Origin) error
  26. AddServerOrigin(ctx context.Context, serverId int64, originId int64) error
  27. EditOriginIsOn(ctx context.Context, originId int64, isOn bool) error
  28. // 修改网站基本信息
  29. EditServerBasic(ctx context.Context, serverId int64, name string,nodeId int64) error
  30. // 从网站中删除某个源站
  31. DelServerOrigin(ctx context.Context, serverId int64, originId int64) error
  32. // 删除网站
  33. DelServer(ctx context.Context, serverId int64) error
  34. // 添加ssl证书
  35. AddSSLCert(ctx context.Context, req v1.SSlCert) (int64, error)
  36. // 修改网站域名
  37. EditServerName(ctx context.Context, req v1.EditServerNames) error
  38. // 添加ssl策略
  39. AddSSLPolicy(ctx context.Context, req v1.AddSSLPolicy) (int64, error)
  40. DelSSLCert(ctx context.Context, sslCertId int64) error
  41. EditSSLCert(ctx context.Context, req v1.SSlCert) error
  42. EditSSLPolicy(ctx context.Context, req v1.SSLPolicy) error
  43. // 修改反向代理
  44. EditProxy(ctx context.Context, req v1.Proxy) error
  45. // 修改日志
  46. EditWebLog(ctx context.Context,webId int64, req v1.WebLog) error
  47. // 修改CC配置
  48. EditCcConfig(ctx context.Context,webId int64, req v1.CcConfig) error
  49. // 添加webSocket
  50. AddWebSockets(ctx context.Context, req v1.WebSocket) (int64,error)
  51. // 修改webSocket
  52. EditWebSockets(ctx context.Context, req v1.WebSocket) error
  53. // 启用webSocket
  54. EditHTTPWebWebsocket(ctx context.Context,websocketId int64,websocketJSON []byte) error
  55. // 启用/禁用网站
  56. EditWebIsOn(ctx context.Context,serverId int64,isOn bool) error
  57. // 删除已购套餐
  58. DelUserPlan(ctx context.Context,planId int64) error
  59. // 删除网站分组
  60. DelServerGroup(ctx context.Context,serverId int64) error
  61. // 删除IP
  62. DelIpItem(ctx context.Context,ipitemId int64,value string,ipFrom string,ipTo string,ipListId int64) error
  63. }
  64. func NewCdnService(
  65. service *service.Service,
  66. conf *viper.Viper,
  67. request service.RequestService,
  68. cdnRepository flexCdn.CdnRepository,
  69. ) CdnService {
  70. return &cdnService{
  71. Service: service,
  72. Url: conf.GetString("flexCdn.Url"),
  73. AccessKeyID: conf.GetString("flexCdn.AccessKeyID"),
  74. AccessKeySecret: conf.GetString("flexCdn.AccessKeySecret"),
  75. request: request,
  76. cdnRepository: cdnRepository,
  77. maxRetryCount: 3, // 可以配置最大重试次数
  78. retryDelaySeconds: 2, // 可以配置重试间隔
  79. }
  80. }
  81. type cdnService struct {
  82. *service.Service
  83. Url string
  84. AccessKeyID string
  85. AccessKeySecret string
  86. request service.RequestService
  87. cdnRepository flexCdn.CdnRepository
  88. maxRetryCount int
  89. retryDelaySeconds int
  90. }
  91. // SendData 是一个通用的请求发送方法,它封装了 token 过期重试的逻辑
  92. func (s *cdnService) sendDataWithTokenRetry(ctx context.Context, formData map[string]interface{}, apiUrl string) ([]byte, error) {
  93. var resBody []byte
  94. for i := 0; i < s.maxRetryCount; i++ {
  95. token, err := s.Token(ctx) // 确保使用最新的 token
  96. if err != nil {
  97. return nil, fmt.Errorf("获取或刷新 token 失败: %w", err)
  98. }
  99. resBody, err = s.request.Request(ctx, formData, apiUrl, "X-Cloud-Access-Token", token)
  100. if err != nil {
  101. // 检查错误是否是由于 token 无效引起的
  102. if s.isTokenInvalidError(resBody, err) { // 判断是否是 token 无效错误
  103. _, getTokenErr := s.GetToken(ctx)
  104. if getTokenErr != nil {
  105. return nil, fmt.Errorf("刷新 token 失败: %w", getTokenErr)
  106. }
  107. continue // 继续下一次循环,使用新的 token
  108. }
  109. return nil, fmt.Errorf("请求失败: %w", err)
  110. }
  111. // 成功获取到响应,处理响应体
  112. var generalResponse v1.GeneralResponse[any]
  113. if err := json.Unmarshal(resBody, &generalResponse); err != nil {
  114. return nil, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  115. }
  116. // 检查 API 返回的 code 和 message
  117. if generalResponse.Code == 400 && generalResponse.Message == "invalid access token" {
  118. fmt.Printf("尝试 %d/%d:API 返回无效 token 错误,准备刷新并重试...\n", i+1, s.maxRetryCount)
  119. _, getTokenErr := s.GetToken(ctx)
  120. if getTokenErr != nil {
  121. return nil, fmt.Errorf("刷新 token 失败: %w", getTokenErr)
  122. }
  123. continue // 继续下一次循环,使用新的 token
  124. }
  125. // 成功处理,返回结果
  126. return resBody, nil
  127. }
  128. // 如果循环结束仍未成功,则返回最终错误
  129. return nil, fmt.Errorf("达到最大重试次数后请求仍然失败")
  130. }
  131. // isTokenInvalidError 是一个辅助函数,用于判断错误是否是由于 token 无效引起的。
  132. // 你需要根据你的 request.Request 实现来具体实现这个函数。
  133. // 例如,你可以检查 resBody 是否包含特定的错误信息。
  134. func (s *cdnService) isTokenInvalidError(resBody []byte, err error) bool {
  135. // 示例:如果请求本身就返回了非 200 的错误,并且响应体中有特定信息
  136. if err != nil {
  137. // 尝试从 resBody 中解析出错误信息,判断是否是 token 无效
  138. var generalResponse v1.GeneralResponse[any]
  139. if parseErr := json.Unmarshal(resBody, &generalResponse); parseErr == nil {
  140. if generalResponse.Code == 400 && generalResponse.Message == "invalid access token" {
  141. return true
  142. }
  143. }
  144. // 或者检查 err 本身是否有相关的错误信息
  145. // if strings.Contains(err.Error(), "invalid access token") {
  146. // return true
  147. // }
  148. }
  149. return false
  150. }
  151. func (s *cdnService) GetToken(ctx context.Context) (string, error) {
  152. formData := map[string]interface{}{
  153. "type": "admin",
  154. "accessKeyId": s.AccessKeyID,
  155. "accessKey": s.AccessKeySecret,
  156. }
  157. apiUrl := s.Url + "APIAccessTokenService/getAPIAccessToken"
  158. resBody, err := s.request.Request(ctx, formData, apiUrl, "X-Cloud-Access-Token", "")
  159. if err != nil {
  160. return "", err
  161. }
  162. var res v1.GeneralResponse[v1.FlexCdnTokenResponse]
  163. if err := json.Unmarshal(resBody, &res); err != nil {
  164. return "", fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  165. }
  166. if res.Code != 200 {
  167. return "", fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  168. }
  169. err = s.cdnRepository.PutToken(ctx, res.Data.Token)
  170. if err != nil {
  171. return "", err
  172. }
  173. return res.Data.Token, nil
  174. }
  175. func (s *cdnService) Token(ctx context.Context) (string, error) {
  176. token, err := s.cdnRepository.GetToken(ctx)
  177. if err != nil {
  178. return "", err
  179. }
  180. if token == "" {
  181. token, err = s.GetToken(ctx)
  182. if err != nil {
  183. return "", err
  184. }
  185. }
  186. return token, nil
  187. }
  188. // 注册用户
  189. func (s *cdnService) AddUser(ctx context.Context, req v1.User) (int64, error) {
  190. formData := map[string]interface{}{
  191. "id": req.ID,
  192. "username": req.Username,
  193. "password": "a7fKiKujgAzzsJ6", // 这个密码应该被妥善管理,而不是硬编码
  194. "fullname": req.Fullname,
  195. "mobile": req.Mobile,
  196. "tel": req.Tel,
  197. "email": req.Email,
  198. "remark": req.Remark,
  199. "source": req.Source,
  200. "nodeClusterId": 1,
  201. }
  202. apiUrl := s.Url + "UserService/createUser"
  203. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  204. if err != nil {
  205. return 0, err
  206. }
  207. type DataStr struct {
  208. UserId int64 `json:"userId" form:"userId"`
  209. }
  210. var res v1.GeneralResponse[DataStr]
  211. if err := json.Unmarshal(resBody, &res); err != nil {
  212. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  213. }
  214. if res.Code != 200 {
  215. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  216. }
  217. if res.Data.UserId == 0 {
  218. return 0, fmt.Errorf("添加用户失败")
  219. }
  220. return res.Data.UserId, nil
  221. }
  222. // 创建规则分组
  223. func (s *cdnService) CreateGroup(ctx context.Context, req v1.Group) (int64, error) {
  224. formData := map[string]interface{}{
  225. "name": req.Name,
  226. }
  227. apiUrl := s.Url + "ServerGroupService/createServerGroup"
  228. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  229. if err != nil {
  230. return 0, err
  231. }
  232. type DataStr struct {
  233. ServerGroupId int64 `json:"serverGroupId" form:"serverGroupId"`
  234. }
  235. var res v1.GeneralResponse[DataStr]
  236. if err := json.Unmarshal(resBody, &res); err != nil {
  237. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  238. }
  239. if res.Code != 200 {
  240. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  241. }
  242. if res.Data.ServerGroupId == 0 {
  243. return 0, fmt.Errorf("创建规则分组失败")
  244. }
  245. return res.Data.ServerGroupId, nil
  246. }
  247. // 分配套餐
  248. func (s *cdnService) BindPlan(ctx context.Context, req v1.Plan) (int64, error) {
  249. formData := map[string]interface{}{
  250. "userId": req.UserId,
  251. "planId": req.PlanId,
  252. "dayTo": req.DayTo,
  253. "period": req.Period,
  254. "countPeriod": req.CountPeriod,
  255. "name": req.Name,
  256. "isFree": req.IsFree,
  257. "periodDayTo": req.PeriodDayTo,
  258. }
  259. apiUrl := s.Url + "UserPlanService/buyUserPlan"
  260. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  261. if err != nil {
  262. return 0, err
  263. }
  264. type DataStr struct {
  265. UserPlanId int64 `json:"userPlanId" form:"userPlanId"`
  266. }
  267. var res v1.GeneralResponse[DataStr]
  268. if err := json.Unmarshal(resBody, &res); err != nil {
  269. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  270. }
  271. if res.Code != 200 {
  272. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  273. }
  274. if res.Data.UserPlanId == 0 {
  275. return 0, fmt.Errorf("分配套餐失败")
  276. }
  277. return res.Data.UserPlanId, nil
  278. }
  279. // 续费套餐
  280. func (s *cdnService) RenewPlan(ctx context.Context, req v1.RenewalPlan) error {
  281. formData := map[string]interface{}{
  282. "userPlanId": req.UserPlanId,
  283. "dayTo": req.DayTo,
  284. "period": req.Period,
  285. "countPeriod": req.CountPeriod,
  286. "isFree": req.IsFree,
  287. "periodDayTo": req.PeriodDayTo,
  288. }
  289. apiUrl := s.Url + "UserPlanService/renewUserPlan"
  290. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  291. if err != nil {
  292. return err
  293. }
  294. var res v1.GeneralResponse[any]
  295. if err := json.Unmarshal(resBody, &res); err != nil {
  296. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  297. }
  298. if res.Code != 200 {
  299. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  300. }
  301. return nil
  302. }
  303. // 创建网站
  304. func (s *cdnService) CreateWebsite(ctx context.Context, req v1.WebsiteSend) (int64, error) {
  305. formData := map[string]interface{}{
  306. "userId": req.UserId,
  307. "type": req.Type,
  308. "name": req.Name,
  309. "description": req.Description,
  310. "serverNamesJSON": req.ServerNamesJSON,
  311. "httpJSON": req.HttpJSON,
  312. "httpsJSON": req.HttpsJSON,
  313. "tcpJSON": req.TcpJSON,
  314. "tlsJSON": req.TlsJSON,
  315. "udpJSON": req.UdpJSON,
  316. "webId": req.WebId,
  317. "reverseProxyJSON": req.ReverseProxyJSON,
  318. "serverGroupIds": req.ServerGroupIds,
  319. "userPlanId": req.UserPlanId,
  320. "nodeClusterId": req.NodeClusterId,
  321. }
  322. apiUrl := s.Url + "ServerService/createServer"
  323. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  324. if err != nil {
  325. return 0, err
  326. }
  327. type DataStr struct {
  328. ServerId int64 `json:"serverId" form:"serverId"`
  329. }
  330. var res v1.GeneralResponse[DataStr]
  331. if err := json.Unmarshal(resBody, &res); err != nil {
  332. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  333. }
  334. if res.Code != 200 {
  335. return 0, fmt.Errorf("创建网站API 错误: code %d, msg '%s'", res.Code, res.Message)
  336. }
  337. if res.Data.ServerId == 0 {
  338. return 0, fmt.Errorf("创建网站失败")
  339. }
  340. return res.Data.ServerId, nil
  341. }
  342. func (s *cdnService) EditProtocol(ctx context.Context, req v1.ProxyJson, action string) error {
  343. formData := map[string]interface{}{
  344. "serverId": req.ServerId,
  345. }
  346. var apiUrl string
  347. switch action {
  348. case "tcp":
  349. formData["tcpJSON"] = req.JSON
  350. apiUrl = s.Url + "ServerService/updateServerTCP"
  351. case "tls":
  352. formData["tlsJSON"] = req.JSON
  353. apiUrl = s.Url + "ServerService/updateServerTLS"
  354. case "udp":
  355. formData["udpJSON"] = req.JSON
  356. apiUrl = s.Url + "ServerService/updateServerUDP"
  357. case "http":
  358. formData["httpJSON"] = req.JSON
  359. apiUrl = s.Url + "ServerService/updateServerHTTP"
  360. case "https":
  361. formData["httpsJSON"] = req.JSON
  362. apiUrl = s.Url + "ServerService/updateServerHTTPS"
  363. default:
  364. return fmt.Errorf("不支持的协议类型")
  365. }
  366. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  367. if err != nil {
  368. return err
  369. }
  370. var res v1.GeneralResponse[any]
  371. if err := json.Unmarshal(resBody, &res); err != nil {
  372. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  373. }
  374. if res.Code != 200 {
  375. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  376. }
  377. return nil
  378. }
  379. func (s *cdnService) CreateOrigin(ctx context.Context, req v1.Origin) (int64, error) {
  380. formData := map[string]interface{}{
  381. "name": req.Name,
  382. "addr": req.Addr,
  383. "ossJSON": req.OssJSON,
  384. "description": req.Description,
  385. "weight": req.Weight,
  386. "isOn": req.IsOn,
  387. "domains": req.Domains,
  388. "certRefJSON": req.CertRefJSON,
  389. "host": req.Host,
  390. "followPort": req.FollowPort,
  391. "http2Enabled": req.Http2Enabled,
  392. "tlsSecurityVerifyMode": req.TlsSecurityVerifyMode,
  393. }
  394. apiUrl := s.Url + "OriginService/createOrigin"
  395. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  396. if err != nil {
  397. return 0, err
  398. }
  399. type DataStr struct {
  400. OriginId int64 `json:"originId" form:"originId"`
  401. }
  402. var res v1.GeneralResponse[DataStr]
  403. if err := json.Unmarshal(resBody, &res); err != nil {
  404. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  405. }
  406. if res.Code != 200 {
  407. return 0, fmt.Errorf("添加源站API 错误: code %d, msg '%s'", res.Code, res.Message)
  408. }
  409. if res.Data.OriginId == 0 {
  410. return 0, fmt.Errorf("创建源站失败")
  411. }
  412. return res.Data.OriginId, nil
  413. }
  414. func (s *cdnService) EditServerType(ctx context.Context, req v1.EditWebsite, apiType string) error {
  415. typeName := apiType + "JSON"
  416. formData := map[string]interface{}{
  417. "serverId": req.Id,
  418. typeName: req.TypeJSON,
  419. }
  420. apiUrl := s.Url + "ServerService/updateServer" + strings.ToUpper(apiType)
  421. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  422. if err != nil {
  423. return err
  424. }
  425. var res v1.GeneralResponse[any]
  426. if err := json.Unmarshal(resBody, &res); err != nil {
  427. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  428. }
  429. if res.Code != 200 {
  430. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  431. }
  432. return nil
  433. }
  434. // EditOrigin 编辑源站
  435. func (s *cdnService) EditOrigin(ctx context.Context, req v1.Origin) error {
  436. formData := map[string]interface{}{
  437. "originId": req.OriginId,
  438. "name": req.Name,
  439. "addr": req.Addr,
  440. "ossJSON": req.OssJSON,
  441. "description": req.Description,
  442. "weight": req.Weight,
  443. "isOn": req.IsOn,
  444. "domains": req.Domains,
  445. "certRefJSON": req.CertRefJSON,
  446. "host": req.Host,
  447. "followPort": req.FollowPort,
  448. "http2Enabled": req.Http2Enabled,
  449. "tlsSecurityVerifyMode": req.TlsSecurityVerifyMode,
  450. }
  451. apiUrl := s.Url + "OriginService/updateOrigin"
  452. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl) // 使用封装后的方法
  453. if err != nil {
  454. return err
  455. }
  456. var res v1.GeneralResponse[any]
  457. if err := json.Unmarshal(resBody, &res); err != nil {
  458. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  459. }
  460. if res.Code != 200 {
  461. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  462. }
  463. return nil
  464. }
  465. // AddServerOrigin 网站绑定源站
  466. func (s *cdnService) AddServerOrigin(ctx context.Context, serverId int64, originId int64) error {
  467. formData := map[string]interface{}{
  468. "serverId": serverId,
  469. "originId": originId,
  470. "isPrimary": true,
  471. }
  472. apiUrl := s.Url + "ServerService/addServerOrigin"
  473. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  474. if err != nil {
  475. return err
  476. }
  477. var res v1.GeneralResponse[any]
  478. if err := json.Unmarshal(resBody, &res); err != nil {
  479. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  480. }
  481. if res.Code != 200 {
  482. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  483. }
  484. return nil
  485. }
  486. // EditOriginIsOn 编辑源站是否开启
  487. func (s *cdnService) EditOriginIsOn(ctx context.Context, originId int64, isOn bool) error {
  488. formData := map[string]interface{}{
  489. "originId": originId,
  490. "isOn": isOn,
  491. }
  492. apiUrl := s.Url + "OriginService/updateOriginIsOn"
  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. // EditServerBasic 修改网站基本信息
  507. func (s *cdnService) EditServerBasic(ctx context.Context, serverId int64, name string,nodeId int64) error {
  508. formData := map[string]interface{}{
  509. "serverId": serverId,
  510. "name": name,
  511. "nodeClusterId": nodeId,
  512. "isOn": true,
  513. }
  514. apiUrl := s.Url + "ServerService/updateServerBasic"
  515. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  516. if err != nil {
  517. return err
  518. }
  519. var res v1.GeneralResponse[any]
  520. if err := json.Unmarshal(resBody, &res); err != nil {
  521. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  522. }
  523. if res.Code != 200 {
  524. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  525. }
  526. return nil
  527. }
  528. // DelServerOrigin 从网站中删除某个源站
  529. func (s *cdnService) DelServerOrigin(ctx context.Context, serverId int64, originId int64) error {
  530. formData := map[string]interface{}{
  531. "serverId": serverId,
  532. "originId": originId,
  533. }
  534. apiUrl := s.Url + "ServerService/deleteServerOrigin"
  535. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  536. if err != nil {
  537. return err
  538. }
  539. var res v1.GeneralResponse[any]
  540. if err := json.Unmarshal(resBody, &res); err != nil {
  541. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  542. }
  543. if res.Code != 200 {
  544. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  545. }
  546. return nil
  547. }
  548. func (s *cdnService) DelServer(ctx context.Context, serverId int64) error {
  549. formData := map[string]interface{}{
  550. "serverId": serverId,
  551. }
  552. apiUrl := s.Url + "ServerService/deleteServer"
  553. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  554. if err != nil {
  555. return err
  556. }
  557. var res v1.GeneralResponse[any]
  558. if err := json.Unmarshal(resBody, &res); err != nil {
  559. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  560. }
  561. if res.Code != 200 {
  562. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  563. }
  564. return nil
  565. }
  566. // AddSSLCert 添加证书
  567. func (s *cdnService) AddSSLCert(ctx context.Context, req v1.SSlCert) (int64, error) {
  568. formData := map[string]interface{}{
  569. "isOn": req.IsOn,
  570. "userId": req.UserId,
  571. "name": req.Name,
  572. "serverName": req.ServerName,
  573. "description": req.Description,
  574. "isCA": req.IsCA,
  575. "certData": req.CertData,
  576. "keyData": req.KeyData,
  577. "timeBeginAt": req.TimeBeginAt,
  578. "timeEndAt": req.TimeEndAt,
  579. "dnsNames": req.DnsNames,
  580. "commonNames": req.CommonNames,
  581. "isSelfSigned": req.IsSelfSigned,
  582. }
  583. apiUrl := s.Url + "SSLCertService/createSSLCert"
  584. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  585. if err != nil {
  586. return 0, err
  587. }
  588. type DataStr struct {
  589. SslCertId int64 `json:"sslCertId" form:"sslCertId"`
  590. }
  591. var res v1.GeneralResponse[DataStr]
  592. if err := json.Unmarshal(resBody, &res); err != nil {
  593. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  594. }
  595. if res.Code != 200 {
  596. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  597. }
  598. return res.Data.SslCertId, nil
  599. }
  600. // 修改网站域名
  601. func (s *cdnService) EditServerName(ctx context.Context, req v1.EditServerNames) error {
  602. formData := map[string]interface{}{
  603. "serverId": req.ServerId,
  604. "serverNamesJSON": req.ServerNamesJSON,
  605. }
  606. apiUrl := s.Url + "ServerService/updateServerNames"
  607. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  608. if err != nil {
  609. return err
  610. }
  611. var res v1.GeneralResponse[any]
  612. if err := json.Unmarshal(resBody, &res); err != nil {
  613. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  614. }
  615. if res.Code != 200 {
  616. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  617. }
  618. return nil
  619. }
  620. // 添加ssl策略
  621. func (s *cdnService) AddSSLPolicy(ctx context.Context, req v1.AddSSLPolicy) (int64, error) {
  622. formData := map[string]interface{}{
  623. "http2Enabled": req.Http2Enabled,
  624. "http3Enabled": req.Http3Enabled,
  625. "minVersion": req.MinVersion,
  626. "sslCertsJSON": req.SslCertsJSON,
  627. "hstsJSON": req.HstsJSON,
  628. "clientAuthType": req.ClientAuthType,
  629. "cipherSuites": req.CipherSuites,
  630. "cipherSuitesIsOn": req.CipherSuitesIsOn,
  631. "ocspIsOn": req.OcspIsOn,
  632. }
  633. apiUrl := s.Url + "SSLPolicyService/createSSLPolicy"
  634. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  635. if err != nil {
  636. return 0, err
  637. }
  638. type DataStr struct {
  639. SslPolicyId int64 `json:"sslPolicyId" form:"sslPolicyId"`
  640. }
  641. var res v1.GeneralResponse[DataStr]
  642. if err := json.Unmarshal(resBody, &res); err != nil {
  643. return 0, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  644. }
  645. if res.Code != 200 {
  646. return 0, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  647. }
  648. return res.Data.SslPolicyId, nil
  649. }
  650. func (s *cdnService) DelSSLCert(ctx context.Context, sslCertId int64) error {
  651. formData := map[string]interface{}{
  652. "sslCertId": sslCertId,
  653. }
  654. apiUrl := s.Url + "SSLCertService/deleteSSLCert"
  655. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  656. if err != nil {
  657. return err
  658. }
  659. var res v1.GeneralResponse[any]
  660. if err := json.Unmarshal(resBody, &res); err != nil {
  661. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  662. }
  663. if res.Code != 200 {
  664. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  665. }
  666. return nil
  667. }
  668. func (s *cdnService) GetSSLPolicy(ctx context.Context, sslPolicyId int64) (v1.SSLPolicy, error) {
  669. formData := map[string]interface{}{
  670. "sslPolicyId": sslPolicyId,
  671. "ignoreData": true,
  672. }
  673. apiUrl := s.Url + "SSLPolicyService/findEnabledSSLPolicyConfig"
  674. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  675. if err != nil {
  676. return v1.SSLPolicy{}, err
  677. }
  678. var res v1.GeneralResponse[v1.SSLPolicy]
  679. if err := json.Unmarshal(resBody, &res); err != nil {
  680. return v1.SSLPolicy{}, fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  681. }
  682. if res.Code != 200 {
  683. return v1.SSLPolicy{}, fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  684. }
  685. return res.Data, nil
  686. }
  687. func (s *cdnService) EditSSLCert(ctx context.Context, req v1.SSlCert) error {
  688. formData := map[string]interface{}{
  689. "sslCertId": req.SslCertId,
  690. "userId": req.UserId,
  691. "isOn": req.IsOn,
  692. "name": req.Name,
  693. "description": req.Description,
  694. "isCA": req.IsCA,
  695. "certData": req.CertData,
  696. "keyData": req.KeyData,
  697. "timeBeginAt": req.TimeBeginAt,
  698. "timeEndAt": req.TimeEndAt,
  699. "dnsNames": req.DnsNames,
  700. "commonNames": req.CommonNames,
  701. "isSelfSigned": req.IsSelfSigned,
  702. }
  703. apiUrl := s.Url + "SSLCertService/updateSSLCert"
  704. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  705. if err != nil {
  706. return err
  707. }
  708. var res v1.GeneralResponse[any]
  709. if err := json.Unmarshal(resBody, &res); err != nil {
  710. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  711. }
  712. if res.Code != 200 {
  713. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  714. }
  715. return nil
  716. }
  717. func (s *cdnService) EditSSLPolicy(ctx context.Context, req v1.SSLPolicy) error {
  718. formData := map[string]interface{}{
  719. "sslPolicyId": req.SslPolicyId,
  720. "http2Enabled": req.Http2Enabled,
  721. "http3Enabled": req.Http3Enabled,
  722. "minVersion": req.MinVersion,
  723. "sslCertsJSON": req.SslCertsJSON,
  724. "hstsJSON": req.HstsJSON,
  725. "clientAuthType": req.ClientAuthType,
  726. "cipherSuites": req.CipherSuites,
  727. "cipherSuitesIsOn": req.CipherSuitesIsOn,
  728. }
  729. apiUrl := s.Url + "SSLPolicyService/updateSSLPolicy"
  730. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  731. if err != nil {
  732. return err
  733. }
  734. var res v1.GeneralResponse[any]
  735. if err := json.Unmarshal(resBody, &res); err != nil {
  736. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  737. }
  738. if res.Code != 200 {
  739. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  740. }
  741. return nil
  742. }
  743. // 修改反向代理
  744. func (s *cdnService) EditProxy(ctx context.Context, req v1.Proxy) error {
  745. formData := map[string]interface{}{
  746. "reverseProxyId" : req.ReverseProxyId,
  747. "requestHostType" : req.RequestHostType,
  748. "requestHost" : req.RequestHost,
  749. "requestHostExcludingPort" : req.RequestHostExcludingPort,
  750. "requestURI" : req.RequestURI,
  751. "stripPrefix" : req.StripPrefix,
  752. "autoFlush" : req.AutoFlush,
  753. "addHeaders" : req.AddHeaders,
  754. "proxyProtocolJSON": req.ProxyProtocolJSON,
  755. "followRedirects" : req.FollowRedirects,
  756. "retry50X" : req.Retry50X,
  757. "retry40X" : req.Retry40X,
  758. }
  759. apiUrl := s.Url + "ReverseProxyService/updateReverseProxy"
  760. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  761. if err != nil {
  762. return err
  763. }
  764. var res v1.GeneralResponse[any]
  765. if err := json.Unmarshal(resBody, &res); err != nil {
  766. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  767. }
  768. if res.Code != 200 {
  769. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  770. }
  771. return nil
  772. }
  773. // 修改网站日志配置
  774. func (s *cdnService) EditWebLog(ctx context.Context,webId int64, req v1.WebLog) error {
  775. reqJson, err := json.Marshal(req)
  776. if err != nil {
  777. return err
  778. }
  779. formData := map[string]interface{}{
  780. "httpWebId": webId,
  781. "accessLogJSON": reqJson,
  782. }
  783. apiUrl := s.Url + "HTTPWebService/updateHTTPWebAccessLog"
  784. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  785. if err != nil {
  786. return err
  787. }
  788. var res v1.GeneralResponse[any]
  789. if err := json.Unmarshal(resBody, &res); err != nil {
  790. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  791. }
  792. if res.Code != 200 {
  793. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  794. }
  795. return nil
  796. }
  797. // 修改网站CC配置
  798. func (s *cdnService) EditCcConfig(ctx context.Context,webId int64, req v1.CcConfig) error {
  799. reqJson, err := json.Marshal(req)
  800. if err != nil {
  801. return err
  802. }
  803. formData := map[string]interface{}{
  804. "httpWebId": webId,
  805. "ccJSON": reqJson,
  806. }
  807. apiUrl := s.Url + "HTTPWebService/updateHTTPWebCC"
  808. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  809. if err != nil {
  810. return err
  811. }
  812. var res v1.GeneralResponse[any]
  813. if err := json.Unmarshal(resBody, &res); err != nil {
  814. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  815. }
  816. if res.Code != 200 {
  817. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  818. }
  819. return nil
  820. }
  821. // 创建websockets配置
  822. func (s *cdnService) AddWebSockets(ctx context.Context, req v1.WebSocket) (int64,error) {
  823. formData := map[string]interface{}{
  824. "handshakeTimeoutJSON": req.HandshakeTimeoutJSON,
  825. "allowAllOrigins" : req.AllowAllOrigins,
  826. "allowedOrigins" : req.AllowedOrigins,
  827. "requestSameOrigin" : req.RequestSameOrigin,
  828. "requestOrigin" : req.RequestOrigin,
  829. }
  830. apiUrl := s.Url + "HTTPWebsocketService/createHTTPWebsocket"
  831. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  832. if err != nil {
  833. return 0,err
  834. }
  835. type WebSocket struct {
  836. WebSocketId int64 `json:"websocketId"`
  837. }
  838. var res v1.GeneralResponse[WebSocket]
  839. if err := json.Unmarshal(resBody, &res); err != nil {
  840. return 0,fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  841. }
  842. if res.Code != 200 {
  843. return 0,fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  844. }
  845. return res.Data.WebSocketId,nil
  846. }
  847. func (s *cdnService) EditWebSockets(ctx context.Context,req v1.WebSocket) error {
  848. formData := map[string]interface{}{
  849. "websocketId" : req.WebsocketId,
  850. "handshakeTimeoutJSON": req.HandshakeTimeoutJSON,
  851. "allowAllOrigins" : req.AllowAllOrigins,
  852. "allowedOrigins" : req.AllowedOrigins,
  853. "requestSameOrigin" : req.RequestSameOrigin,
  854. "requestOrigin" : req.RequestOrigin,
  855. }
  856. apiUrl := s.Url + "HTTPWebsocketService/updateHTTPWebsocket"
  857. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  858. if err != nil {
  859. return err
  860. }
  861. var res v1.GeneralResponse[any]
  862. if err := json.Unmarshal(resBody, &res); err != nil {
  863. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  864. }
  865. if res.Code != 200 {
  866. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  867. }
  868. return nil
  869. }
  870. // 启用/禁用websockets
  871. func (s *cdnService) EditHTTPWebWebsocket(ctx context.Context,websocketId int64,websocketJSON []byte) error {
  872. formData := map[string]interface{}{
  873. "httpWebId" : websocketId,
  874. "websocketJSON": websocketJSON,
  875. }
  876. apiUrl := s.Url + "HTTPWebService/updateHTTPWebWebsocket"
  877. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  878. if err != nil {
  879. return err
  880. }
  881. var res v1.GeneralResponse[any]
  882. if err := json.Unmarshal(resBody, &res); err != nil {
  883. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  884. }
  885. if res.Code != 200 {
  886. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  887. }
  888. return nil
  889. }
  890. // 启用/禁用网站
  891. func (s *cdnService) EditWebIsOn(ctx context.Context,serverId int64,isOn bool) error {
  892. formData := map[string]interface{}{
  893. "serverId": serverId,
  894. "isOn": isOn,
  895. }
  896. apiUrl := s.Url + "ServerService/updateServerIsOn"
  897. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  898. if err != nil {
  899. return err
  900. }
  901. var res v1.GeneralResponse[any]
  902. if err := json.Unmarshal(resBody, &res); err != nil {
  903. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  904. }
  905. if res.Code != 200 {
  906. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  907. }
  908. return nil
  909. }
  910. // 删除已购套餐
  911. func (s *cdnService) DelUserPlan(ctx context.Context,planId int64) error {
  912. formData := map[string]interface{}{
  913. "userPlanId": planId,
  914. }
  915. apiUrl := s.Url + "UserPlanService/deleteUserPlan"
  916. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  917. if err != nil {
  918. return err
  919. }
  920. var res v1.GeneralResponse[any]
  921. if err := json.Unmarshal(resBody, &res); err != nil {
  922. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  923. }
  924. if res.Code != 200 {
  925. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  926. }
  927. return nil
  928. }
  929. // 删除网站分组
  930. func (s *cdnService) DelServerGroup(ctx context.Context,serverId int64) error {
  931. formData := map[string]interface{}{
  932. "serverId": serverId,
  933. }
  934. apiUrl := s.Url + "ServerService/deleteServer"
  935. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  936. if err != nil {
  937. return err
  938. }
  939. var res v1.GeneralResponse[any]
  940. if err := json.Unmarshal(resBody, &res); err != nil {
  941. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  942. }
  943. if res.Code != 200 {
  944. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  945. }
  946. return nil
  947. }
  948. // 删除IP
  949. func (s *cdnService) DelIpItem(ctx context.Context,ipitemId int64,value string,ipFrom string,ipTo string,ipListId int64) error {
  950. formData := map[string]interface{}{
  951. "ipitemId": ipitemId,
  952. "value": value,
  953. "ipFrom": ipFrom,
  954. "ipTo": ipTo,
  955. "ipListId": ipListId,
  956. }
  957. apiUrl := s.Url + "IPItemService/deleteIPItem"
  958. resBody, err := s.sendDataWithTokenRetry(ctx, formData, apiUrl)
  959. if err != nil {
  960. return err
  961. }
  962. var res v1.GeneralResponse[any]
  963. if err := json.Unmarshal(resBody, &res); err != nil {
  964. return fmt.Errorf("反序列化响应 JSON 失败 (内容: %s): %w", string(resBody), err)
  965. }
  966. if res.Code != 200 {
  967. return fmt.Errorf("API 错误: code %d, msg '%s'", res.Code, res.Message)
  968. }
  969. return nil
  970. }