catch 202 early
This commit is contained in:
		| @@ -47,6 +47,16 @@ type ClientInterface interface { | |||||||
| 	DeleteService(string) error | 	DeleteService(string) error | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // StatusErr might get returned from an api call if your request is still being processed | ||||||
|  | // and hence the expected return data is not available yet. | ||||||
|  | type StatusErr struct { | ||||||
|  | 	Status api.Status | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *StatusErr) Error() string { | ||||||
|  | 	return fmt.Sprintf("Status: %v (%#v)", s.Status.Status, s) | ||||||
|  | } | ||||||
|  |  | ||||||
| // AuthInfo is used to store authorization information | // AuthInfo is used to store authorization information | ||||||
| type AuthInfo struct { | type AuthInfo struct { | ||||||
| 	User     string | 	User     string | ||||||
| @@ -93,6 +103,13 @@ func (c *Client) doRequest(request *http.Request) ([]byte, error) { | |||||||
| 	if response.StatusCode < http.StatusOK || response.StatusCode > http.StatusPartialContent { | 	if response.StatusCode < http.StatusOK || response.StatusCode > http.StatusPartialContent { | ||||||
| 		return nil, fmt.Errorf("request [%#v] failed (%d) %s: %s", request, response.StatusCode, response.Status, string(body)) | 		return nil, fmt.Errorf("request [%#v] failed (%d) %s: %s", request, response.StatusCode, response.Status, string(body)) | ||||||
| 	} | 	} | ||||||
|  | 	if response.StatusCode == http.StatusAccepted { | ||||||
|  | 		var status api.Status | ||||||
|  | 		if err := api.DecodeInto(body, &status); err == nil { | ||||||
|  | 			return nil, &StatusErr{status} | ||||||
|  | 		} | ||||||
|  | 		// Sometimes the server returns 202 even though it completely handled the request. | ||||||
|  | 	} | ||||||
| 	return body, err | 	return body, err | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -427,3 +427,37 @@ func TestDoRequest(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	fakeHandler.ValidateRequest(t, "/foo/bar", "GET", nil) | 	fakeHandler.ValidateRequest(t, "/foo/bar", "GET", nil) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestDoRequestAccepted(t *testing.T) { | ||||||
|  | 	status := api.Status{Status: api.StatusWorking} | ||||||
|  | 	expectedBody, _ := api.Encode(status) | ||||||
|  | 	fakeHandler := util.FakeHandler{ | ||||||
|  | 		StatusCode:   202, | ||||||
|  | 		ResponseBody: string(expectedBody), | ||||||
|  | 		T:            t, | ||||||
|  | 	} | ||||||
|  | 	testServer := httptest.NewTLSServer(&fakeHandler) | ||||||
|  | 	request, _ := http.NewRequest("GET", testServer.URL+"/foo/bar", nil) | ||||||
|  | 	auth := AuthInfo{User: "user", Password: "pass"} | ||||||
|  | 	c := New(testServer.URL, &auth) | ||||||
|  | 	body, err := c.doRequest(request) | ||||||
|  | 	if request.Header["Authorization"] == nil { | ||||||
|  | 		t.Errorf("Request is missing authorization header: %#v", *request) | ||||||
|  | 	} | ||||||
|  | 	if err == nil { | ||||||
|  | 		t.Error("Unexpected non-error") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	se, ok := err.(*StatusErr) | ||||||
|  | 	if !ok { | ||||||
|  | 		t.Errorf("Unexpected kind of error: %#v", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if !reflect.DeepEqual(se.Status, status) { | ||||||
|  | 		t.Errorf("Unexpected status: %#v", se.Status) | ||||||
|  | 	} | ||||||
|  | 	if body != nil { | ||||||
|  | 		t.Errorf("Expected nil body, but saw: '%s'", body) | ||||||
|  | 	} | ||||||
|  | 	fakeHandler.ValidateRequest(t, "/foo/bar", "GET", nil) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -166,6 +166,14 @@ func (r *Request) Do() Result { | |||||||
| 		return Result{err: err} | 		return Result{err: err} | ||||||
| 	} | 	} | ||||||
| 	respBody, err := r.c.doRequest(req) | 	respBody, err := r.c.doRequest(req) | ||||||
|  | 	if err != nil { | ||||||
|  | 		if statusErr, ok := err.(*StatusErr); ok { | ||||||
|  | 			// TODO: using the information in statusErr, | ||||||
|  | 			// loop querying the server to wait and retrieve | ||||||
|  | 			// the actual result. | ||||||
|  | 			_ = statusErr | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	return Result{respBody, err} | 	return Result{respBody, err} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Daniel Smith
					Daniel Smith