provider.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package route
  2. import (
  3. "context"
  4. "net/http"
  5. C "github.com/metacubex/mihomo/constant"
  6. "github.com/metacubex/mihomo/constant/provider"
  7. "github.com/metacubex/mihomo/tunnel"
  8. "github.com/go-chi/chi/v5"
  9. "github.com/go-chi/render"
  10. "github.com/samber/lo"
  11. )
  12. func proxyProviderRouter() http.Handler {
  13. r := chi.NewRouter()
  14. r.Get("/", getProviders)
  15. r.Route("/{providerName}", func(r chi.Router) {
  16. r.Use(parseProviderName, findProviderByName)
  17. r.Get("/", getProvider)
  18. r.Put("/", updateProvider)
  19. r.Get("/healthcheck", healthCheckProvider)
  20. r.Mount("/", proxyProviderProxyRouter())
  21. })
  22. return r
  23. }
  24. func proxyProviderProxyRouter() http.Handler {
  25. r := chi.NewRouter()
  26. r.Route("/{name}", func(r chi.Router) {
  27. r.Use(parseProxyName, findProviderProxyByName)
  28. r.Get("/", getProxy)
  29. r.Get("/healthcheck", getProxyDelay)
  30. })
  31. return r
  32. }
  33. func getProviders(w http.ResponseWriter, r *http.Request) {
  34. providers := tunnel.Providers()
  35. render.JSON(w, r, render.M{
  36. "providers": providers,
  37. })
  38. }
  39. func getProvider(w http.ResponseWriter, r *http.Request) {
  40. provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
  41. render.JSON(w, r, provider)
  42. }
  43. func updateProvider(w http.ResponseWriter, r *http.Request) {
  44. provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
  45. if err := provider.Update(); err != nil {
  46. render.Status(r, http.StatusServiceUnavailable)
  47. render.JSON(w, r, newError(err.Error()))
  48. return
  49. }
  50. render.NoContent(w, r)
  51. }
  52. func healthCheckProvider(w http.ResponseWriter, r *http.Request) {
  53. provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
  54. provider.HealthCheck()
  55. render.NoContent(w, r)
  56. }
  57. func parseProviderName(next http.Handler) http.Handler {
  58. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  59. name := getEscapeParam(r, "providerName")
  60. ctx := context.WithValue(r.Context(), CtxKeyProviderName, name)
  61. next.ServeHTTP(w, r.WithContext(ctx))
  62. })
  63. }
  64. func findProviderByName(next http.Handler) http.Handler {
  65. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  66. name := r.Context().Value(CtxKeyProviderName).(string)
  67. providers := tunnel.Providers()
  68. provider, exist := providers[name]
  69. if !exist {
  70. render.Status(r, http.StatusNotFound)
  71. render.JSON(w, r, ErrNotFound)
  72. return
  73. }
  74. ctx := context.WithValue(r.Context(), CtxKeyProvider, provider)
  75. next.ServeHTTP(w, r.WithContext(ctx))
  76. })
  77. }
  78. func findProviderProxyByName(next http.Handler) http.Handler {
  79. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  80. var (
  81. name = r.Context().Value(CtxKeyProxyName).(string)
  82. pd = r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
  83. )
  84. proxy, exist := lo.Find(pd.Proxies(), func(proxy C.Proxy) bool {
  85. return proxy.Name() == name
  86. })
  87. if !exist {
  88. render.Status(r, http.StatusNotFound)
  89. render.JSON(w, r, ErrNotFound)
  90. return
  91. }
  92. ctx := context.WithValue(r.Context(), CtxKeyProxy, proxy)
  93. next.ServeHTTP(w, r.WithContext(ctx))
  94. })
  95. }
  96. func ruleProviderRouter() http.Handler {
  97. r := chi.NewRouter()
  98. r.Get("/", getRuleProviders)
  99. r.Route("/{name}", func(r chi.Router) {
  100. r.Use(parseRuleProviderName, findRuleProviderByName)
  101. r.Put("/", updateRuleProvider)
  102. })
  103. return r
  104. }
  105. func getRuleProviders(w http.ResponseWriter, r *http.Request) {
  106. ruleProviders := tunnel.RuleProviders()
  107. render.JSON(w, r, render.M{
  108. "providers": ruleProviders,
  109. })
  110. }
  111. func updateRuleProvider(w http.ResponseWriter, r *http.Request) {
  112. provider := r.Context().Value(CtxKeyProvider).(provider.RuleProvider)
  113. if err := provider.Update(); err != nil {
  114. render.Status(r, http.StatusServiceUnavailable)
  115. render.JSON(w, r, newError(err.Error()))
  116. return
  117. }
  118. render.NoContent(w, r)
  119. }
  120. func parseRuleProviderName(next http.Handler) http.Handler {
  121. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  122. name := getEscapeParam(r, "name")
  123. ctx := context.WithValue(r.Context(), CtxKeyProviderName, name)
  124. next.ServeHTTP(w, r.WithContext(ctx))
  125. })
  126. }
  127. func findRuleProviderByName(next http.Handler) http.Handler {
  128. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  129. name := r.Context().Value(CtxKeyProviderName).(string)
  130. providers := tunnel.RuleProviders()
  131. provider, exist := providers[name]
  132. if !exist {
  133. render.Status(r, http.StatusNotFound)
  134. render.JSON(w, r, ErrNotFound)
  135. return
  136. }
  137. ctx := context.WithValue(r.Context(), CtxKeyProvider, provider)
  138. next.ServeHTTP(w, r.WithContext(ctx))
  139. })
  140. }