Skip to content

Commit c751e16

Browse files
committed
feat: add TemporarilyUnavailableError for 503 responses
1 parent 81d7993 commit c751e16

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func (c *Client) handleError(resp *http.Response, body []byte) error {
140140
}
141141

142142
var retryAfter int
143-
if resp.StatusCode == 429 {
143+
if resp.StatusCode == 429 || resp.StatusCode == 503 {
144144
if v := resp.Header.Get("Retry-After"); v != "" {
145145
retryAfter, _ = strconv.Atoi(v)
146146
}

client_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,35 @@ func TestErrorResponses(t *testing.T) {
567567
}
568568
},
569569
},
570+
{
571+
name: "503 TemporarilyUnavailableError",
572+
status: 503,
573+
body: `{"error":"temporarily_unavailable","message":"Data for this domain is temporarily unavailable."}`,
574+
headers: map[string]string{"Retry-After": "300"},
575+
checkErr: func(t *testing.T, err error) {
576+
var target *TemporarilyUnavailableError
577+
if !errors.As(err, &target) {
578+
t.Fatal("expected TemporarilyUnavailableError")
579+
}
580+
if target.RetryAfter != 300 {
581+
t.Errorf("RetryAfter = %d, want 300", target.RetryAfter)
582+
}
583+
},
584+
},
585+
{
586+
name: "503 TemporarilyUnavailableError without Retry-After",
587+
status: 503,
588+
body: `{"error":"temporarily_unavailable","message":"Data for this domain is temporarily unavailable."}`,
589+
checkErr: func(t *testing.T, err error) {
590+
var target *TemporarilyUnavailableError
591+
if !errors.As(err, &target) {
592+
t.Fatal("expected TemporarilyUnavailableError")
593+
}
594+
if target.RetryAfter != 0 {
595+
t.Errorf("RetryAfter = %d, want 0", target.RetryAfter)
596+
}
597+
},
598+
},
570599
{
571600
name: "500 unknown error",
572601
status: 500,

errors.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ type NotFoundError struct{ *APIError }
3333
// RateLimitError is returned when rate limit or monthly quota is exceeded (HTTP 429).
3434
type RateLimitError struct{ *APIError }
3535

36+
// TemporarilyUnavailableError is returned when the domain data is temporarily unavailable (HTTP 503).
37+
type TemporarilyUnavailableError struct{ *APIError }
38+
3639
// UpstreamError is returned when the upstream RDAP server fails (HTTP 502).
3740
type UpstreamError struct{ *APIError }
3841

@@ -58,6 +61,8 @@ func newError(statusCode int, code, message string, retryAfter int) error {
5861
return &RateLimitError{base}
5962
case 502:
6063
return &UpstreamError{base}
64+
case 503:
65+
return &TemporarilyUnavailableError{base}
6166
default:
6267
return base
6368
}

errors_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func TestNewErrorTypedErrors(t *testing.T) {
4242
{404, "not_found", "not found", 0, "NotFoundError"},
4343
{429, "rate_limited", "too many", 30, "RateLimitError"},
4444
{502, "upstream_error", "upstream fail", 0, "UpstreamError"},
45+
{503, "temporarily_unavailable", "temporarily unavailable", 300, "TemporarilyUnavailableError"},
4546
}
4647

4748
for _, tt := range tests {
@@ -94,6 +95,15 @@ func TestNewErrorTypedErrors(t *testing.T) {
9495
t.Fatal("errors.As failed for UpstreamError")
9596
}
9697
checkBase(t, target.APIError, tt)
98+
case 503:
99+
var target *TemporarilyUnavailableError
100+
if !errors.As(err, &target) {
101+
t.Fatal("errors.As failed for TemporarilyUnavailableError")
102+
}
103+
checkBase(t, target.APIError, tt)
104+
if target.RetryAfter != 300 {
105+
t.Errorf("RetryAfter = %d, want 300", target.RetryAfter)
106+
}
97107
}
98108

99109
// Typed errors embed *APIError, accessible via the field.

0 commit comments

Comments
 (0)