Skip to content

Commit 64b4a9c

Browse files
committed
API client: Enable fallback on status code 501, too
When discussing #801, I remembered #794. While dealing with the latter, I read the HTTP RFC, stumbling upon the following: When a request method is received that is unrecognized or not implemented by an origin server, the origin server SHOULD respond with the 501 (Not Implemented) status code. When a request method is received that is known by an origin server but not allowed for the target resource, the origin server SHOULD respond with the 405 (Method Not Allowed) status code. Concluding from that, it is possible that a server desiring a fallback to GET will send a status code of 501. It is even preferred if that server does not offer any resource to be used with the POST method. Therefore, I think we should fallback to GET on a 501, too. Signed-off-by: beorn7 <[email protected]>
1 parent 65c5578 commit 64b4a9c

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

api/prometheus/v1/api.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,8 @@ func (h *apiClientImpl) Do(ctx context.Context, req *http.Request) (*http.Respon
10041004

10051005
}
10061006

1007-
// DoGetFallback will attempt to do the request as-is, and on a 405 it will fallback to a GET request.
1007+
// DoGetFallback will attempt to do the request as-is, and on a 405 or 501 it
1008+
// will fallback to a GET request.
10081009
func (h *apiClientImpl) DoGetFallback(ctx context.Context, u *url.URL, args url.Values) (*http.Response, []byte, Warnings, error) {
10091010
req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(args.Encode()))
10101011
if err != nil {
@@ -1013,7 +1014,7 @@ func (h *apiClientImpl) DoGetFallback(ctx context.Context, u *url.URL, args url.
10131014
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
10141015

10151016
resp, body, warnings, err := h.Do(ctx, req)
1016-
if resp != nil && resp.StatusCode == http.StatusMethodNotAllowed {
1017+
if resp != nil && (resp.StatusCode == http.StatusMethodNotAllowed || resp.StatusCode == http.StatusNotImplemented) {
10171018
u.RawQuery = args.Encode()
10181019
req, err = http.NewRequest(http.MethodGet, u.String(), nil)
10191020
if err != nil {

api/prometheus/v1/api_test.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,12 +1447,19 @@ func TestDoGetFallback(t *testing.T) {
14471447
body, _ := json.Marshal(apiResp)
14481448

14491449
if req.Method == http.MethodPost {
1450-
if req.URL.Path == "/blockPost" {
1450+
if req.URL.Path == "/blockPost405" {
14511451
http.Error(w, string(body), http.StatusMethodNotAllowed)
14521452
return
14531453
}
14541454
}
14551455

1456+
if req.Method == http.MethodPost {
1457+
if req.URL.Path == "/blockPost501" {
1458+
http.Error(w, string(body), http.StatusNotImplemented)
1459+
return
1460+
}
1461+
}
1462+
14561463
w.Write(body)
14571464
}))
14581465
// Close the server when test finishes.
@@ -1483,8 +1490,24 @@ func TestDoGetFallback(t *testing.T) {
14831490
t.Fatalf("Mismatch in values")
14841491
}
14851492

1486-
// Do a fallbcak to a get.
1487-
u.Path = "/blockPost"
1493+
// Do a fallback to a get on 405.
1494+
u.Path = "/blockPost405"
1495+
_, b, _, err = api.DoGetFallback(context.TODO(), u, v)
1496+
if err != nil {
1497+
t.Fatalf("Error doing local request: %v", err)
1498+
}
1499+
if err := json.Unmarshal(b, resp); err != nil {
1500+
t.Fatal(err)
1501+
}
1502+
if resp.Method != http.MethodGet {
1503+
t.Fatalf("Mismatch method")
1504+
}
1505+
if resp.Values != v.Encode() {
1506+
t.Fatalf("Mismatch in values")
1507+
}
1508+
1509+
// Do a fallback to a get on 501.
1510+
u.Path = "/blockPost501"
14881511
_, b, _, err = api.DoGetFallback(context.TODO(), u, v)
14891512
if err != nil {
14901513
t.Fatalf("Error doing local request: %v", err)

0 commit comments

Comments
 (0)