123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- package route
- import (
- "context"
- "net/http"
- C "github.com/metacubex/mihomo/constant"
- "github.com/metacubex/mihomo/constant/provider"
- "github.com/metacubex/mihomo/tunnel"
- "github.com/go-chi/chi/v5"
- "github.com/go-chi/render"
- "github.com/samber/lo"
- )
- func proxyProviderRouter() http.Handler {
- r := chi.NewRouter()
- r.Get("/", getProviders)
- r.Route("/{providerName}", func(r chi.Router) {
- r.Use(parseProviderName, findProviderByName)
- r.Get("/", getProvider)
- r.Put("/", updateProvider)
- r.Get("/healthcheck", healthCheckProvider)
- r.Mount("/", proxyProviderProxyRouter())
- })
- return r
- }
- func proxyProviderProxyRouter() http.Handler {
- r := chi.NewRouter()
- r.Route("/{name}", func(r chi.Router) {
- r.Use(parseProxyName, findProviderProxyByName)
- r.Get("/", getProxy)
- r.Get("/healthcheck", getProxyDelay)
- })
- return r
- }
- func getProviders(w http.ResponseWriter, r *http.Request) {
- providers := tunnel.Providers()
- render.JSON(w, r, render.M{
- "providers": providers,
- })
- }
- func getProvider(w http.ResponseWriter, r *http.Request) {
- provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
- render.JSON(w, r, provider)
- }
- func updateProvider(w http.ResponseWriter, r *http.Request) {
- provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
- if err := provider.Update(); err != nil {
- render.Status(r, http.StatusServiceUnavailable)
- render.JSON(w, r, newError(err.Error()))
- return
- }
- render.NoContent(w, r)
- }
- func healthCheckProvider(w http.ResponseWriter, r *http.Request) {
- provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
- provider.HealthCheck()
- render.NoContent(w, r)
- }
- func parseProviderName(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- name := getEscapeParam(r, "providerName")
- ctx := context.WithValue(r.Context(), CtxKeyProviderName, name)
- next.ServeHTTP(w, r.WithContext(ctx))
- })
- }
- func findProviderByName(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- name := r.Context().Value(CtxKeyProviderName).(string)
- providers := tunnel.Providers()
- provider, exist := providers[name]
- if !exist {
- render.Status(r, http.StatusNotFound)
- render.JSON(w, r, ErrNotFound)
- return
- }
- ctx := context.WithValue(r.Context(), CtxKeyProvider, provider)
- next.ServeHTTP(w, r.WithContext(ctx))
- })
- }
- func findProviderProxyByName(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- var (
- name = r.Context().Value(CtxKeyProxyName).(string)
- pd = r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
- )
- proxy, exist := lo.Find(pd.Proxies(), func(proxy C.Proxy) bool {
- return proxy.Name() == name
- })
- if !exist {
- render.Status(r, http.StatusNotFound)
- render.JSON(w, r, ErrNotFound)
- return
- }
- ctx := context.WithValue(r.Context(), CtxKeyProxy, proxy)
- next.ServeHTTP(w, r.WithContext(ctx))
- })
- }
- func ruleProviderRouter() http.Handler {
- r := chi.NewRouter()
- r.Get("/", getRuleProviders)
- r.Route("/{name}", func(r chi.Router) {
- r.Use(parseRuleProviderName, findRuleProviderByName)
- r.Put("/", updateRuleProvider)
- })
- return r
- }
- func getRuleProviders(w http.ResponseWriter, r *http.Request) {
- ruleProviders := tunnel.RuleProviders()
- render.JSON(w, r, render.M{
- "providers": ruleProviders,
- })
- }
- func updateRuleProvider(w http.ResponseWriter, r *http.Request) {
- provider := r.Context().Value(CtxKeyProvider).(provider.RuleProvider)
- if err := provider.Update(); err != nil {
- render.Status(r, http.StatusServiceUnavailable)
- render.JSON(w, r, newError(err.Error()))
- return
- }
- render.NoContent(w, r)
- }
- func parseRuleProviderName(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- name := getEscapeParam(r, "name")
- ctx := context.WithValue(r.Context(), CtxKeyProviderName, name)
- next.ServeHTTP(w, r.WithContext(ctx))
- })
- }
- func findRuleProviderByName(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- name := r.Context().Value(CtxKeyProviderName).(string)
- providers := tunnel.RuleProviders()
- provider, exist := providers[name]
- if !exist {
- render.Status(r, http.StatusNotFound)
- render.JSON(w, r, ErrNotFound)
- return
- }
- ctx := context.WithValue(r.Context(), CtxKeyProvider, provider)
- next.ServeHTTP(w, r.WithContext(ctx))
- })
- }
|