AWS SDK for Go v2 with 130+ service clients, Request/Send pattern, and context support.
All AWS SDK v2 service operations follow a consistent Request/Send pattern.
// 1. Create service client
cfg, _ := external.LoadDefaultAWSConfig()
cfg.Region = "us-east-1"
svc := s3.New(cfg) // or any other service
// 2. Create operation request (typed per service)
req := svc.GetObjectRequest(&s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("my-key"),
})
// 3. Send the request
resp, err := req.Send()
if err != nil { ... }
fmt.Println(resp.ContentLength)Each API operation has a corresponding typed request struct:
// Service clients expose methods returning typed requests:
// func (c *ServiceName) <OperationName>Request(input *<OperationName>Input) <OperationName>Request
// Each typed request struct wraps an aws.Request and provides Send():
type <OperationName>Request struct {
Input *<OperationName>Input
Copy func(*<OperationName>Input) <OperationName>Request
// unexported aws.Request
}
func (r <OperationName>Request) Send() (*<OperationName>Output, error)
func (r <OperationName>Request) Presign(expireTime time.Duration) (string, error)
func (r <OperationName>Request) PresignRequest(expireTime time.Duration) (string, http.Header, error)func (r *aws.Request) SetContext(ctx aws.Context)ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
req := svc.GetObjectRequest(&s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("my-key"),
})
req.SetContext(ctx)
resp, err := req.Send()For paginated operations, service clients expose Paginate() methods that return typed pagers.
// Service clients expose (for paginated operations):
type <OperationName>Pager struct {
// unexported fields
}
func (p *<OperationName>Pager) Next() bool
func (p *<OperationName>Pager) CurrentPage() *<OperationName>Output
func (p *<OperationName>Pager) Err() error
// The request object also has Paginate():
func (r <OperationName>Request) Paginate() *<OperationName>Pagerreq := svc.ListObjectsV2Request(&s3.ListObjectsV2Input{
Bucket: aws.String("my-bucket"),
})
p := req.Paginate()
for p.Next() {
page := p.CurrentPage()
for _, obj := range page.Contents {
fmt.Println(*obj.Key)
}
}
if err := p.Err(); err != nil {
return err
}type Pager struct {
NewRequest func() (*aws.Request, error)
// unexported fields
}
func (p *Pager) Next() bool
func (p *Pager) CurrentPage() interface{}
func (p *Pager) Err() errorGenerate pre-signed URLs for temporary access to S3 objects (or other presignable operations).
// On a service request:
func (r <OperationName>Request) Presign(expireTime time.Duration) (string, error)
func (r <OperationName>Request) PresignRequest(expireTime time.Duration) (string, http.Header, error)svc := s3.New(cfg)
req := svc.GetObjectRequest(&s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("my-key"),
})
// Presign returns just the URL
url, err := req.Presign(15 * time.Minute)
if err != nil { ... }
// PresignRequest returns URL + headers that must be included with the request
url, headers, err := req.PresignRequest(15 * time.Minute)Modify individual requests without changing the service client.
type Option func(*aws.Request)// Add custom header to a specific request
req := svc.PutObjectRequest(&s3.PutObjectInput{...})
req.ApplyOptions(func(r *aws.Request) {
r.HTTPRequest.Header.Set("x-amz-server-side-encryption", "AES256")
})
resp, err := req.Send()// On aws.Request:
func (r *Request) SetBufferBody(buf []byte)
func (r *Request) SetStringBody(s string)
func (r *Request) SetReaderBody(reader io.ReadSeeker)
func (r *Request) ResetBody()
func (r *Request) GetBody() io.ReadSeekerWaiters poll an API until a resource reaches a desired state.
// Service clients expose WaitUntil<State> methods:
// func (c *ServiceClient) WaitUntil<State>(ctx aws.Context, input *<Input>, opts ...aws.WaiterOption) error// Wait for EC2 instance to be running
err := svc.WaitUntilInstanceRunning(aws.BackgroundContext(), &ec2.DescribeInstancesInput{
InstanceIds: []string{"i-1234567890abcdef0"},
})
// Wait with custom options
err := svc.WaitUntilInstanceRunning(ctx, input,
aws.WithWaiterDelay(aws.ConstantWaiterDelay(5 * time.Second)),
aws.WithWaiterMaxAttempts(60),
)resp, err := req.Send()
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case s3.ErrCodeNoSuchBucket:
fmt.Println("bucket does not exist")
case s3.ErrCodeNoSuchKey:
fmt.Println("key does not exist")
default:
fmt.Println("AWS error:", aerr.Code(), aerr.Message())
}
// Check for HTTP-level error
if reqErr, ok := err.(awserr.RequestFailure); ok {
fmt.Println("HTTP status:", reqErr.StatusCode())
fmt.Println("Request ID:", reqErr.RequestID())
}
} else {
fmt.Println("Error:", err)
}
}These are available on the underlying aws.Request, accessible as req.Request:
func (r *Request) Send() error
func (r *Request) Sign() error
func (r *Request) SetContext(ctx Context)
func (r *Request) Presign(expireTime time.Duration) (string, error)
func (r *Request) PresignRequest(expireTime time.Duration) (string, http.Header, error)
func (r *Request) ParamsFilled() bool
func (r *Request) WillRetry() bool
func (r *Request) IsErrorExpired() bool
func (r *Request) IsErrorRetryable() bool
func (r *Request) IsErrorThrottle() boolAttach custom logic at various stages of the request lifecycle.
svc := s3.New(cfg)
svc.Handlers.Send.PushBack(func(r *aws.Request) {
fmt.Println("Sending request:", r.Operation.Name)
})
svc.Handlers.Complete.PushBack(func(r *aws.Request) {
fmt.Println("Request complete:", r.Operation.Name, "Error:", r.Error)
})Available handler lists on aws.Handlers:
Validate - Validates request parametersBuild - Builds the HTTP requestSign - Signs the requestSend - Sends the HTTP requestValidateResponse - Validates the HTTP responseUnmarshal - Unmarshal response bodyUnmarshalMeta - Unmarshal response metadataUnmarshalError - Unmarshal error responsesRetry - Determines if retry should occurAfterRetry - Actions after retry decisionComplete - Final handler, always runs// From aws package
type Response struct {
Request *aws.Request
}Service-specific output types are returned by Send() and contain all response fields.
Install with Tessl CLI
npx tessl i tessl/golang-github-com--aws--aws-sdk-go-v2@0.4.0