Skip to content

Commit 6cbae6d

Browse files
committed
wfe: Add health endpoint
Fixes #8476
1 parent 18685ee commit 6cbae6d

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

test/integration/wfe_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
66
"io"
77
"net/http"
88
"testing"
9+
"time"
910

11+
"github.com/letsencrypt/boulder/core"
1012
"github.com/letsencrypt/boulder/test"
1113
)
1214

@@ -50,3 +52,22 @@ func TestWFEHTTPMetrics(t *testing.T) {
5052
test.AssertContains(t, string(body), `response_time_count{code="200",endpoint="/directory",method="GET"}`)
5153
resp.Body.Close()
5254
}
55+
56+
// TestWFEHealth checks to make sure that the /health endpoint returns 200 OK,
57+
// retrying in case overrides take a moment to load.
58+
func TestWFEHealth(t *testing.T) {
59+
retries := 0
60+
var status int
61+
for retries < 5 {
62+
time.Sleep(core.RetryBackoff(retries, time.Millisecond*2, time.Millisecond*50, 2))
63+
resp, err := http.Get("http://boulder.service.consul:4001/health")
64+
test.AssertNotError(t, err, "GET boulder-wfe2 health")
65+
status = resp.StatusCode
66+
resp.Body.Close()
67+
if status == http.StatusOK {
68+
break
69+
}
70+
retries++
71+
}
72+
test.AssertEquals(t, status, http.StatusOK)
73+
}

wfe2/wfe.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const (
7171
getCertPath = "/get/cert/"
7272
getCertInfoPath = "/get/certinfo/"
7373
buildIDPath = "/build"
74+
healthPath = "/health"
7475
)
7576

7677
const (
@@ -425,6 +426,7 @@ func (wfe *WebFrontEndImpl) Handler(stats prometheus.Registerer, oTelHTTPOptions
425426
wfe.HandleFunc(m, getCertPath, wfe.Certificate, "GET")
426427
wfe.HandleFunc(m, getCertInfoPath, wfe.CertificateInfo, "GET")
427428
wfe.HandleFunc(m, buildIDPath, wfe.BuildID, "GET")
429+
wfe.HandleFunc(m, healthPath, wfe.HttpHealth, "GET")
428430

429431
// Endpoint for draft-ietf-acme-ari
430432
if features.Get().ServeRenewalInfo {
@@ -1801,6 +1803,23 @@ func (wfe *WebFrontEndImpl) BuildID(ctx context.Context, logEvent *web.RequestEv
18011803
}
18021804
}
18031805

1806+
// HttpHealth tells the requester whether we're ready to serve requests.
1807+
func (wfe *WebFrontEndImpl) HttpHealth(ctx context.Context, _ *web.RequestEvent, response http.ResponseWriter, _ *http.Request) {
1808+
status := http.StatusOK
1809+
details := "OK"
1810+
1811+
if !wfe.txnBuilder.Ready() {
1812+
status = http.StatusServiceUnavailable
1813+
details = "waiting for overrides"
1814+
}
1815+
1816+
response.Header().Set("Content-Type", "text/plain")
1817+
response.WriteHeader(status)
1818+
if _, err := fmt.Println(response, details); err != nil {
1819+
wfe.log.Warningf("Could not write response: %s", err)
1820+
}
1821+
}
1822+
18041823
// Options responds to an HTTP OPTIONS request.
18051824
func (wfe *WebFrontEndImpl) Options(response http.ResponseWriter, request *http.Request, methodsStr string, methodsMap map[string]bool) {
18061825
// Every OPTIONS request gets an Allow header with a list of supported methods.

wfe2/wfe_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,11 @@ func TestHTTPMethods(t *testing.T) {
10951095
Path: buildIDPath,
10961096
Allowed: getOnly,
10971097
},
1098+
{
1099+
Name: "Health path should be GET only",
1100+
Path: healthPath,
1101+
Allowed: getOnly,
1102+
},
10981103
{
10991104
Name: "Rollover path should be POST only",
11001105
Path: rolloverPath,

0 commit comments

Comments
 (0)