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  }