mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			111 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package presignedurl
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
 | 
						|
	v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
 | 
						|
 | 
						|
	"github.com/aws/smithy-go/middleware"
 | 
						|
)
 | 
						|
 | 
						|
// URLPresigner provides the interface to presign the input parameters in to a
 | 
						|
// presigned URL.
 | 
						|
type URLPresigner interface {
 | 
						|
	// PresignURL presigns a URL.
 | 
						|
	PresignURL(ctx context.Context, srcRegion string, params interface{}) (*v4.PresignedHTTPRequest, error)
 | 
						|
}
 | 
						|
 | 
						|
// ParameterAccessor provides an collection of accessor to for retrieving and
 | 
						|
// setting the values needed to PresignedURL generation
 | 
						|
type ParameterAccessor struct {
 | 
						|
	// GetPresignedURL accessor points to a function that retrieves a presigned url if present
 | 
						|
	GetPresignedURL func(interface{}) (string, bool, error)
 | 
						|
 | 
						|
	// GetSourceRegion accessor points to a function that retrieves source region for presigned url
 | 
						|
	GetSourceRegion func(interface{}) (string, bool, error)
 | 
						|
 | 
						|
	// CopyInput accessor points to a function that takes in an input, and returns a copy.
 | 
						|
	CopyInput func(interface{}) (interface{}, error)
 | 
						|
 | 
						|
	// SetDestinationRegion accessor points to a function that sets destination region on api input struct
 | 
						|
	SetDestinationRegion func(interface{}, string) error
 | 
						|
 | 
						|
	// SetPresignedURL accessor points to a function that sets presigned url on api input struct
 | 
						|
	SetPresignedURL func(interface{}, string) error
 | 
						|
}
 | 
						|
 | 
						|
// Options provides the set of options needed by the presigned URL middleware.
 | 
						|
type Options struct {
 | 
						|
	// Accessor are the parameter accessors used by this middleware
 | 
						|
	Accessor ParameterAccessor
 | 
						|
 | 
						|
	// Presigner is the URLPresigner used by the middleware
 | 
						|
	Presigner URLPresigner
 | 
						|
}
 | 
						|
 | 
						|
// AddMiddleware adds the Presign URL middleware to the middleware stack.
 | 
						|
func AddMiddleware(stack *middleware.Stack, opts Options) error {
 | 
						|
	return stack.Initialize.Add(&presign{options: opts}, middleware.Before)
 | 
						|
}
 | 
						|
 | 
						|
// RemoveMiddleware removes the Presign URL middleware from the stack.
 | 
						|
func RemoveMiddleware(stack *middleware.Stack) error {
 | 
						|
	_, err := stack.Initialize.Remove((*presign)(nil).ID())
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
type presign struct {
 | 
						|
	options Options
 | 
						|
}
 | 
						|
 | 
						|
func (m *presign) ID() string { return "Presign" }
 | 
						|
 | 
						|
func (m *presign) HandleInitialize(
 | 
						|
	ctx context.Context, input middleware.InitializeInput, next middleware.InitializeHandler,
 | 
						|
) (
 | 
						|
	out middleware.InitializeOutput, metadata middleware.Metadata, err error,
 | 
						|
) {
 | 
						|
	// If PresignedURL is already set ignore middleware.
 | 
						|
	if _, ok, err := m.options.Accessor.GetPresignedURL(input.Parameters); err != nil {
 | 
						|
		return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
 | 
						|
	} else if ok {
 | 
						|
		return next.HandleInitialize(ctx, input)
 | 
						|
	}
 | 
						|
 | 
						|
	// If have source region is not set ignore middleware.
 | 
						|
	srcRegion, ok, err := m.options.Accessor.GetSourceRegion(input.Parameters)
 | 
						|
	if err != nil {
 | 
						|
		return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
 | 
						|
	} else if !ok || len(srcRegion) == 0 {
 | 
						|
		return next.HandleInitialize(ctx, input)
 | 
						|
	}
 | 
						|
 | 
						|
	// Create a copy of the original input so the destination region value can
 | 
						|
	// be added. This ensures that value does not leak into the original
 | 
						|
	// request parameters.
 | 
						|
	paramCpy, err := m.options.Accessor.CopyInput(input.Parameters)
 | 
						|
	if err != nil {
 | 
						|
		return out, metadata, fmt.Errorf("unable to create presigned URL, %w", err)
 | 
						|
	}
 | 
						|
 | 
						|
	// Destination region is the API client's configured region.
 | 
						|
	dstRegion := awsmiddleware.GetRegion(ctx)
 | 
						|
	if err = m.options.Accessor.SetDestinationRegion(paramCpy, dstRegion); err != nil {
 | 
						|
		return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
 | 
						|
	}
 | 
						|
 | 
						|
	presignedReq, err := m.options.Presigner.PresignURL(ctx, srcRegion, paramCpy)
 | 
						|
	if err != nil {
 | 
						|
		return out, metadata, fmt.Errorf("unable to create presigned URL, %w", err)
 | 
						|
	}
 | 
						|
 | 
						|
	// Update the original input with the presigned URL value.
 | 
						|
	if err = m.options.Accessor.SetPresignedURL(input.Parameters, presignedReq.URL); err != nil {
 | 
						|
		return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
 | 
						|
	}
 | 
						|
 | 
						|
	return next.HandleInitialize(ctx, input)
 | 
						|
}
 |