diff --git a/docs/releases.md b/docs/releases.md index 5d69ffd8..6e8cfba0 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -4,6 +4,10 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release ## ntfy server v1.31.0 (UNRELEASED) +**Features:** + +* Preliminary `/v1/health` API endpoint for service monitoring (no ticket) + **Documentation:** * Add HTTP/2 and TLSv1.3 support to nginx docs ([#553](https://github.com/binwiederhier/ntfy/issues/553), thanks to [bt90](https://github.com/bt90)) diff --git a/server/server.go b/server/server.go index a797f023..1bbc8b8f 100644 --- a/server/server.go +++ b/server/server.go @@ -95,6 +95,7 @@ var ( publishPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/(publish|send|trigger)$`) webConfigPath = "/config.js" + healthPath = "/v1/health" accountPath = "/v1/account" accountTokenPath = "/v1/account/token" accountPasswordPath = "/v1/account/password" @@ -330,6 +331,8 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit return s.ensureWebEnabled(s.handleHome)(w, r, v) } else if r.Method == http.MethodHead && r.URL.Path == "/" { return s.ensureWebEnabled(s.handleEmpty)(w, r, v) + } else if r.Method == http.MethodGet && r.URL.Path == healthPath { + return s.handleHealth(w, r, v) } else if r.Method == http.MethodGet && r.URL.Path == webConfigPath { return s.ensureWebEnabled(s.handleWebConfig)(w, r, v) } else if r.Method == http.MethodPost && r.URL.Path == accountPath { @@ -416,6 +419,18 @@ func (s *Server) handleTopicAuth(w http.ResponseWriter, _ *http.Request, _ *visi return err } +func (s *Server) handleHealth(w http.ResponseWriter, _ *http.Request, _ *visitor) error { + response := &apiHealthResponse{ + Healthy: true, + } + w.Header().Set("Content-Type", "text/json") + w.Header().Set("Access-Control-Allow-Origin", "*") // CORS, allow cross-origin requests + if err := json.NewEncoder(w).Encode(response); err != nil { + return err + } + return nil +} + func (s *Server) handleWebConfig(w http.ResponseWriter, _ *http.Request, _ *visitor) error { appRoot := "/" if !s.config.WebRootIsApp { diff --git a/server/types.go b/server/types.go index bc66d555..2f144853 100644 --- a/server/types.go +++ b/server/types.go @@ -216,6 +216,10 @@ func (q *queryFilter) Pass(msg *message) bool { return true } +type apiHealthResponse struct { + Healthy bool `json:"healthy"` +} + type apiAccountCreateRequest struct { Username string `json:"username"` Password string `json:"password"`