File: response_error_example_test.go

package info (click to toggle)
golang-github-aws-smithy-go 1.20.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,116 kB
  • sloc: java: 19,678; xml: 166; sh: 131; makefile: 70
file content (116 lines) | stat: -rw-r--r-- 3,281 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package http

import (
	"context"
	"errors"
	"fmt"
	"net/http"

	"github.com/aws/smithy-go"
	"github.com/aws/smithy-go/middleware"
)

func ExampleResponseError() {
	stack := middleware.NewStack("my cool stack", NewStackRequest)

	stack.Deserialize.Add(middleware.DeserializeMiddlewareFunc("wrap http response error",
		func(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
			out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
		) {
			out, metadata, err = next.HandleDeserialize(ctx, in)
			if err == nil {
				// Nothing to do when there is no error.
				return out, metadata, err
			}

			rawResp, ok := out.RawResponse.(*Response)
			if !ok {
				// No raw response to wrap with.
				return out, metadata, err
			}

			// Wrap the returned error with the response error containing the
			// returned response.
			err = &ResponseError{
				Response: rawResp,
				Err:      err,
			}

			return out, metadata, err
		}),
		middleware.After,
	)

	stack.Deserialize.Add(middleware.DeserializeMiddlewareFunc("deserialize error",
		func(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
			out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
		) {
			out, metadata, err = next.HandleDeserialize(ctx, in)
			if err != nil {
				return middleware.DeserializeOutput{}, metadata, err
			}

			rawResp := out.RawResponse.(*Response)
			if rawResp.StatusCode == 200 {
				return out, metadata, nil
			}

			// Deserialize the response API error values.
			err = &smithy.GenericAPIError{
				Code:    rawResp.Header.Get("Error-Code"),
				Message: rawResp.Header.Get("Error-Message"),
			}

			return out, metadata, err
		}),
		middleware.After,
	)

	// Mock example handler taking the request input and returning a response
	mockHandler := middleware.HandlerFunc(func(ctx context.Context, in interface{}) (
		output interface{}, metadata middleware.Metadata, err error,
	) {
		// populate the mock response with an API error and additional data.
		resp := &http.Response{
			StatusCode: 404,
			Header: http.Header{
				"Extra-Header":  []string{"foo value"},
				"Error-Code":    []string{"FooException"},
				"Error-Message": []string{"some message about the error"},
			},
		}

		// The handler's returned response will be available as the
		// DeserializeOutput.RawResponse field.
		return &Response{
			Response: resp,
		}, metadata, nil
	})

	// Use the stack to decorate the handler then invoke the decorated handler
	// with the inputs.
	handler := middleware.DecorateHandler(mockHandler, stack)
	_, _, err := handler.Handle(context.Background(), struct{}{})
	if err == nil {
		fmt.Printf("expect error, got none")
		return
	}

	if err != nil {
		var apiErr smithy.APIError
		if errors.As(err, &apiErr) {
			fmt.Printf("request failed: %s, %s\n", apiErr.ErrorCode(), apiErr.ErrorMessage())
		}

		var respErr *ResponseError
		if errors.As(err, &respErr) {
			fmt.Printf("response status: %v\n", respErr.HTTPStatusCode())
			fmt.Printf("response header: %v\n", respErr.HTTPResponse().Header.Get("Extra-Header"))
		}
	}

	// Output:
	// request failed: FooException, some message about the error
	// response status: 404
	// response header: foo value
}