fix: return 200 for HEAD / so uptime monitors don't fail (#773)

This commit is contained in:
Alexander Fortin
2026-07-27 04:32:35 +03:00
committed by GitHub
parent c7fe438feb
commit ec429f51c6
4 changed files with 42 additions and 1 deletions
+10
View File
@@ -11,3 +11,13 @@ curl http://localhost:6157/healthcheck
```json
{"database":"ok","opengist":"ok","time":"2024-01-04T05:18:33+01:00"}
```
## `HEAD /healthcheck`
A `HEAD` request to `/healthcheck` returns the same status code as the `GET`
request above, but without a body. This is handy for uptime monitors and load
balancers that probe the endpoint with `curl -I`:
```shell
curl -I http://localhost:6157/healthcheck
```
+12 -1
View File
@@ -1,11 +1,16 @@
package health
import (
"net/http"
"time"
"github.com/thomiceli/opengist/internal/db"
"github.com/thomiceli/opengist/internal/web/context"
"time"
)
// Healthcheck reports service health. A GET request returns the status as JSON;
// a HEAD request returns only the status code (no body), which is convenient
// for uptime monitors and load balancers probing the endpoint with `curl -I`.
func Healthcheck(ctx *context.Context) error {
// Check database connection
dbOk := "ok"
@@ -17,6 +22,12 @@ func Healthcheck(ctx *context.Context) error {
httpStatus = 503
}
// A HEAD request returns only the status code (no body), so uptime
// monitors and load balancers can probe the endpoint with `curl -I`.
if ctx.Request().Method == http.MethodHead {
return ctx.NoContent(httpStatus)
}
return ctx.JSON(httpStatus, map[string]interface{}{
"opengist": "ok",
"database": dbOk,
@@ -28,3 +28,20 @@ func TestHealthcheck(t *testing.T) {
require.NotEmpty(t, result["time"])
})
}
func TestHealthcheckHead(t *testing.T) {
s := webtest.Setup(t)
defer webtest.Teardown(t)
t.Run("Returns 200 without authentication", func(t *testing.T) {
// A HEAD request to "/healthcheck" should return 200 (with no body) so
// that uptime monitors and load balancers using `curl -I` do not see a
// 404.
resp := s.Request(t, "HEAD", "/healthcheck", nil, 200)
// A HEAD response must not carry a body.
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Empty(t, body)
})
}
+3
View File
@@ -35,6 +35,9 @@ func (s *Server) registerRoutes() {
r.POST("/upload", gist.Upload, logged, checkFileUploadEnabled)
r.DELETE("/upload/:uuid", gist.DeleteUpload, logged, checkFileUploadEnabled)
// HEAD "/healthcheck" returns the health status code without a body, for
// uptime monitors and load balancers probing the endpoint (e.g. `curl -I`).
r.HEAD("/healthcheck", health.Healthcheck)
r.GET("/healthcheck", health.Healthcheck)
r.Static("/avatar", settings.AvatarsDir())