src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

middleware.go (5344B)


      1 package client
      2 
      3 import (
      4 	"context"
      5 	"encoding/json"
      6 	"fmt"
      7 	"io"
      8 	"net/url"
      9 
     10 	"github.com/aws/smithy-go"
     11 	smithymiddleware "github.com/aws/smithy-go/middleware"
     12 	smithyhttp "github.com/aws/smithy-go/transport/http"
     13 )
     14 
     15 type buildEndpoint struct {
     16 	Endpoint string
     17 }
     18 
     19 func (b *buildEndpoint) ID() string {
     20 	return "BuildEndpoint"
     21 }
     22 
     23 func (b *buildEndpoint) HandleBuild(ctx context.Context, in smithymiddleware.BuildInput, next smithymiddleware.BuildHandler) (
     24 	out smithymiddleware.BuildOutput, metadata smithymiddleware.Metadata, err error,
     25 ) {
     26 	request, ok := in.Request.(*smithyhttp.Request)
     27 	if !ok {
     28 		return out, metadata, fmt.Errorf("unknown transport, %T", in.Request)
     29 	}
     30 
     31 	if len(b.Endpoint) == 0 {
     32 		return out, metadata, fmt.Errorf("endpoint not provided")
     33 	}
     34 
     35 	parsed, err := url.Parse(b.Endpoint)
     36 	if err != nil {
     37 		return out, metadata, fmt.Errorf("failed to parse endpoint, %w", err)
     38 	}
     39 
     40 	request.URL = parsed
     41 
     42 	return next.HandleBuild(ctx, in)
     43 }
     44 
     45 type serializeOpGetCredential struct{}
     46 
     47 func (s *serializeOpGetCredential) ID() string {
     48 	return "OperationSerializer"
     49 }
     50 
     51 func (s *serializeOpGetCredential) HandleSerialize(ctx context.Context, in smithymiddleware.SerializeInput, next smithymiddleware.SerializeHandler) (
     52 	out smithymiddleware.SerializeOutput, metadata smithymiddleware.Metadata, err error,
     53 ) {
     54 	request, ok := in.Request.(*smithyhttp.Request)
     55 	if !ok {
     56 		return out, metadata, fmt.Errorf("unknown transport type, %T", in.Request)
     57 	}
     58 
     59 	params, ok := in.Parameters.(*GetCredentialsInput)
     60 	if !ok {
     61 		return out, metadata, fmt.Errorf("unknown input parameters, %T", in.Parameters)
     62 	}
     63 
     64 	const acceptHeader = "Accept"
     65 	request.Header[acceptHeader] = append(request.Header[acceptHeader][:0], "application/json")
     66 
     67 	if len(params.AuthorizationToken) > 0 {
     68 		const authHeader = "Authorization"
     69 		request.Header[authHeader] = append(request.Header[authHeader][:0], params.AuthorizationToken)
     70 	}
     71 
     72 	return next.HandleSerialize(ctx, in)
     73 }
     74 
     75 type deserializeOpGetCredential struct{}
     76 
     77 func (d *deserializeOpGetCredential) ID() string {
     78 	return "OperationDeserializer"
     79 }
     80 
     81 func (d *deserializeOpGetCredential) HandleDeserialize(ctx context.Context, in smithymiddleware.DeserializeInput, next smithymiddleware.DeserializeHandler) (
     82 	out smithymiddleware.DeserializeOutput, metadata smithymiddleware.Metadata, err error,
     83 ) {
     84 	out, metadata, err = next.HandleDeserialize(ctx, in)
     85 
     86 	// Close the response body on every exit path in place of the standalone close middleware.
     87 	// Deferred in a closure so it observes the final err (this output is not a streaming
     88 	// payload, so it is always closed regardless).
     89 	response, _ := out.RawResponse.(*smithyhttp.Response)
     90 	defer func() { smithyhttp.CloseResponseBody(ctx, response, false, err) }()
     91 
     92 	if err != nil {
     93 		return out, metadata, err
     94 	}
     95 
     96 	if response == nil {
     97 		return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)}
     98 	}
     99 
    100 	if response.StatusCode < 200 || response.StatusCode >= 300 {
    101 		return out, metadata, deserializeError(response)
    102 	}
    103 
    104 	var shape *GetCredentialsOutput
    105 	if err = json.NewDecoder(response.Body).Decode(&shape); err != nil {
    106 		return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("failed to deserialize json response, %w", err)}
    107 	}
    108 
    109 	out.Result = shape
    110 	return out, metadata, err
    111 }
    112 
    113 func deserializeError(response *smithyhttp.Response) error {
    114 	// we could be talking to anything, json isn't guaranteed
    115 	// see https://github.com/aws/aws-sdk-go-v2/issues/2316
    116 	if response.Header.Get("Content-Type") == "application/json" {
    117 		return deserializeJSONError(response)
    118 	}
    119 
    120 	msg, err := io.ReadAll(response.Body)
    121 	if err != nil {
    122 		return &smithy.DeserializationError{
    123 			Err: fmt.Errorf("read response, %w", err),
    124 		}
    125 	}
    126 
    127 	return &EndpointError{
    128 		// no sensible value for Code
    129 		Message:    string(msg),
    130 		Fault:      stof(response.StatusCode),
    131 		statusCode: response.StatusCode,
    132 	}
    133 }
    134 
    135 func deserializeJSONError(response *smithyhttp.Response) error {
    136 	var errShape *EndpointError
    137 	if err := json.NewDecoder(response.Body).Decode(&errShape); err != nil {
    138 		return &smithy.DeserializationError{
    139 			Err: fmt.Errorf("failed to decode error message, %w", err),
    140 		}
    141 	}
    142 
    143 	errShape.Fault = stof(response.StatusCode)
    144 	errShape.statusCode = response.StatusCode
    145 	return errShape
    146 }
    147 
    148 // maps HTTP status code to smithy ErrorFault
    149 func stof(code int) smithy.ErrorFault {
    150 	if code >= 500 {
    151 		return smithy.FaultServer
    152 	}
    153 	return smithy.FaultClient
    154 }
    155 
    156 func addProtocolFinalizerMiddlewares(stack *smithymiddleware.Stack, options Options, operation string) error {
    157 	if err := stack.Finalize.Add(&resolveAuthSchemeMiddleware{operation: operation, options: options}, smithymiddleware.Before); err != nil {
    158 		return fmt.Errorf("add ResolveAuthScheme: %w", err)
    159 	}
    160 	if err := stack.Finalize.Insert(&getIdentityMiddleware{options: options}, "ResolveAuthScheme", smithymiddleware.After); err != nil {
    161 		return fmt.Errorf("add GetIdentity: %w", err)
    162 	}
    163 	if err := stack.Finalize.Insert(&resolveEndpointV2Middleware{options: options}, "GetIdentity", smithymiddleware.After); err != nil {
    164 		return fmt.Errorf("add ResolveEndpointV2: %w", err)
    165 	}
    166 	if err := stack.Finalize.Insert(&signRequestMiddleware{}, "ResolveEndpointV2", smithymiddleware.After); err != nil {
    167 		return fmt.Errorf("add Signing: %w", err)
    168 	}
    169 	return nil
    170 }