github.com/chwjbn/xclash@v0.2.0/hub/route/connections.go (about)

     1  package route
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"net/http"
     7  	"strconv"
     8  	"time"
     9  
    10  	"github.com/chwjbn/xclash/tunnel/statistic"
    11  
    12  	"github.com/go-chi/chi/v5"
    13  	"github.com/go-chi/render"
    14  	"github.com/gorilla/websocket"
    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
    39  	if intervalStr != "" {
    40  		t, err := strconv.Atoi(intervalStr)
    41  		if err != nil {
    42  			render.Status(r, http.StatusBadRequest)
    43  			render.JSON(w, r, ErrBadRequest)
    44  			return
    45  		}
    46  
    47  		interval = t
    48  	}
    49  
    50  	buf := &bytes.Buffer{}
    51  	sendSnapshot := func() error {
    52  		buf.Reset()
    53  		snapshot := statistic.DefaultManager.Snapshot()
    54  		if err := json.NewEncoder(buf).Encode(snapshot); err != nil {
    55  			return err
    56  		}
    57  
    58  		return conn.WriteMessage(websocket.TextMessage, buf.Bytes())
    59  	}
    60  
    61  	if err := sendSnapshot(); err != nil {
    62  		return
    63  	}
    64  
    65  	tick := time.NewTicker(time.Millisecond * time.Duration(interval))
    66  	defer tick.Stop()
    67  	for range tick.C {
    68  		if err := sendSnapshot(); err != nil {
    69  			break
    70  		}
    71  	}
    72  }
    73  
    74  func closeConnection(w http.ResponseWriter, r *http.Request) {
    75  	id := chi.URLParam(r, "id")
    76  	snapshot := statistic.DefaultManager.Snapshot()
    77  	for _, c := range snapshot.Connections {
    78  		if id == c.ID() {
    79  			c.Close()
    80  			break
    81  		}
    82  	}
    83  	render.NoContent(w, r)
    84  }
    85  
    86  func closeAllConnections(w http.ResponseWriter, r *http.Request) {
    87  	snapshot := statistic.DefaultManager.Snapshot()
    88  	for _, c := range snapshot.Connections {
    89  		c.Close()
    90  	}
    91  	render.NoContent(w, r)
    92  }