From 1ef60b5cd32e8470806dad1c559c4953916fe6fd Mon Sep 17 00:00:00 2001 From: Stefan Majewsky Date: Mon, 23 Oct 2023 13:01:31 +0200 Subject: add Method, Target to type UnexpectedStatusCodeError --- CHANGELOG.md | 9 +++++++++ errors.go | 7 +++++++ request.go | 14 ++++++++++++++ tests/container_test.go | 5 +++-- 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: diff --git a/errors.go b/errors.go index bee0b9f..06fa639 100644 --- a/errors.go +++ b/errors.go @@ -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 "" 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) } diff --git a/request.go b/request.go index 2e78f00..7b5da6d 100644 --- a/request.go +++ b/request.go @@ -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 "" + 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:

Not Found

The resource could not be found.

") + expectError(t, err, fmt.Sprintf("could not DELETE %q in Swift: expected 204 response, got 404 instead:

Not Found

The resource could not be found.

", 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:

Not Found

The resource could not be found.

") + expectError(t, err, fmt.Sprintf("could not DELETE %q in Swift: expected 204 response, got 404 instead:

Not Found

The resource could not be found.

", 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:

Not Found

The resource could not be found.

") + expectError(t, err, fmt.Sprintf("could not POST %q in Swift: expected 202 response, got 404 instead:

Not Found

The resource could not be found.

", obj.FullName())) //create object err = obj.Upload(nil, nil, nil) -- cgit v1.2.3