diff --git a/adapters/outbound/base.go b/adapters/outbound/base.go index 0b9c90df..3dc97825 100644 --- a/adapters/outbound/base.go +++ b/adapters/outbound/base.go @@ -142,6 +142,7 @@ func (p *Proxy) MarshalJSON() ([]byte, error) { mapping := map[string]interface{}{} json.Unmarshal(inner, &mapping) mapping["history"] = p.DelayHistory() + mapping["name"] = p.Name() return json.Marshal(mapping) } diff --git a/adapters/provider/provider.go b/adapters/provider/provider.go index 3d718cb6..ddecbbf5 100644 --- a/adapters/provider/provider.go +++ b/adapters/provider/provider.go @@ -60,6 +60,7 @@ type ProxyProvider interface { Provider Proxies() []C.Proxy HealthCheck() + Update() error } type ProxySchema struct { @@ -106,6 +107,10 @@ func (pp *ProxySetProvider) HealthCheck() { } } +func (pp *ProxySetProvider) Update() error { + return pp.pull() +} + func (pp *ProxySetProvider) Destroy() error { pp.mux.Lock() defer pp.mux.Unlock() @@ -124,8 +129,10 @@ func (pp *ProxySetProvider) Destroy() error { func (pp *ProxySetProvider) Initial() error { var buf []byte var err error - if _, err := os.Stat(pp.vehicle.Path()); err == nil { + if stat, err := os.Stat(pp.vehicle.Path()); err == nil { buf, err = ioutil.ReadFile(pp.vehicle.Path()) + modTime := stat.ModTime() + pp.updatedAt = &modTime } else { buf, err = pp.vehicle.Read() } @@ -180,9 +187,11 @@ func (pp *ProxySetProvider) pull() error { return err } + now := time.Now() hash := md5.Sum(buf) if bytes.Equal(pp.hash[:], hash[:]) { log.Debugln("[Provider] %s's proxies doesn't change", pp.Name()) + pp.updatedAt = &now return nil } @@ -196,7 +205,6 @@ func (pp *ProxySetProvider) pull() error { return err } - now := time.Now() pp.updatedAt = &now pp.hash = hash pp.setProxies(proxies) @@ -224,6 +232,10 @@ func (pp *ProxySetProvider) parse(buf []byte) ([]C.Proxy, error) { proxies = append(proxies, proxy) } + if len(proxies) == 0 { + return nil, errors.New("File doesn't have any valid proxy") + } + return proxies, nil } @@ -291,6 +303,10 @@ func (cp *CompatibleProvier) HealthCheck() { } } +func (cp *CompatibleProvier) Update() error { + return nil +} + func (cp *CompatibleProvier) Initial() error { if cp.healthCheck != nil { go cp.healthCheck.process() diff --git a/hub/route/provider.go b/hub/route/provider.go index ddc2426c..f69bec46 100644 --- a/hub/route/provider.go +++ b/hub/route/provider.go @@ -18,7 +18,8 @@ func proxyProviderRouter() http.Handler { r.Route("/{name}", func(r chi.Router) { r.Use(parseProviderName, findProviderByName) r.Get("/", getProvider) - r.Get("/healthcheck", doProviderHealthCheck) + r.Put("/", updateProvider) + r.Get("/healthcheck", healthCheckProvider) }) return r } @@ -35,7 +36,17 @@ func getProvider(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, provider) } -func doProviderHealthCheck(w http.ResponseWriter, r *http.Request) { +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)