@@ -71,6 +71,7 @@ const (
7171 getCertPath = "/get/cert/"
7272 getCertInfoPath = "/get/certinfo/"
7373 buildIDPath = "/build"
74+ healthzPath = "/healthz"
7475)
7576
7677const (
@@ -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 , healthzPath , wfe .Healthz , "GET" )
428430
429431 // Endpoint for draft-ietf-acme-ari
430432 if features .Get ().ServeRenewalInfo {
@@ -1801,6 +1803,31 @@ func (wfe *WebFrontEndImpl) BuildID(ctx context.Context, logEvent *web.RequestEv
18011803 }
18021804}
18031805
1806+ type WfeHealthzResponse struct {
1807+ Details string
1808+ }
1809+
1810+ // Healthz tells the requester whether we're ready to serve requests.
1811+ func (wfe * WebFrontEndImpl ) Healthz (ctx context.Context , logEvent * web.RequestEvent , response http.ResponseWriter , request * http.Request ) {
1812+ status := http .StatusOK
1813+ details := "OK"
1814+
1815+ if ! wfe .txnBuilder .Ready () {
1816+ status = http .StatusServiceUnavailable
1817+ details = "waiting for overrides"
1818+ }
1819+
1820+ jsonResponse , err := json .Marshal (WfeHealthzResponse {Details : details })
1821+ if err != nil {
1822+ wfe .log .Warningf ("Could not marshal healthz response: %s" , err )
1823+ }
1824+
1825+ err = wfe .writeJsonResponse (response , logEvent , status , jsonResponse )
1826+ if err != nil {
1827+ wfe .log .Warningf ("Could not write response: %s" , err )
1828+ }
1829+ }
1830+
18041831// Options responds to an HTTP OPTIONS request.
18051832func (wfe * WebFrontEndImpl ) Options (response http.ResponseWriter , request * http.Request , methodsStr string , methodsMap map [string ]bool ) {
18061833 // Every OPTIONS request gets an Allow header with a list of supported methods.
0 commit comments