error_passthrough_handler.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. package admin
  2. import (
  3. "strconv"
  4. "github.com/Wei-Shaw/sub2api/internal/model"
  5. "github.com/Wei-Shaw/sub2api/internal/pkg/response"
  6. "github.com/Wei-Shaw/sub2api/internal/service"
  7. "github.com/gin-gonic/gin"
  8. )
  9. // ErrorPassthroughHandler 处理错误透传规则的 HTTP 请求
  10. type ErrorPassthroughHandler struct {
  11. service *service.ErrorPassthroughService
  12. }
  13. // NewErrorPassthroughHandler 创建错误透传规则处理器
  14. func NewErrorPassthroughHandler(service *service.ErrorPassthroughService) *ErrorPassthroughHandler {
  15. return &ErrorPassthroughHandler{service: service}
  16. }
  17. // CreateErrorPassthroughRuleRequest 创建规则请求
  18. type CreateErrorPassthroughRuleRequest struct {
  19. Name string `json:"name" binding:"required"`
  20. Enabled *bool `json:"enabled"`
  21. Priority int `json:"priority"`
  22. ErrorCodes []int `json:"error_codes"`
  23. Keywords []string `json:"keywords"`
  24. MatchMode string `json:"match_mode"`
  25. Platforms []string `json:"platforms"`
  26. PassthroughCode *bool `json:"passthrough_code"`
  27. ResponseCode *int `json:"response_code"`
  28. PassthroughBody *bool `json:"passthrough_body"`
  29. CustomMessage *string `json:"custom_message"`
  30. SkipMonitoring *bool `json:"skip_monitoring"`
  31. Description *string `json:"description"`
  32. }
  33. // UpdateErrorPassthroughRuleRequest 更新规则请求(部分更新,所有字段可选)
  34. type UpdateErrorPassthroughRuleRequest struct {
  35. Name *string `json:"name"`
  36. Enabled *bool `json:"enabled"`
  37. Priority *int `json:"priority"`
  38. ErrorCodes []int `json:"error_codes"`
  39. Keywords []string `json:"keywords"`
  40. MatchMode *string `json:"match_mode"`
  41. Platforms []string `json:"platforms"`
  42. PassthroughCode *bool `json:"passthrough_code"`
  43. ResponseCode *int `json:"response_code"`
  44. PassthroughBody *bool `json:"passthrough_body"`
  45. CustomMessage *string `json:"custom_message"`
  46. SkipMonitoring *bool `json:"skip_monitoring"`
  47. Description *string `json:"description"`
  48. }
  49. // List 获取所有规则
  50. // GET /api/v1/admin/error-passthrough-rules
  51. func (h *ErrorPassthroughHandler) List(c *gin.Context) {
  52. rules, err := h.service.List(c.Request.Context())
  53. if err != nil {
  54. response.ErrorFrom(c, err)
  55. return
  56. }
  57. response.Success(c, rules)
  58. }
  59. // GetByID 根据 ID 获取规则
  60. // GET /api/v1/admin/error-passthrough-rules/:id
  61. func (h *ErrorPassthroughHandler) GetByID(c *gin.Context) {
  62. id, err := strconv.ParseInt(c.Param("id"), 10, 64)
  63. if err != nil {
  64. response.BadRequest(c, "Invalid rule ID")
  65. return
  66. }
  67. rule, err := h.service.GetByID(c.Request.Context(), id)
  68. if err != nil {
  69. response.ErrorFrom(c, err)
  70. return
  71. }
  72. if rule == nil {
  73. response.NotFound(c, "Rule not found")
  74. return
  75. }
  76. response.Success(c, rule)
  77. }
  78. // Create 创建规则
  79. // POST /api/v1/admin/error-passthrough-rules
  80. func (h *ErrorPassthroughHandler) Create(c *gin.Context) {
  81. var req CreateErrorPassthroughRuleRequest
  82. if err := c.ShouldBindJSON(&req); err != nil {
  83. response.BadRequest(c, "Invalid request: "+err.Error())
  84. return
  85. }
  86. rule := &model.ErrorPassthroughRule{
  87. Name: req.Name,
  88. Priority: req.Priority,
  89. ErrorCodes: req.ErrorCodes,
  90. Keywords: req.Keywords,
  91. Platforms: req.Platforms,
  92. }
  93. // 设置默认值
  94. if req.Enabled != nil {
  95. rule.Enabled = *req.Enabled
  96. } else {
  97. rule.Enabled = true
  98. }
  99. if req.MatchMode != "" {
  100. rule.MatchMode = req.MatchMode
  101. } else {
  102. rule.MatchMode = model.MatchModeAny
  103. }
  104. if req.PassthroughCode != nil {
  105. rule.PassthroughCode = *req.PassthroughCode
  106. } else {
  107. rule.PassthroughCode = true
  108. }
  109. if req.PassthroughBody != nil {
  110. rule.PassthroughBody = *req.PassthroughBody
  111. } else {
  112. rule.PassthroughBody = true
  113. }
  114. if req.SkipMonitoring != nil {
  115. rule.SkipMonitoring = *req.SkipMonitoring
  116. }
  117. rule.ResponseCode = req.ResponseCode
  118. rule.CustomMessage = req.CustomMessage
  119. rule.Description = req.Description
  120. // 确保切片不为 nil
  121. if rule.ErrorCodes == nil {
  122. rule.ErrorCodes = []int{}
  123. }
  124. if rule.Keywords == nil {
  125. rule.Keywords = []string{}
  126. }
  127. if rule.Platforms == nil {
  128. rule.Platforms = []string{}
  129. }
  130. created, err := h.service.Create(c.Request.Context(), rule)
  131. if err != nil {
  132. if _, ok := err.(*model.ValidationError); ok {
  133. response.BadRequest(c, err.Error())
  134. return
  135. }
  136. response.ErrorFrom(c, err)
  137. return
  138. }
  139. response.Success(c, created)
  140. }
  141. // Update 更新规则(支持部分更新)
  142. // PUT /api/v1/admin/error-passthrough-rules/:id
  143. func (h *ErrorPassthroughHandler) Update(c *gin.Context) {
  144. id, err := strconv.ParseInt(c.Param("id"), 10, 64)
  145. if err != nil {
  146. response.BadRequest(c, "Invalid rule ID")
  147. return
  148. }
  149. var req UpdateErrorPassthroughRuleRequest
  150. if err := c.ShouldBindJSON(&req); err != nil {
  151. response.BadRequest(c, "Invalid request: "+err.Error())
  152. return
  153. }
  154. // 先获取现有规则
  155. existing, err := h.service.GetByID(c.Request.Context(), id)
  156. if err != nil {
  157. response.ErrorFrom(c, err)
  158. return
  159. }
  160. if existing == nil {
  161. response.NotFound(c, "Rule not found")
  162. return
  163. }
  164. // 部分更新:只更新请求中提供的字段
  165. rule := &model.ErrorPassthroughRule{
  166. ID: id,
  167. Name: existing.Name,
  168. Enabled: existing.Enabled,
  169. Priority: existing.Priority,
  170. ErrorCodes: existing.ErrorCodes,
  171. Keywords: existing.Keywords,
  172. MatchMode: existing.MatchMode,
  173. Platforms: existing.Platforms,
  174. PassthroughCode: existing.PassthroughCode,
  175. ResponseCode: existing.ResponseCode,
  176. PassthroughBody: existing.PassthroughBody,
  177. CustomMessage: existing.CustomMessage,
  178. SkipMonitoring: existing.SkipMonitoring,
  179. Description: existing.Description,
  180. }
  181. // 应用请求中提供的更新
  182. if req.Name != nil {
  183. rule.Name = *req.Name
  184. }
  185. if req.Enabled != nil {
  186. rule.Enabled = *req.Enabled
  187. }
  188. if req.Priority != nil {
  189. rule.Priority = *req.Priority
  190. }
  191. if req.ErrorCodes != nil {
  192. rule.ErrorCodes = req.ErrorCodes
  193. }
  194. if req.Keywords != nil {
  195. rule.Keywords = req.Keywords
  196. }
  197. if req.MatchMode != nil {
  198. rule.MatchMode = *req.MatchMode
  199. }
  200. if req.Platforms != nil {
  201. rule.Platforms = req.Platforms
  202. }
  203. if req.PassthroughCode != nil {
  204. rule.PassthroughCode = *req.PassthroughCode
  205. }
  206. if req.ResponseCode != nil {
  207. rule.ResponseCode = req.ResponseCode
  208. }
  209. if req.PassthroughBody != nil {
  210. rule.PassthroughBody = *req.PassthroughBody
  211. }
  212. if req.CustomMessage != nil {
  213. rule.CustomMessage = req.CustomMessage
  214. }
  215. if req.Description != nil {
  216. rule.Description = req.Description
  217. }
  218. if req.SkipMonitoring != nil {
  219. rule.SkipMonitoring = *req.SkipMonitoring
  220. }
  221. // 确保切片不为 nil
  222. if rule.ErrorCodes == nil {
  223. rule.ErrorCodes = []int{}
  224. }
  225. if rule.Keywords == nil {
  226. rule.Keywords = []string{}
  227. }
  228. if rule.Platforms == nil {
  229. rule.Platforms = []string{}
  230. }
  231. updated, err := h.service.Update(c.Request.Context(), rule)
  232. if err != nil {
  233. if _, ok := err.(*model.ValidationError); ok {
  234. response.BadRequest(c, err.Error())
  235. return
  236. }
  237. response.ErrorFrom(c, err)
  238. return
  239. }
  240. response.Success(c, updated)
  241. }
  242. // Delete 删除规则
  243. // DELETE /api/v1/admin/error-passthrough-rules/:id
  244. func (h *ErrorPassthroughHandler) Delete(c *gin.Context) {
  245. id, err := strconv.ParseInt(c.Param("id"), 10, 64)
  246. if err != nil {
  247. response.BadRequest(c, "Invalid rule ID")
  248. return
  249. }
  250. if err := h.service.Delete(c.Request.Context(), id); err != nil {
  251. response.ErrorFrom(c, err)
  252. return
  253. }
  254. response.Success(c, gin.H{"message": "Rule deleted successfully"})
  255. }