github.com/chwjbn/xclash@v0.2.0/hub/route/provider.go (about) 1 package route 2 3 import ( 4 "context" 5 "net/http" 6 7 "github.com/chwjbn/xclash/constant/provider" 8 "github.com/chwjbn/xclash/tunnel" 9 10 "github.com/go-chi/chi/v5" 11 "github.com/go-chi/render" 12 ) 13 14 func proxyProviderRouter() http.Handler { 15 r := chi.NewRouter() 16 r.Get("/", getProviders) 17 18 r.Route("/{name}", func(r chi.Router) { 19 r.Use(parseProviderName, findProviderByName) 20 r.Get("/", getProvider) 21 r.Put("/", updateProvider) 22 r.Get("/healthcheck", healthCheckProvider) 23 }) 24 return r 25 } 26 27 func getProviders(w http.ResponseWriter, r *http.Request) { 28 providers := tunnel.Providers() 29 render.JSON(w, r, render.M{ 30 "providers": providers, 31 }) 32 } 33 34 func getProvider(w http.ResponseWriter, r *http.Request) { 35 provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider) 36 render.JSON(w, r, provider) 37 } 38 39 func updateProvider(w http.ResponseWriter, r *http.Request) { 40 provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider) 41 if err := provider.Update(); err != nil { 42 render.Status(r, http.StatusServiceUnavailable) 43 render.JSON(w, r, newError(err.Error())) 44 return 45 } 46 render.NoContent(w, r) 47 } 48 49 func healthCheckProvider(w http.ResponseWriter, r *http.Request) { 50 provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider) 51 provider.HealthCheck() 52 render.NoContent(w, r) 53 } 54 55 func parseProviderName(next http.Handler) http.Handler { 56 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 57 name := getEscapeParam(r, "name") 58 ctx := context.WithValue(r.Context(), CtxKeyProviderName, name) 59 next.ServeHTTP(w, r.WithContext(ctx)) 60 }) 61 } 62 63 func findProviderByName(next http.Handler) http.Handler { 64 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 65 name := r.Context().Value(CtxKeyProviderName).(string) 66 providers := tunnel.Providers() 67 provider, exist := providers[name] 68 if !exist { 69 render.Status(r, http.StatusNotFound) 70 render.JSON(w, r, ErrNotFound) 71 return 72 } 73 74 ctx := context.WithValue(r.Context(), CtxKeyProvider, provider) 75 next.ServeHTTP(w, r.WithContext(ctx)) 76 }) 77 }