groups.go 2.4 KB

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