refactor(api): consolidate health check endpoints to /health
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 1m44s
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 1m44s
Removes the redundant `/healthz` and `/api/v1/health` endpoints, leaving `/health` as the sole health check endpoint. - Update router to return 404 Not Found for the removed endpoints - Update admin log filtering to only ignore `/health` - Remove health URL from API documentation data - Update tests to verify `/health` returns 200 and others return 404 - Update README documentation to reflect the change
This commit is contained in:
@@ -108,8 +108,7 @@ The compose example also works with Podman compatible compose tools. Its data vo
|
|||||||
`./data:/data:Z` for SELinux relabeling, and the container overrides runtime paths to use
|
`./data:/data:Z` for SELinux relabeling, and the container overrides runtime paths to use
|
||||||
`/data`, `/app/static`, and `/app/templates`.
|
`/data`, `/app/static`, and `/app/templates`.
|
||||||
|
|
||||||
The image exposes `/health`, `/healthz`, and `/api/v1/health`. Docker and compose healthchecks
|
The image exposes the health endpoint: `/health`. Docker and compose healthchecks use it.
|
||||||
use `/health`.
|
|
||||||
|
|
||||||
## Reverse Proxy Security
|
## Reverse Proxy Security
|
||||||
|
|
||||||
|
|||||||
@@ -1770,7 +1770,7 @@ func isHealthCheckLogEntry(raw map[string]any) bool {
|
|||||||
if idx := strings.IndexByte(path, '?'); idx >= 0 {
|
if idx := strings.IndexByte(path, '?'); idx >= 0 {
|
||||||
path = path[:idx]
|
path = path[:idx]
|
||||||
}
|
}
|
||||||
return path == "/health" || path == "/healthz" || path == "/api/v1/health"
|
return path == "/health"
|
||||||
}
|
}
|
||||||
|
|
||||||
func logEntryFromMap(raw map[string]any) adminLogEntry {
|
func logEntryFromMap(raw map[string]any) adminLogEntry {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
type apiDocsData struct {
|
type apiDocsData struct {
|
||||||
BaseURL string
|
BaseURL string
|
||||||
UploadURL string
|
UploadURL string
|
||||||
HealthURL string
|
|
||||||
RequestSchemaURL string
|
RequestSchemaURL string
|
||||||
ResponseSchemaURL string
|
ResponseSchemaURL string
|
||||||
ShareXExamplePath string
|
ShareXExamplePath string
|
||||||
@@ -39,7 +38,6 @@ func (a *App) APIDocs(w http.ResponseWriter, r *http.Request) {
|
|||||||
Data: apiDocsData{
|
Data: apiDocsData{
|
||||||
BaseURL: a.cfg.BaseURL,
|
BaseURL: a.cfg.BaseURL,
|
||||||
UploadURL: a.cfg.BaseURL + "/api/v1/upload",
|
UploadURL: a.cfg.BaseURL + "/api/v1/upload",
|
||||||
HealthURL: a.cfg.BaseURL + "/api/v1/health",
|
|
||||||
RequestSchemaURL: a.cfg.BaseURL + "/api/v1/schemas/upload-request.json",
|
RequestSchemaURL: a.cfg.BaseURL + "/api/v1/schemas/upload-request.json",
|
||||||
ResponseSchemaURL: a.cfg.BaseURL + "/api/v1/schemas/upload-response.json",
|
ResponseSchemaURL: a.cfg.BaseURL + "/api/v1/schemas/upload-response.json",
|
||||||
ShareXExamplePath: "examples/sharex/warpbox-anonymous.sxcu",
|
ShareXExamplePath: "examples/sharex/warpbox-anonymous.sxcu",
|
||||||
|
|||||||
@@ -129,8 +129,8 @@ func (a *App) RegisterRoutes(mux *http.ServeMux) {
|
|||||||
mux.HandleFunc("GET /d/{boxID}/thumb/{fileID}", a.Thumbnail)
|
mux.HandleFunc("GET /d/{boxID}/thumb/{fileID}", a.Thumbnail)
|
||||||
mux.HandleFunc("GET /d/{boxID}/og-image.jpg", a.BoxOGImage)
|
mux.HandleFunc("GET /d/{boxID}/og-image.jpg", a.BoxOGImage)
|
||||||
mux.HandleFunc("GET /health", a.Health)
|
mux.HandleFunc("GET /health", a.Health)
|
||||||
mux.HandleFunc("GET /healthz", a.Health)
|
mux.HandleFunc("GET /healthz", notFound)
|
||||||
mux.HandleFunc("GET /api/v1/health", a.Health)
|
mux.HandleFunc("GET /api/v1/health", notFound)
|
||||||
mux.HandleFunc("GET /api/v1/sharex/warpbox-anonymous.sxcu", a.ShareXAnonymousConfig)
|
mux.HandleFunc("GET /api/v1/sharex/warpbox-anonymous.sxcu", a.ShareXAnonymousConfig)
|
||||||
mux.HandleFunc("GET /api/v1/schemas/upload-request.json", a.UploadRequestSchema)
|
mux.HandleFunc("GET /api/v1/schemas/upload-request.json", a.UploadRequestSchema)
|
||||||
mux.HandleFunc("GET /api/v1/schemas/upload-response.json", a.UploadResponseSchema)
|
mux.HandleFunc("GET /api/v1/schemas/upload-response.json", a.UploadResponseSchema)
|
||||||
@@ -138,3 +138,7 @@ func (a *App) RegisterRoutes(mux *http.ServeMux) {
|
|||||||
mux.HandleFunc("GET /emoji/{pack}/{file}", a.EmojiAsset)
|
mux.HandleFunc("GET /emoji/{pack}/{file}", a.EmojiAsset)
|
||||||
mux.Handle("GET /static/", a.Static())
|
mux.Handle("GET /static/", a.Static())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func notFound(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ type healthResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) Health(w http.ResponseWriter, r *http.Request) {
|
func (a *App) Health(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path != "/health" {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
helpers.WriteJSON(w, http.StatusOK, healthResponse{
|
helpers.WriteJSON(w, http.StatusOK, healthResponse{
|
||||||
Status: "ok",
|
Status: "ok",
|
||||||
Time: time.Now().UTC().Format(time.RFC3339),
|
Time: time.Now().UTC().Format(time.RFC3339),
|
||||||
|
|||||||
@@ -13,16 +13,20 @@ func TestHealthRoutes(t *testing.T) {
|
|||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
app.RegisterRoutes(mux)
|
app.RegisterRoutes(mux)
|
||||||
|
|
||||||
for _, path := range []string{"/health", "/healthz", "/api/v1/health"} {
|
request := httptest.NewRequest(http.MethodGet, "/health", nil)
|
||||||
t.Run(path, func(t *testing.T) {
|
response := httptest.NewRecorder()
|
||||||
request := httptest.NewRequest(http.MethodGet, path, nil)
|
|
||||||
response := httptest.NewRecorder()
|
|
||||||
|
|
||||||
mux.ServeHTTP(response, request)
|
mux.ServeHTTP(response, request)
|
||||||
|
|
||||||
if response.Code != http.StatusOK {
|
if response.Code != http.StatusOK {
|
||||||
t.Fatalf("status = %d, body = %s", response.Code, response.Body.String())
|
t.Fatalf("status = %d, body = %s", response.Code, response.Body.String())
|
||||||
}
|
}
|
||||||
})
|
for _, path := range []string{"/healthz", "/api/v1/health"} {
|
||||||
|
request := httptest.NewRequest(http.MethodGet, path, nil)
|
||||||
|
response := httptest.NewRecorder()
|
||||||
|
mux.ServeHTTP(response, request)
|
||||||
|
if response.Code != http.StatusNotFound {
|
||||||
|
t.Fatalf("%s status = %d, want 404", path, response.Code)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ func (s *BanService) MaliciousPattern(path string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func shouldSkipMaliciousPath(path string) bool {
|
func shouldSkipMaliciousPath(path string) bool {
|
||||||
return path == "/health" || path == "/healthz" || path == "/api/v1/health" || strings.HasPrefix(path, "/static/")
|
return path == "/health" || strings.HasPrefix(path, "/static/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BanService) RecordAbuse(ip, kind, detail string, threshold int, now time.Time) (AbuseResult, error) {
|
func (s *BanService) RecordAbuse(ip, kind, detail string, threshold int, now time.Time) (AbuseResult, error) {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<h2>Endpoints</h2>
|
<h2>Endpoints</h2>
|
||||||
<dl class="endpoint-list">
|
<dl class="endpoint-list">
|
||||||
<div><dt>Upload</dt><dd><code>POST /api/v1/upload</code></dd></div>
|
<div><dt>Upload</dt><dd><code>POST /api/v1/upload</code></dd></div>
|
||||||
<div><dt>Health</dt><dd><code>GET /api/v1/health</code></dd></div>
|
<div><dt>Health</dt><dd><code>GET /health</code></dd></div>
|
||||||
<div><dt>Request schema</dt><dd><a href="/api/v1/schemas/upload-request.json"><code>/api/v1/schemas/upload-request.json</code></a></dd></div>
|
<div><dt>Request schema</dt><dd><a href="/api/v1/schemas/upload-request.json"><code>/api/v1/schemas/upload-request.json</code></a></dd></div>
|
||||||
<div><dt>Response schema</dt><dd><a href="/api/v1/schemas/upload-response.json"><code>/api/v1/schemas/upload-response.json</code></a></dd></div>
|
<div><dt>Response schema</dt><dd><a href="/api/v1/schemas/upload-response.json"><code>/api/v1/schemas/upload-response.json</code></a></dd></div>
|
||||||
</dl>
|
</dl>
|
||||||
|
|||||||
Reference in New Issue
Block a user