github.com/yaling888/clash@v1.53.0/hub/route/connections.go (about) 1 package route 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "strconv" 7 "time" 8 9 "github.com/go-chi/chi/v5" 10 "github.com/go-chi/render" 11 "github.com/gorilla/websocket" 12 13 "github.com/yaling888/clash/common/pool" 14 "github.com/yaling888/clash/tunnel/statistic" 15 ) 16 17 func connectionRouter() http.Handler { 18 r := chi.NewRouter() 19 r.Get("/", getConnections) 20 r.Delete("/", closeAllConnections) 21 r.Delete("/{id}", closeConnection) 22 return r 23 } 24 25 func getConnections(w http.ResponseWriter, r *http.Request) { 26 if !websocket.IsWebSocketUpgrade(r) { 27 snapshot := statistic.DefaultManager.Snapshot() 28 render.JSON(w, r, snapshot) 29 return 30 } 31 32 conn, err := upgrader.Upgrade(w, r, nil) 33 if err != nil { 34 return 35 } 36 37 intervalStr := r.URL.Query().Get("interval") 38 interval := 1000 * time.Millisecond 39 if intervalStr != "" { 40 t, err := strconv.ParseInt(intervalStr, 10, 64) 41 if err != nil { 42 d, err := time.ParseDuration(intervalStr) 43 if err != nil { 44 render.Status(r, http.StatusBadRequest) 45 render.JSON(w, r, ErrBadRequest) 46 return 47 } 48 interval = d 49 } else { 50 interval = time.Duration(t) * time.Millisecond 51 } 52 } 53 54 buf := pool.BufferWriter{} 55 encoder := json.NewEncoder(&buf) 56 sendSnapshot := func() error { 57 buf.Reset() 58 snapshot := statistic.DefaultManager.Snapshot() 59 if err := encoder.Encode(snapshot); err != nil { 60 return err 61 } 62 63 return conn.WriteMessage(websocket.TextMessage, buf.Bytes()) 64 } 65 66 if err := sendSnapshot(); err != nil { 67 return 68 } 69 70 tick := time.NewTicker(interval) 71 defer tick.Stop() 72 for range tick.C { 73 if err := sendSnapshot(); err != nil { 74 break 75 } 76 } 77 } 78 79 func closeConnection(w http.ResponseWriter, r *http.Request) { 80 id := chi.URLParam(r, "id") 81 snapshot := statistic.DefaultManager.Snapshot() 82 for _, c := range snapshot.Connections { 83 if id == c.ID() { 84 _ = c.Close() 85 break 86 } 87 } 88 render.NoContent(w, r) 89 } 90 91 func closeAllConnections(w http.ResponseWriter, r *http.Request) { 92 snapshot := statistic.DefaultManager.Snapshot() 93 for _, c := range snapshot.Connections { 94 _ = c.Close() 95 } 96 render.NoContent(w, r) 97 }