diff options
| -rw-r--r-- | CHANGELOG.md | 9 | ||||
| -rw-r--r-- | errors.go | 7 | ||||
| -rw-r--r-- | request.go | 14 | ||||
| -rw-r--r-- | tests/container_test.go | 5 | ||||
| -rw-r--r-- | tests/object_test.go | 7 |
5 files changed, 37 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 17a55aa..67523ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# v1.3.0 (TBD) + +New features: + +- The error message of `type UnexpectedStatusCodeError` now includes the + request method and target object name. This will make those errors more + plausible when returned from complex operations that involve several Swift + API calls. + # v1.2.0 (2022-10-28) New features: @@ -60,6 +60,8 @@ var ( // a response with the expected successful status code. The actual status code // can be checked with the Is() function; see documentation over there. type UnexpectedStatusCodeError struct { + Method string //e.g. http.MethodGet + Target string //either "<account>" or "$CONTAINER_NAME" or "$CONTAINER_NAME/$OBJECT_NAME" ExpectedStatusCodes []int ActualResponse *http.Response ResponseBody []byte @@ -75,6 +77,11 @@ func (e UnexpectedStatusCodeError) Error() string { strings.Join(codeStrs, "/"), e.ActualResponse.StatusCode, ) + if e.Method != "" && e.Target != "" { + //NOTE: Method and Target were added in a minor version change, + //and may not be filled if `e` was constructed outside the library. + msg = fmt.Sprintf("could not %s %q in Swift: %s", e.Method, e.Target, msg) + } if len(e.ResponseBody) > 0 { msg += ": " + string(e.ResponseBody) } @@ -161,12 +161,26 @@ func (r Request) Do(backend Backend) (*http.Response, error) { return nil, err } return nil, UnexpectedStatusCodeError{ + Method: r.Method, + Target: describeTarget(r.ContainerName, r.ObjectName), ExpectedStatusCodes: r.ExpectStatusCodes, ActualResponse: resp, ResponseBody: buf, } } +// Builds a value for the UnexpectedStatusCodeError.Target attribute. +func describeTarget(containerName, objectName string) string { + switch { + case containerName == "": + return "<account>" + case objectName == "": + return containerName + default: + return containerName + "/" + objectName + } +} + func drainResponseBody(r *http.Response) error { _, err := io.Copy(io.Discard, r.Body) if err != nil { diff --git a/tests/container_test.go b/tests/container_test.go index eed4906..26dcaac 100644 --- a/tests/container_test.go +++ b/tests/container_test.go @@ -19,6 +19,7 @@ package tests import ( + "fmt" "net/http" "testing" @@ -40,14 +41,14 @@ func TestContainerLifecycle(t *testing.T) { expectBool(t, exists, false) _, err = c.Headers() - expectError(t, err, "expected 204 response, got 404 instead") + expectError(t, err, fmt.Sprintf("could not HEAD %q in Swift: expected 204 response, got 404 instead", containerName)) expectBool(t, schwift.Is(err, http.StatusNotFound), true) expectBool(t, schwift.Is(err, http.StatusNoContent), false) //DELETE should be idempotent and not return success on non-existence, but //OpenStack LOVES to be inconsistent with everything (including, notably, itself) err = c.Delete(nil) - expectError(t, err, "expected 204 response, got 404 instead: <html><h1>Not Found</h1><p>The resource could not be found.</p></html>") + expectError(t, err, fmt.Sprintf("could not DELETE %q in Swift: expected 204 response, got 404 instead: <html><h1>Not Found</h1><p>The resource could not be found.</p></html>", containerName)) err = c.Create(nil) expectSuccess(t, err) diff --git a/tests/object_test.go b/tests/object_test.go index 2f22b24..cfcc908 100644 --- a/tests/object_test.go +++ b/tests/object_test.go @@ -20,6 +20,7 @@ package tests import ( "bytes" + "fmt" "io" "net/http" "strings" @@ -41,14 +42,14 @@ func TestObjectLifecycle(t *testing.T) { expectObjectExistence(t, o, false) _, err := o.Headers() - expectError(t, err, "expected 200 response, got 404 instead") + expectError(t, err, fmt.Sprintf("could not HEAD %q in Swift: expected 200 response, got 404 instead", o.FullName())) expectBool(t, schwift.Is(err, http.StatusNotFound), true) expectBool(t, schwift.Is(err, http.StatusNoContent), false) //DELETE should be idempotent and not return success on non-existence, but //OpenStack LOVES to be inconsistent with everything (including, notably, itself) err = o.Delete(nil, nil) - expectError(t, err, "expected 204 response, got 404 instead: <html><h1>Not Found</h1><p>The resource could not be found.</p></html>") + expectError(t, err, fmt.Sprintf("could not DELETE %q in Swift: expected 204 response, got 404 instead: <html><h1>Not Found</h1><p>The resource could not be found.</p></html>", o.FullName())) err = o.Upload(bytes.NewReader([]byte("test")), nil, nil) expectSuccess(t, err) @@ -165,7 +166,7 @@ func TestObjectUpdate(t *testing.T) { newHeaders.ContentType().Set("application/json") err := obj.Update(newHeaders, nil) expectBool(t, schwift.Is(err, http.StatusNotFound), true) - expectError(t, err, "expected 202 response, got 404 instead: <html><h1>Not Found</h1><p>The resource could not be found.</p></html>") + expectError(t, err, fmt.Sprintf("could not POST %q in Swift: expected 202 response, got 404 instead: <html><h1>Not Found</h1><p>The resource could not be found.</p></html>", obj.FullName())) //create object err = obj.Upload(nil, nil, nil) |
