summaryrefslogtreecommitdiffhomepage
path: root/ipn/localapi/localapi.go
diff options
context:
space:
mode:
Diffstat (limited to 'ipn/localapi/localapi.go')
-rw-r--r--ipn/localapi/localapi.go32
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
+}