File: middleware.go

package info (click to toggle)
golang-github-aws-aws-sdk-go-v2 1.30.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 662,428 kB
  • sloc: java: 16,875; makefile: 432; sh: 175
file content (164 lines) | stat: -rw-r--r-- 5,027 bytes parent folder | download | duplicates (6)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package client

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/url"

	"github.com/aws/smithy-go"
	smithymiddleware "github.com/aws/smithy-go/middleware"
	smithyhttp "github.com/aws/smithy-go/transport/http"
)

type buildEndpoint struct {
	Endpoint string
}

func (b *buildEndpoint) ID() string {
	return "BuildEndpoint"
}

func (b *buildEndpoint) HandleBuild(ctx context.Context, in smithymiddleware.BuildInput, next smithymiddleware.BuildHandler) (
	out smithymiddleware.BuildOutput, metadata smithymiddleware.Metadata, err error,
) {
	request, ok := in.Request.(*smithyhttp.Request)
	if !ok {
		return out, metadata, fmt.Errorf("unknown transport, %T", in.Request)
	}

	if len(b.Endpoint) == 0 {
		return out, metadata, fmt.Errorf("endpoint not provided")
	}

	parsed, err := url.Parse(b.Endpoint)
	if err != nil {
		return out, metadata, fmt.Errorf("failed to parse endpoint, %w", err)
	}

	request.URL = parsed

	return next.HandleBuild(ctx, in)
}

type serializeOpGetCredential struct{}

func (s *serializeOpGetCredential) ID() string {
	return "OperationSerializer"
}

func (s *serializeOpGetCredential) HandleSerialize(ctx context.Context, in smithymiddleware.SerializeInput, next smithymiddleware.SerializeHandler) (
	out smithymiddleware.SerializeOutput, metadata smithymiddleware.Metadata, err error,
) {
	request, ok := in.Request.(*smithyhttp.Request)
	if !ok {
		return out, metadata, fmt.Errorf("unknown transport type, %T", in.Request)
	}

	params, ok := in.Parameters.(*GetCredentialsInput)
	if !ok {
		return out, metadata, fmt.Errorf("unknown input parameters, %T", in.Parameters)
	}

	const acceptHeader = "Accept"
	request.Header[acceptHeader] = append(request.Header[acceptHeader][:0], "application/json")

	if len(params.AuthorizationToken) > 0 {
		const authHeader = "Authorization"
		request.Header[authHeader] = append(request.Header[authHeader][:0], params.AuthorizationToken)
	}

	return next.HandleSerialize(ctx, in)
}

type deserializeOpGetCredential struct{}

func (d *deserializeOpGetCredential) ID() string {
	return "OperationDeserializer"
}

func (d *deserializeOpGetCredential) HandleDeserialize(ctx context.Context, in smithymiddleware.DeserializeInput, next smithymiddleware.DeserializeHandler) (
	out smithymiddleware.DeserializeOutput, metadata smithymiddleware.Metadata, err error,
) {
	out, metadata, err = next.HandleDeserialize(ctx, in)
	if err != nil {
		return out, metadata, err
	}

	response, ok := out.RawResponse.(*smithyhttp.Response)
	if !ok {
		return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)}
	}

	if response.StatusCode < 200 || response.StatusCode >= 300 {
		return out, metadata, deserializeError(response)
	}

	var shape *GetCredentialsOutput
	if err = json.NewDecoder(response.Body).Decode(&shape); err != nil {
		return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("failed to deserialize json response, %w", err)}
	}

	out.Result = shape
	return out, metadata, err
}

func deserializeError(response *smithyhttp.Response) error {
	// we could be talking to anything, json isn't guaranteed
	// see https://github.com/aws/aws-sdk-go-v2/issues/2316
	if response.Header.Get("Content-Type") == "application/json" {
		return deserializeJSONError(response)
	}

	msg, err := io.ReadAll(response.Body)
	if err != nil {
		return &smithy.DeserializationError{
			Err: fmt.Errorf("read response, %w", err),
		}
	}

	return &EndpointError{
		// no sensible value for Code
		Message:    string(msg),
		Fault:      stof(response.StatusCode),
		statusCode: response.StatusCode,
	}
}

func deserializeJSONError(response *smithyhttp.Response) error {
	var errShape *EndpointError
	if err := json.NewDecoder(response.Body).Decode(&errShape); err != nil {
		return &smithy.DeserializationError{
			Err: fmt.Errorf("failed to decode error message, %w", err),
		}
	}

	errShape.Fault = stof(response.StatusCode)
	errShape.statusCode = response.StatusCode
	return errShape
}

// maps HTTP status code to smithy ErrorFault
func stof(code int) smithy.ErrorFault {
	if code >= 500 {
		return smithy.FaultServer
	}
	return smithy.FaultClient
}

func addProtocolFinalizerMiddlewares(stack *smithymiddleware.Stack, options Options, operation string) error {
	if err := stack.Finalize.Add(&resolveAuthSchemeMiddleware{operation: operation, options: options}, smithymiddleware.Before); err != nil {
		return fmt.Errorf("add ResolveAuthScheme: %w", err)
	}
	if err := stack.Finalize.Insert(&getIdentityMiddleware{options: options}, "ResolveAuthScheme", smithymiddleware.After); err != nil {
		return fmt.Errorf("add GetIdentity: %w", err)
	}
	if err := stack.Finalize.Insert(&resolveEndpointV2Middleware{options: options}, "GetIdentity", smithymiddleware.After); err != nil {
		return fmt.Errorf("add ResolveEndpointV2: %w", err)
	}
	if err := stack.Finalize.Insert(&signRequestMiddleware{}, "ResolveEndpointV2", smithymiddleware.After); err != nil {
		return fmt.Errorf("add Signing: %w", err)
	}
	return nil
}