ipn/localapi,client/local: honour Retry-After on cert rate-limit (#20315)
* ipn/localapi,ipnlocal,feature/acme,client/local: honour Retry-After on cert rate-limit serveCert now responds with 429 + Retry-After when the underlying ACME error is a rate limit, instead of a generic 500. client/local surfaces this as a typed RateLimitedError with the parsed hint so callers can back off intelligently. Updates tailscale/corp#42164 Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk> * tsweb,feature/acme,ipn/localapi,ipnlocal: generalise cert error → HTTP mapping via tsweb.HTTPStatuser Introduces a tsweb.HTTPStatuser interface, any error can implement to describe its intended HTTP response (code, message, headers). Moves CertRateLimitedError from ipnlocal to feature/acme where it's constructed, and it now uses HTTPStatuser to return 429 + Retry-After. serveCert now checks for tsweb.HTTPStatuser rather than the specific error type, so it no longer needs to know about the ACME rate-limit type. Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk> --------- Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
This commit is contained in:
@@ -784,6 +784,12 @@ func (h errorHandler) handleError(w http.ResponseWriter, r *http.Request, lw *lo
|
||||
// Extract a presentable, loggable error.
|
||||
var hOK bool
|
||||
hErr, hAsOK := errors.AsType[HTTPError](err)
|
||||
if !hAsOK {
|
||||
if hs, ok := errors.AsType[HTTPStatuser](err); ok {
|
||||
hErr = hs.HTTPStatus()
|
||||
hAsOK = true
|
||||
}
|
||||
}
|
||||
if hAsOK {
|
||||
hOK = true
|
||||
if hErr.Code == 0 {
|
||||
@@ -919,6 +925,15 @@ func WriteHTTPError(w http.ResponseWriter, r *http.Request, e HTTPError) {
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPStatuser is an optional interface implemented by errors that
|
||||
// carry an intended HTTP response. Handlers translating errors to
|
||||
// HTTP should honour the returned HTTPError rather than defaulting to
|
||||
// 500.
|
||||
type HTTPStatuser interface {
|
||||
error
|
||||
HTTPStatus() HTTPError
|
||||
}
|
||||
|
||||
// HTTPError is an error with embedded HTTP response information.
|
||||
//
|
||||
// It is the error type to be (optionally) used by Handler.ServeHTTPReturn.
|
||||
|
||||
Reference in New Issue
Block a user