api_meta.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package clashapi
  2. import (
  3. "bytes"
  4. "net"
  5. "net/http"
  6. "runtime/debug"
  7. "time"
  8. "github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
  9. "github.com/sagernet/sing/common/json"
  10. "github.com/sagernet/ws"
  11. "github.com/sagernet/ws/wsutil"
  12. "github.com/go-chi/chi/v5"
  13. "github.com/go-chi/chi/v5/middleware"
  14. "github.com/go-chi/render"
  15. )
  16. // API created by Clash.Meta
  17. func (s *Server) setupMetaAPI(r chi.Router) {
  18. if s.logDebug {
  19. r := chi.NewRouter()
  20. r.Put("/gc", func(w http.ResponseWriter, r *http.Request) {
  21. debug.FreeOSMemory()
  22. })
  23. r.Mount("/", middleware.Profiler())
  24. }
  25. r.Get("/memory", memory(s.trafficManager))
  26. r.Mount("/group", groupRouter(s))
  27. r.Mount("/upgrade", upgradeRouter(s))
  28. }
  29. type Memory struct {
  30. Inuse uint64 `json:"inuse"`
  31. OSLimit uint64 `json:"oslimit"` // maybe we need it in the future
  32. }
  33. func memory(trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
  34. return func(w http.ResponseWriter, r *http.Request) {
  35. var conn net.Conn
  36. if r.Header.Get("Upgrade") == "websocket" {
  37. var err error
  38. conn, _, _, err = ws.UpgradeHTTP(r, w)
  39. if err != nil {
  40. return
  41. }
  42. }
  43. if conn == nil {
  44. w.Header().Set("Content-Type", "application/json")
  45. render.Status(r, http.StatusOK)
  46. }
  47. tick := time.NewTicker(time.Second)
  48. defer tick.Stop()
  49. buf := &bytes.Buffer{}
  50. var err error
  51. first := true
  52. for range tick.C {
  53. buf.Reset()
  54. inuse := trafficManager.Snapshot().Memory
  55. // make chat.js begin with zero
  56. // this is shit var,but we need output 0 for first time
  57. if first {
  58. first = false
  59. inuse = 0
  60. }
  61. if err := json.NewEncoder(buf).Encode(Memory{
  62. Inuse: inuse,
  63. OSLimit: 0,
  64. }); err != nil {
  65. break
  66. }
  67. if conn == nil {
  68. _, err = w.Write(buf.Bytes())
  69. w.(http.Flusher).Flush()
  70. } else {
  71. err = wsutil.WriteServerText(conn, buf.Bytes())
  72. }
  73. if err != nil {
  74. break
  75. }
  76. }
  77. }
  78. }