github.com/metacubex/mihomo@v1.18.5/hub/route/groups.go (about) 1 package route 2 3 import ( 4 "context" 5 "net/http" 6 "strconv" 7 "time" 8 9 "github.com/go-chi/chi/v5" 10 "github.com/go-chi/render" 11 12 "github.com/metacubex/mihomo/adapter" 13 "github.com/metacubex/mihomo/adapter/outboundgroup" 14 "github.com/metacubex/mihomo/common/utils" 15 "github.com/metacubex/mihomo/component/profile/cachefile" 16 C "github.com/metacubex/mihomo/constant" 17 "github.com/metacubex/mihomo/tunnel" 18 ) 19 20 func GroupRouter() http.Handler { 21 r := chi.NewRouter() 22 r.Get("/", getGroups) 23 24 r.Route("/{name}", func(r chi.Router) { 25 r.Use(parseProxyName, findProxyByName) 26 r.Get("/", getGroup) 27 r.Get("/delay", getGroupDelay) 28 }) 29 return r 30 } 31 32 func getGroups(w http.ResponseWriter, r *http.Request) { 33 var gs []C.Proxy 34 for _, p := range tunnel.Proxies() { 35 if _, ok := p.(*adapter.Proxy).ProxyAdapter.(C.Group); ok { 36 gs = append(gs, p) 37 } 38 } 39 render.JSON(w, r, render.M{ 40 "proxies": gs, 41 }) 42 } 43 44 func getGroup(w http.ResponseWriter, r *http.Request) { 45 proxy := r.Context().Value(CtxKeyProxy).(C.Proxy) 46 if _, ok := proxy.(*adapter.Proxy).ProxyAdapter.(C.Group); ok { 47 render.JSON(w, r, proxy) 48 return 49 } 50 render.Status(r, http.StatusNotFound) 51 render.JSON(w, r, ErrNotFound) 52 } 53 54 func getGroupDelay(w http.ResponseWriter, r *http.Request) { 55 proxy := r.Context().Value(CtxKeyProxy).(C.Proxy) 56 group, ok := proxy.(*adapter.Proxy).ProxyAdapter.(C.Group) 57 if !ok { 58 render.Status(r, http.StatusNotFound) 59 render.JSON(w, r, ErrNotFound) 60 return 61 } 62 63 if proxy.(*adapter.Proxy).Type() == C.URLTest { 64 URLTestGroup := proxy.(*adapter.Proxy).ProxyAdapter.(*outboundgroup.URLTest) 65 URLTestGroup.ForceSet("") 66 } 67 68 if proxy.(*adapter.Proxy).Type() != C.Selector { 69 cachefile.Cache().SetSelected(proxy.Name(), "") 70 } 71 72 query := r.URL.Query() 73 url := query.Get("url") 74 timeout, err := strconv.ParseInt(query.Get("timeout"), 10, 32) 75 if err != nil { 76 render.Status(r, http.StatusBadRequest) 77 render.JSON(w, r, ErrBadRequest) 78 return 79 } 80 81 expectedStatus, err := utils.NewUnsignedRanges[uint16](query.Get("expected")) 82 if err != nil { 83 render.Status(r, http.StatusBadRequest) 84 render.JSON(w, r, ErrBadRequest) 85 return 86 } 87 88 ctx, cancel := context.WithTimeout(r.Context(), time.Millisecond*time.Duration(timeout)) 89 defer cancel() 90 91 dm, err := group.URLTest(ctx, url, expectedStatus) 92 if err != nil { 93 render.Status(r, http.StatusGatewayTimeout) 94 render.JSON(w, r, newError(err.Error())) 95 return 96 } 97 98 render.JSON(w, r, dm) 99 }