diff options
Diffstat (limited to 'ipn/localapi/localapi.go')
| -rw-r--r-- | ipn/localapi/localapi.go | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index 4e0dba3da..169f18ba4 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -10,9 +10,11 @@ import ( "io" "net/http" "runtime" + "strconv" "inet.af/netaddr" "tailscale.com/ipn/ipnlocal" + "tailscale.com/ipn/ipnstate" "tailscale.com/tailcfg" ) @@ -56,6 +58,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.serveWhoIs(w, r) case "/localapi/v0/goroutines": h.serveGoroutines(w, r) + case "/localapi/v0/status": + h.serveStatus(w, r) default: io.WriteString(w, "tailscaled\n") } @@ -109,3 +113,31 @@ func (h *Handler) serveGoroutines(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") w.Write(buf) } + +func (h *Handler) serveStatus(w http.ResponseWriter, r *http.Request) { + if !h.PermitRead { + http.Error(w, "status access denied", http.StatusForbidden) + return + } + w.Header().Set("Content-Type", "application/json") + var st *ipnstate.Status + if defBool(r.FormValue("peers"), true) { + st = h.b.Status() + } else { + st = h.b.StatusWithoutPeers() + } + e := json.NewEncoder(w) + e.SetIndent("", "\t") + e.Encode(st) +} + +func defBool(a string, def bool) bool { + if a == "" { + return def + } + v, err := strconv.ParseBool(a) + if err != nil { + return def + } + return v +} |
