package api import ( "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "github.com/prism/proxy/internal/rulematch" ) type testRuleReq struct { URL string `json:"url"` } func (s *Server) mergedRules(c *gin.Context) { limit, offset := parseLimitOffset(c.DefaultQuery("limit", "50"), c.DefaultQuery("offset", "0")) items, err := s.app.Store.ListMergedRulesPage(c.Request.Context(), limit, offset) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } total, err := s.app.Store.CountMergedRules(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } settings, _ := s.app.Store.GetSettings(c.Request.Context()) policy := settings["default_policy"] if policy == "" { policy = "DIRECT" } c.JSON(http.StatusOK, gin.H{ "items": items, "total": total, "limit": limit, "offset": offset, "default_policy": policy, }) } func (s *Server) testRule(c *gin.Context) { var req testRuleReq if err := c.ShouldBindJSON(&req); err != nil || strings.TrimSpace(req.URL) == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "url required"}) return } ctx := c.Request.Context() rules, err := s.app.Store.ListRules(ctx, "") if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } settings, _ := s.app.Store.GetSettings(ctx) policy := settings["default_policy"] geoReady := geoDataReady(s.app.DataDir) result := rulematch.Match(rules, policy, req.URL, geoReady) if result.SkippedGeo > 0 { result.Note = appendNote(result.Note, "已跳过 "+strconv.Itoa(result.SkippedGeo)+" 条 Geo 规则(本地测试不支持 GEOIP/GEOSITE)") } c.JSON(http.StatusOK, result) } func appendNote(existing, extra string) string { if existing == "" { return extra } return existing + ";" + extra }