@@ -382,14 +382,14 @@ func (h *Handler) Provision(ctx caddy.Context) error {
382382 // defaulting to a sane wait period between attempts
383383 h .LoadBalancing .TryInterval = caddy .Duration (250 * time .Millisecond )
384384 }
385- lbMatcherSets , err := ctx .LoadModule (h .LoadBalancing , "RetryMatchRaw" )
386- if err != nil {
387- return err
388- }
389- err = h .LoadBalancing .RetryMatch .FromInterface (lbMatcherSets )
390- if err != nil {
391- return err
385+ // convert legacy retry_match entries into retry_conditions for
386+ // backward compatibility with the JSON API
387+ for _ , matcherSetRaw := range h .LoadBalancing .RetryMatchRaw {
388+ h .LoadBalancing .RetryConditionsRaw = append (h .LoadBalancing .RetryConditionsRaw , & RetryConditionSet {
389+ MatchRaw : matcherSetRaw ,
390+ })
392391 }
392+ h .LoadBalancing .RetryMatchRaw = nil
393393
394394 // provision retry conditions
395395 for i , rc := range h .LoadBalancing .RetryConditionsRaw {
@@ -1325,16 +1325,10 @@ func (lb LoadBalancing) tryAgain(ctx caddy.Context, start time.Time, retries int
13251325 if ! isDialError && (! isHandlerError || ! errors .Is (herr , errNoUpstream )) {
13261326 // retryableStatusError is always safe to retry (we control when it's generated)
13271327 if _ , ok := proxyErr .(retryableStatusError ); ! ok {
1328- // default behavior: retry GET or RetryMatch
1329- if lb .RetryMatch == nil && req .Method != "GET" {
1328+ if len (lb .retryConditions ) == 0 && req .Method != "GET" {
13301329 return false
13311330 }
1332- match , err := lb .RetryMatch .AnyMatchWithError (req )
1333- if err != nil {
1334- logger .Error ("error matching request for retry" , zap .Error (err ))
1335- return false
1336- }
1337- if ! match {
1331+ if len (lb .retryConditions ) > 0 && ! lb .matchesRetryCondition (req , logger ) {
13381332 return false
13391333 }
13401334 }
@@ -1360,6 +1354,26 @@ func (lb LoadBalancing) tryAgain(ctx caddy.Context, start time.Time, retries int
13601354 }
13611355}
13621356
1357+ // matchesRetryCondition checks whether any configured retry condition's
1358+ // request matchers match the given request. If a condition has no matchers,
1359+ // any request matches it.
1360+ func (lb LoadBalancing ) matchesRetryCondition (req * http.Request , logger * zap.Logger ) bool {
1361+ for _ , rc := range lb .retryConditions {
1362+ if len (rc .matchers ) == 0 {
1363+ return true
1364+ }
1365+ match , err := rc .matchers .MatchWithError (req )
1366+ if err != nil {
1367+ logger .Error ("error matching request for retry condition" , zap .Error (err ))
1368+ continue
1369+ }
1370+ if match {
1371+ return true
1372+ }
1373+ }
1374+ return false
1375+ }
1376+
13631377// directRequest modifies only req.URL so that it points to the upstream
13641378// in the given DialInfo. It must modify ONLY the request URL.
13651379func (h * Handler ) directRequest (req * http.Request , di DialInfo ) {
@@ -1610,23 +1624,23 @@ type LoadBalancing struct {
16101624 // to spin if all backends are down and latency is very low.
16111625 TryInterval caddy.Duration `json:"try_interval,omitempty"`
16121626
1613- // A list of matcher sets that restricts with which requests retries are
1614- // allowed. A request must match any of the given matcher sets in order
1615- // to be retried if the connection to the upstream succeeded but the
1616- // subsequent round-trip failed. If the connection to the upstream failed,
1617- // a retry is always allowed. If unspecified, only GET requests will be
1618- // allowed to be retried. Note that a retry is done with the next available
1619- // host according to the load balancing policy.
1627+ // Deprecated: Use RetryConditionsRaw instead. Kept for backward
1628+ // compatibility with the JSON API. Entries are converted to
1629+ // RetryConditionsRaw during provisioning.
16201630 RetryMatchRaw caddyhttp.RawMatcherSets `json:"retry_match,omitempty" caddy:"namespace=http.matchers"`
16211631
16221632 // A list of retry condition sets. Each set bundles request matchers
1623- // with optional status codes. A retry is triggered if the upstream
1624- // responds with a matching status code. Within a set, the request
1625- // must also match the matchers (if any).
1633+ // with optional status codes. A request must match any of the given
1634+ // condition sets in order to be retried if the connection to the
1635+ // upstream succeeded but the subsequent round-trip failed. If the
1636+ // connection to the upstream failed, a retry is always allowed. If
1637+ // a condition has status codes, the upstream's response status must
1638+ // match one of them for a retry to be triggered. If unspecified,
1639+ // only GET requests will be retried. Note that a retry is done with
1640+ // the next available host according to the load balancing policy.
16261641 RetryConditionsRaw []* RetryConditionSet `json:"retry_conditions,omitempty"`
16271642
1628- SelectionPolicy Selector `json:"-"`
1629- RetryMatch caddyhttp.MatcherSets `json:"-"`
1643+ SelectionPolicy Selector `json:"-"`
16301644 retryConditions []* retryCondition
16311645}
16321646
0 commit comments