goamz: github.com/goamz/goamz/aws Index | Examples | Files

package aws

import "github.com/goamz/goamz/aws"

goamz - Go packages to interact with the Amazon Web Services.

https://wiki.ubuntu.com/goamz

Copyright (c) 2011 Canonical Ltd.

Written by Gustavo Niemeyer <gustavo.niemeyer@canonical.com>

Index

Examples

Package Files

attempt.go aws.go client.go regions.go sign.go

Constants

const (
    V2Signature      = iota
    V4Signature      = iota
    Route53Signature = iota
)

Defines the valid signers

const (
    ISO8601BasicFormat      = "20060102T150405Z"
    ISO8601BasicFormatShort = "20060102"
)

Common date formats for signing requests

Variables

var APNortheast = Region{
    "ap-northeast-1",
    "https://ec2.ap-northeast-1.amazonaws.com",
    "https://s3-ap-northeast-1.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.ap-northeast-1.amazonaws.com",
    "",
    "https://sns.ap-northeast-1.amazonaws.com",
    "https://sqs.ap-northeast-1.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.ap-northeast-1.amazonaws.com",
    "https://dynamodb.ap-northeast-1.amazonaws.com",
    ServiceInfo{"https://monitoring.ap-northeast-1.amazonaws.com", V2Signature},
    "https://autoscaling.ap-northeast-1.amazonaws.com",
    ServiceInfo{"https://rds.ap-northeast-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.ap-northeast-1.amazonaws.com",
    "https://ecs.ap-northeast-1.amazonaws.com",
    "https://streams.dynamodb.ap-northeast-1.amazonaws.com",
}
var APNortheast2 = Region{
    "ap-northeast-2",
    "https://ec2.ap-northeast-2.amazonaws.com",
    "https://s3-ap-northeast-2.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.ap-northeast-2.amazonaws.com",
    "",
    "https://sns.ap-northeast-2.amazonaws.com",
    "https://sqs.ap-northeast-2.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.ap-northeast-2.amazonaws.com",
    "https://dynamodb.ap-northeast-2.amazonaws.com",
    ServiceInfo{"https://monitoring.ap-northeast-2.amazonaws.com", V2Signature},
    "https://autoscaling.ap-northeast-2.amazonaws.com",
    ServiceInfo{"https://rds.ap-northeast-2.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.ap-northeast-2.amazonaws.com",
    "https://ecs.ap-northeast-2.amazonaws.com",
    "https://streams.dynamodb.ap-northeast-2.amazonaws.com",
}
var APSoutheast = Region{
    "ap-southeast-1",
    "https://ec2.ap-southeast-1.amazonaws.com",
    "https://s3-ap-southeast-1.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.ap-southeast-1.amazonaws.com",
    "",
    "https://sns.ap-southeast-1.amazonaws.com",
    "https://sqs.ap-southeast-1.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.ap-southeast-1.amazonaws.com",
    "https://dynamodb.ap-southeast-1.amazonaws.com",
    ServiceInfo{"https://monitoring.ap-southeast-1.amazonaws.com", V2Signature},
    "https://autoscaling.ap-southeast-1.amazonaws.com",
    ServiceInfo{"https://rds.ap-southeast-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.ap-southeast-1.amazonaws.com",
    "https://ecs.ap-southeast-1.amazonaws.com",
    "https://streams.dynamodb.ap-southeast-1.amazonaws.com",
}
var APSoutheast2 = Region{
    "ap-southeast-2",
    "https://ec2.ap-southeast-2.amazonaws.com",
    "https://s3-ap-southeast-2.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.ap-southeast-2.amazonaws.com",
    "",
    "https://sns.ap-southeast-2.amazonaws.com",
    "https://sqs.ap-southeast-2.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.ap-southeast-2.amazonaws.com",
    "https://dynamodb.ap-southeast-2.amazonaws.com",
    ServiceInfo{"https://monitoring.ap-southeast-2.amazonaws.com", V2Signature},
    "https://autoscaling.ap-southeast-2.amazonaws.com",
    ServiceInfo{"https://rds.ap-southeast-2.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.ap-southeast-2.amazonaws.com",
    "https://ecs.ap-southeast-2.amazonaws.com",
    "https://streams.dynamodb.ap-southeast-2.amazonaws.com",
}
var CNNorth = Region{
    "cn-north-1",
    "https://ec2.cn-north-1.amazonaws.com.cn",
    "https://s3.cn-north-1.amazonaws.com.cn",
    "",
    true,
    true,
    "https://sdb.cn-north-1.amazonaws.com.cn",
    "",
    "https://sns.cn-north-1.amazonaws.com.cn",
    "https://sqs.cn-north-1.amazonaws.com.cn",
    "https://iam.cn-north-1.amazonaws.com.cn",
    "https://elasticloadbalancing.cn-north-1.amazonaws.com.cn",
    "https://dynamodb.cn-north-1.amazonaws.com.cn",
    ServiceInfo{"https://monitoring.cn-north-1.amazonaws.com.cn", V4Signature},
    "https://autoscaling.cn-north-1.amazonaws.com.cn",
    ServiceInfo{"https://rds.cn-north-1.amazonaws.com.cn", V4Signature},
    "https://sts.cn-north-1.amazonaws.com.cn",
    "https://cloudformation.cn-north-1.amazonaws.com.cn",
    "https://ecs.cn-north-1.amazonaws.com.cn",
    "https://streams.dynamodb.cn-north-1.amazonaws.com.cn",
}
var EUCentral = Region{
    "eu-central-1",
    "https://ec2.eu-central-1.amazonaws.com",
    "https://s3-eu-central-1.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.eu-central-1.amazonaws.com",
    "https://email.eu-central-1.amazonaws.com",
    "https://sns.eu-central-1.amazonaws.com",
    "https://sqs.eu-central-1.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.eu-central-1.amazonaws.com",
    "https://dynamodb.eu-central-1.amazonaws.com",
    ServiceInfo{"https://monitoring.eu-central-1.amazonaws.com", V2Signature},
    "https://autoscaling.eu-central-1.amazonaws.com",
    ServiceInfo{"https://rds.eu-central-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.eu-central-1.amazonaws.com",
    "https://ecs.eu-central-1.amazonaws.com",
    "https://streams.dynamodb.eu-central-1.amazonaws.com",
}
var EUWest = Region{
    "eu-west-1",
    "https://ec2.eu-west-1.amazonaws.com",
    "https://s3-eu-west-1.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.eu-west-1.amazonaws.com",
    "https://email.eu-west-1.amazonaws.com",
    "https://sns.eu-west-1.amazonaws.com",
    "https://sqs.eu-west-1.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.eu-west-1.amazonaws.com",
    "https://dynamodb.eu-west-1.amazonaws.com",
    ServiceInfo{"https://monitoring.eu-west-1.amazonaws.com", V2Signature},
    "https://autoscaling.eu-west-1.amazonaws.com",
    ServiceInfo{"https://rds.eu-west-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.eu-west-1.amazonaws.com",
    "https://ecs.eu-west-1.amazonaws.com",
    "https://streams.dynamodb.eu-west-1.amazonaws.com",
}
var Regions = map[string]Region{
    APNortheast.Name:  APNortheast,
    APNortheast2.Name: APNortheast2,
    APSoutheast.Name:  APSoutheast,
    APSoutheast2.Name: APSoutheast2,
    EUCentral.Name:    EUCentral,
    EUWest.Name:       EUWest,
    USEast.Name:       USEast,
    USEast2.Name:      USEast2,
    USWest.Name:       USWest,
    USWest2.Name:      USWest2,
    USGovWest.Name:    USGovWest,
    SAEast.Name:       SAEast,
    CNNorth.Name:      CNNorth,
}
var RetryingClient = NewClient(retryingTransport)

Exported default client

var SAEast = Region{
    "sa-east-1",
    "https://ec2.sa-east-1.amazonaws.com",
    "https://s3-sa-east-1.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.sa-east-1.amazonaws.com",
    "",
    "https://sns.sa-east-1.amazonaws.com",
    "https://sqs.sa-east-1.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.sa-east-1.amazonaws.com",
    "https://dynamodb.sa-east-1.amazonaws.com",
    ServiceInfo{"https://monitoring.sa-east-1.amazonaws.com", V2Signature},
    "https://autoscaling.sa-east-1.amazonaws.com",
    ServiceInfo{"https://rds.sa-east-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.sa-east-1.amazonaws.com",
    "https://ecs.sa-east-1.amazonaws.com",
    "https://streams.dynamodb.sa-east-1.amazonaws.com",
}
var USEast = Region{
    "us-east-1",
    "https://ec2.us-east-1.amazonaws.com",
    "https://s3.amazonaws.com",
    "",
    false,
    false,
    "https://sdb.amazonaws.com",
    "https://email.us-east-1.amazonaws.com",
    "https://sns.us-east-1.amazonaws.com",
    "https://sqs.us-east-1.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.us-east-1.amazonaws.com",
    "https://dynamodb.us-east-1.amazonaws.com",
    ServiceInfo{"https://monitoring.us-east-1.amazonaws.com", V2Signature},
    "https://autoscaling.us-east-1.amazonaws.com",
    ServiceInfo{"https://rds.us-east-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.us-east-1.amazonaws.com",
    "https://ecs.us-east-1.amazonaws.com",
    "https://streams.dynamodb.us-east-1.amazonaws.com",
}
var USEast2 = Region{
    "us-east-2",
    "https://ec2.us-east-2.amazonaws.com",
    "https://s3.amazonaws.com",
    "",
    true,
    true,
    "",
    "",
    "https://sns.us-east-2.amazonaws.com",
    "https://sqs.us-east-2.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.us-east-2.amazonaws.com",
    "https://dynamodb.us-east-2.amazonaws.com",
    ServiceInfo{"https://monitoring.us-east-2.amazonaws.com", V2Signature},
    "https://autoscaling.us-east-1.amazonaws.com",
    ServiceInfo{"https://rds.us-east-2.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.us-east-2.amazonaws.com",
    "https://ecs.us-east-2.amazonaws.com",
    "https://streams.dynamodb.us-east-2.amazonaws.com",
}
var USGovWest = Region{
    "us-gov-west-1",
    "https://ec2.us-gov-west-1.amazonaws.com",
    "https://s3-fips-us-gov-west-1.amazonaws.com",
    "",
    true,
    true,
    "",
    "",
    "https://sns.us-gov-west-1.amazonaws.com",
    "https://sqs.us-gov-west-1.amazonaws.com",
    "https://iam.us-gov.amazonaws.com",
    "https://elasticloadbalancing.us-gov-west-1.amazonaws.com",
    "https://dynamodb.us-gov-west-1.amazonaws.com",
    ServiceInfo{"https://monitoring.us-gov-west-1.amazonaws.com", V2Signature},
    "https://autoscaling.us-gov-west-1.amazonaws.com",
    ServiceInfo{"https://rds.us-gov-west-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.us-gov-west-1.amazonaws.com",
    "https://ecs.us-gov-west-1.amazonaws.com",
    "https://streams.dynamodb.us-gov-west-1.amazonaws.com",
}
var USWest = Region{
    "us-west-1",
    "https://ec2.us-west-1.amazonaws.com",
    "https://s3-us-west-1.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.us-west-1.amazonaws.com",
    "",
    "https://sns.us-west-1.amazonaws.com",
    "https://sqs.us-west-1.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.us-west-1.amazonaws.com",
    "https://dynamodb.us-west-1.amazonaws.com",
    ServiceInfo{"https://monitoring.us-west-1.amazonaws.com", V2Signature},
    "https://autoscaling.us-west-1.amazonaws.com",
    ServiceInfo{"https://rds.us-west-1.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.us-west-1.amazonaws.com",
    "https://ecs.us-west-1.amazonaws.com",
    "https://streams.dynamodb.us-west-1.amazonaws.com",
}
var USWest2 = Region{
    "us-west-2",
    "https://ec2.us-west-2.amazonaws.com",
    "https://s3-us-west-2.amazonaws.com",
    "",
    true,
    true,
    "https://sdb.us-west-2.amazonaws.com",
    "https://email.us-west-2.amazonaws.com",
    "https://sns.us-west-2.amazonaws.com",
    "https://sqs.us-west-2.amazonaws.com",
    "https://iam.amazonaws.com",
    "https://elasticloadbalancing.us-west-2.amazonaws.com",
    "https://dynamodb.us-west-2.amazonaws.com",
    ServiceInfo{"https://monitoring.us-west-2.amazonaws.com", V2Signature},
    "https://autoscaling.us-west-2.amazonaws.com",
    ServiceInfo{"https://rds.us-west-2.amazonaws.com", V2Signature},
    "https://sts.amazonaws.com",
    "https://cloudformation.us-west-2.amazonaws.com",
    "https://ecs.us-west-2.amazonaws.com",
    "https://streams.dynamodb.us-west-2.amazonaws.com",
}

func Encode Uses

func Encode(s string) string

Encode takes a string and URI-encodes it in a way suitable to be used in AWS signatures.

func ExpBackoff Uses

func ExpBackoff(try int)

func GetMetaData Uses

func GetMetaData(path string) (contents []byte, err error)

GetMetaData retrieves instance metadata about the current machine.

See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html for more details.

func LinearBackoff Uses

func LinearBackoff(try int)

func MakeParams Uses

func MakeParams(action string) map[string]string

Create a base set of params for an action

func NewClient Uses

func NewClient(rt *ResilientTransport) *http.Client

Convenience method for creating an http client

type AWSService Uses

type AWSService interface {
    // Queries the AWS service at a given method/path with the params and
    // returns an http.Response and error
    Query(method, path string, params map[string]string) (*http.Response, error)
    // Builds an error given an XML payload in the http.Response, can be used
    // to process an error if the status code is not 200 for example.
    BuildError(r *http.Response) error
}

An AWS Service interface with the API to query the AWS service

Supplied as an easy way to mock out service calls during testing.

type Attempt Uses

type Attempt struct {
    // contains filtered or unexported fields
}

func (*Attempt) HasNext Uses

func (a *Attempt) HasNext() bool

HasNext returns whether another attempt will be made if the current one fails. If it returns true, the following call to Next is guaranteed to return true.

func (*Attempt) Next Uses

func (a *Attempt) Next() bool

Next waits until it is time to perform the next attempt or returns false if it is time to stop trying.

type AttemptStrategy Uses

type AttemptStrategy struct {
    Total time.Duration // total duration of attempt.
    Delay time.Duration // interval between each try in the burst.
    Min   int           // minimum number of retries; overrides Total
}

AttemptStrategy represents a strategy for waiting for an action to complete successfully. This is an internal type used by the implementation of other goamz packages.

func (AttemptStrategy) Start Uses

func (s AttemptStrategy) Start() *Attempt

Start begins a new sequence of attempts for the given strategy.

type Auth Uses

type Auth struct {
    AccessKey, SecretKey string
    // contains filtered or unexported fields
}

func EnvAuth Uses

func EnvAuth() (auth Auth, err error)

EnvAuth creates an Auth based on environment information. The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables are used. AWS_SESSION_TOKEN is used if present.

func GetAuth Uses

func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error)

GetAuth creates an Auth based on either passed in credentials, environment information or instance based role credentials.

func NewAuth Uses

func NewAuth(accessKey, secretKey, token string, expiration time.Time) *Auth

To be used with other APIs that return auth credentials such as STS

func SharedAuth Uses

func SharedAuth() (auth Auth, err error)

SharedAuth creates an Auth based on shared credentials stored in $HOME/.aws/credentials. The AWS_PROFILE environment variables is used to select the profile.

func (*Auth) Expiration Uses

func (a *Auth) Expiration() time.Time

func (*Auth) Token Uses

func (a *Auth) Token() string

type BaseResponse Uses

type BaseResponse struct {
    ResponseMetadata ResponseMetadata
}

type DeadlineFunc Uses

type DeadlineFunc func() time.Time

type Error Uses

type Error struct {
    StatusCode int
    Type       string
    Code       string
    Message    string
    RequestId  string
}

func (*Error) Error Uses

func (err *Error) Error() string

type ErrorResponse Uses

type ErrorResponse struct {
    Errors    Error  `xml:"Error"`
    RequestId string // A unique ID for tracking the request
}

type Region Uses

type Region struct {
    Name                    string // the canonical name of this region.
    EC2Endpoint             string
    S3Endpoint              string
    S3BucketEndpoint        string // Not needed by AWS S3. Use ${bucket} for bucket name.
    S3LocationConstraint    bool   // true if this region requires a LocationConstraint declaration.
    S3LowercaseBucket       bool   // true if the region requires bucket names to be lower case.
    SDBEndpoint             string
    SESEndpoint             string
    SNSEndpoint             string
    SQSEndpoint             string
    IAMEndpoint             string
    ELBEndpoint             string
    DynamoDBEndpoint        string
    CloudWatchServicepoint  ServiceInfo
    AutoScalingEndpoint     string
    RDSEndpoint             ServiceInfo
    STSEndpoint             string
    CloudFormationEndpoint  string
    ECSEndpoint             string
    DynamoDBStreamsEndpoint string
}

Region defines the URLs where AWS services may be accessed.

See http://goo.gl/d8BP1 for more details.

type ResilientTransport Uses

type ResilientTransport struct {
    // Timeout is the maximum amount of time a dial will wait for
    // a connect to complete.
    //
    // The default is no timeout.
    //
    // With or without a timeout, the operating system may impose
    // its own earlier timeout. For instance, TCP timeouts are
    // often around 3 minutes.
    DialTimeout time.Duration

    // MaxTries, if non-zero, specifies the number of times we will retry on
    // failure. Retries are only attempted for temporary network errors or known
    // safe failures.
    MaxTries    int
    Deadline    DeadlineFunc
    ShouldRetry RetryableFunc
    Wait        WaitFunc
    // contains filtered or unexported fields
}

func NewResilientTransport Uses

func NewResilientTransport(tr ...*http.Transport) *ResilientTransport

Convenience method for creating a RelisientTransport with optional http transport argument

func (*ResilientTransport) RoundTrip Uses

func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error)

type ResponseMetadata Uses

type ResponseMetadata struct {
    RequestId string // A unique ID for tracking the request
}

ResponseMetadata

type RetryableFunc Uses

type RetryableFunc func(*http.Request, *http.Response, error) bool

type Route53Signer Uses

type Route53Signer struct {
    // contains filtered or unexported fields
}

func NewRoute53Signer Uses

func NewRoute53Signer(auth Auth) *Route53Signer

func (*Route53Signer) Sign Uses

func (s *Route53Signer) Sign(req *http.Request)

Adds all the required headers for AWS Route53 API to the request including the authorization

type Service Uses

type Service struct {
    // contains filtered or unexported fields
}

Implements a Server Query/Post API to easily query AWS services and build errors when desired

func NewService Uses

func NewService(auth Auth, service ServiceInfo) (s *Service, err error)

Create a new AWS server to handle making requests

func (*Service) BuildError Uses

func (s *Service) BuildError(r *http.Response) error

func (*Service) Query Uses

func (s *Service) Query(method, path string, params map[string]string) (resp *http.Response, err error)

type ServiceInfo Uses

type ServiceInfo struct {
    Endpoint string
    Signer   uint
}

Defines the service endpoint and correct Signer implementation to use to sign requests for this endpoint

type Signer Uses

type Signer interface {
    Sign(method, path string, params map[string]string)
}

Designates a signer interface suitable for signing AWS requests, params should be appropriately encoded for the request before signing.

A signer should be initialized with Auth and the appropriate endpoint.

type V2Signer Uses

type V2Signer struct {
    // contains filtered or unexported fields
}

func NewV2Signer Uses

func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error)

func (*V2Signer) Sign Uses

func (s *V2Signer) Sign(method, path string, params map[string]string)

type V4Signer Uses

type V4Signer struct {
    // contains filtered or unexported fields
}

The V4Signer encapsulates all of the functionality to sign a request with the AWS Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)

Code:

package main

import (
    "fmt"
    "net/http"
    "strings"
    "time"

    "github.com/goamz/goamz/aws"
    . "gopkg.in/check.v1"
)

var _ = Suite(&V4SignerSuite{})

type V4SignerSuite struct {
    auth   aws.Auth
    region aws.Region
    cases  []V4SignerSuiteCase
}

type V4SignerSuiteCase struct {
    label            string
    request          V4SignerSuiteCaseRequest
    canonicalRequest string
    stringToSign     string
    signature        string
    authorization    string
}

type V4SignerSuiteCaseRequest struct {
    method  string
    host    string
    url     string
    headers []string
    body    string
}

func (s *V4SignerSuite) SetUpSuite(c *C) {
    s.auth = aws.Auth{AccessKey: "AKIDEXAMPLE", SecretKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"}
    s.region = aws.USEast

    // Test cases from the Signature Version 4 Test Suite (http://goo.gl/nguvs0)
    s.cases = append(s.cases,

        // get-header-key-duplicate
        V4SignerSuiteCase{
            label: "get-header-key-duplicate",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "ZOO:zoobar", "zoo:foobar", "zoo:zoobar"},
            },
            canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:foobar,zoobar,zoobar\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n3c52f0eaae2b61329c0a332e3fa15842a37bc5812cf4d80eb64784308850e313",
            signature:        "54afcaaf45b331f81cd2edb974f7b824ff4dd594cbbaa945ed636b48477368ed",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=54afcaaf45b331f81cd2edb974f7b824ff4dd594cbbaa945ed636b48477368ed",
        },

        // get-header-value-order
        V4SignerSuiteCase{
            label: "get-header-value-order",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "p:z", "p:a", "p:p", "p:a"},
            },
            canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\np:a,a,p,z\n\ndate;host;p\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n94c0389fefe0988cbbedc8606f0ca0b485b48da010d09fc844b45b697c8924fe",
            signature:        "d2973954263943b11624a11d1c963ca81fb274169c7868b2858c04f083199e3d",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;p, Signature=d2973954263943b11624a11d1c963ca81fb274169c7868b2858c04f083199e3d",
        },

        // get-header-value-trim
        V4SignerSuiteCase{
            label: "get-header-value-trim",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "p: phfft "},
            },
            canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\np:phfft\n\ndate;host;p\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ndddd1902add08da1ac94782b05f9278c08dc7468db178a84f8950d93b30b1f35",
            signature:        "debf546796015d6f6ded8626f5ce98597c33b47b9164cf6b17b4642036fcb592",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;p, Signature=debf546796015d6f6ded8626f5ce98597c33b47b9164cf6b17b4642036fcb592",
        },

        // get-relative-relative
        V4SignerSuiteCase{
            label: "get-relative-relative",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/foo/bar/../..",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
            signature:        "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
        },

        // get-relative
        V4SignerSuiteCase{
            label: "get-relative",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/foo/..",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
            signature:        "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
        },

        // get-slash-dot-slash
        V4SignerSuiteCase{
            label: "get-slash-dot-slash",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/./",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
            signature:        "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
        },

        // get-slash-pointless-dot
        V4SignerSuiteCase{
            label: "get-slash-pointless-dot",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/./foo",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/foo\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n8021a97572ee460f87ca67f4e8c0db763216d84715f5424a843a5312a3321e2d",
            signature:        "910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a",
        },

        // get-slash
        V4SignerSuiteCase{
            label: "get-slash",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "//",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
            signature:        "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
        },

        // get-slashes
        V4SignerSuiteCase{
            label: "get-slashes",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "//foo//",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/foo/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n6bb4476ee8745730c9cb79f33a0c70baa6d8af29c0077fa12e4e8f1dd17e7098",
            signature:        "b00392262853cfe3201e47ccf945601079e9b8a7f51ee4c3d9ee4f187aa9bf19",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b00392262853cfe3201e47ccf945601079e9b8a7f51ee4c3d9ee4f187aa9bf19",
        },

        // get-space
        V4SignerSuiteCase{
            label: "get-space",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/%20/foo",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/%20/foo\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n69c45fb9fe3fd76442b5086e50b2e9fec8298358da957b293ef26e506fdfb54b",
            signature:        "f309cfbd10197a230c42dd17dbf5cca8a0722564cb40a872d25623cfa758e374",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=f309cfbd10197a230c42dd17dbf5cca8a0722564cb40a872d25623cfa758e374",
        },

        // get-unreserved
        V4SignerSuiteCase{
            label: "get-unreserved",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ndf63ee3247c0356c696a3b21f8d8490b01fa9cd5bc6550ef5ef5f4636b7b8901",
            signature:        "830cc36d03f0f84e6ee4953fbe701c1c8b71a0372c63af9255aa364dd183281e",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=830cc36d03f0f84e6ee4953fbe701c1c8b71a0372c63af9255aa364dd183281e",
        },

        // get-utf8
        V4SignerSuiteCase{
            label: "get-utf8",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/%E1%88%B4",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/%E1%88%B4\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n27ba31df5dbc6e063d8f87d62eb07143f7f271c5330a917840586ac1c85b6f6b",
            signature:        "8d6634c189aa8c75c2e51e106b6b5121bed103fdb351f7d7d4381c738823af74",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=8d6634c189aa8c75c2e51e106b6b5121bed103fdb351f7d7d4381c738823af74",
        },

        // get-vanilla-empty-query-key
        V4SignerSuiteCase{
            label: "get-vanilla-empty-query-key",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/?foo=bar",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n0846c2945b0832deb7a463c66af5c4f8bd54ec28c438e67a214445b157c9ddf8",
            signature:        "56c054473fd260c13e4e7393eb203662195f5d4a1fada5314b8b52b23f985e9f",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=56c054473fd260c13e4e7393eb203662195f5d4a1fada5314b8b52b23f985e9f",
        },

        // get-vanilla-space-query-parameters
        V4SignerSuiteCase{
            label: "get-vanilla-space-query-parameters",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/?foo foo=bar bar",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\nfoo%20foo=bar%20bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n6a81658ae0a0a4f73aa72ca7d3b01c9cb0c5d4099f7a5ee897f5a571bfe6f7ff",
            signature:        "c8556bc676129d0806ea8fe6ef182dc095666f4c1582c3d9751d47e4306037c9",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=c8556bc676129d0806ea8fe6ef182dc095666f4c1582c3d9751d47e4306037c9",
        },

        // get-vanilla-query-order-key-case
        V4SignerSuiteCase{
            label: "get-vanilla-query-order-key-case",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/?foo=Zoo&foo=aha",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\nfoo=Zoo&foo=aha\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ne25f777ba161a0f1baf778a87faf057187cf5987f17953320e3ca399feb5f00d",
            signature:        "be7148d34ebccdc6423b19085378aa0bee970bdc61d144bd1a8c48c33079ab09",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=be7148d34ebccdc6423b19085378aa0bee970bdc61d144bd1a8c48c33079ab09",
        },

        // get-vanilla-query-order-key
        V4SignerSuiteCase{
            label: "get-vanilla-query-order-key",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/?a=foo&b=foo",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\na=foo&b=foo\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n2f23d14fe13caebf6dfda346285c6d9c14f49eaca8f5ec55c627dd7404f7a727",
            signature:        "0dc122f3b28b831ab48ba65cb47300de53fbe91b577fe113edac383730254a3b",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=0dc122f3b28b831ab48ba65cb47300de53fbe91b577fe113edac383730254a3b",
        },

        // get-vanilla-query-order-value
        V4SignerSuiteCase{
            label: "get-vanilla-query-order-value",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/?foo=b&foo=a",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\nfoo=a&foo=b\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n33dffc220e89131f8f6157a35c40903daa658608d9129ff9489e5cf5bbd9b11b",
            signature:        "feb926e49e382bec75c9d7dcb2a1b6dc8aa50ca43c25d2bc51143768c0875acc",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=feb926e49e382bec75c9d7dcb2a1b6dc8aa50ca43c25d2bc51143768c0875acc",
        },

        // get-vanilla-query-unreserved
        V4SignerSuiteCase{
            label: "get-vanilla-query-unreserved",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/?-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nd2578f3156d4c9d180713d1ff20601d8a3eed0dd35447d24603d7d67414bd6b5",
            signature:        "f1498ddb4d6dae767d97c466fb92f1b59a2c71ca29ac954692663f9db03426fb",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=f1498ddb4d6dae767d97c466fb92f1b59a2c71ca29ac954692663f9db03426fb",
        },

        // get-vanilla-query
        V4SignerSuiteCase{
            label: "get-vanilla-query",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
            signature:        "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
        },

        // get-vanilla-ut8-query
        V4SignerSuiteCase{
            label: "get-vanilla-ut8-query",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/?ሴ=bar",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n%E1%88%B4=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nde5065ff39c131e6c2e2bd19cd9345a794bf3b561eab20b8d97b2093fc2a979e",
            signature:        "6fb359e9a05394cc7074e0feb42573a2601abc0c869a953e8c5c12e4e01f1a8c",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=6fb359e9a05394cc7074e0feb42573a2601abc0c869a953e8c5c12e4e01f1a8c",
        },

        // get-vanilla
        V4SignerSuiteCase{
            label: "get-vanilla",
            request: V4SignerSuiteCaseRequest{
                method:  "GET",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
            signature:        "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
        },

        // post-header-key-case
        V4SignerSuiteCase{
            label: "post-header-key-case",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n05da62cee468d24ae84faff3c39f1b85540de60243c1bcaace39c0a2acc7b2c4",
            signature:        "22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
        },

        // post-header-key-sort
        V4SignerSuiteCase{
            label: "post-header-key-sort",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "ZOO:zoobar"},
            },
            canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:zoobar\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n34e1bddeb99e76ee01d63b5e28656111e210529efeec6cdfd46a48e4c734545d",
            signature:        "b7a95a52518abbca0964a999a880429ab734f35ebbf1235bd79a5de87756dc4a",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=b7a95a52518abbca0964a999a880429ab734f35ebbf1235bd79a5de87756dc4a",
        },

        // post-header-value-case
        V4SignerSuiteCase{
            label: "post-header-value-case",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "zoo:ZOOBAR"},
            },
            canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:ZOOBAR\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n3aae6d8274b8c03e2cc96fc7d6bda4b9bd7a0a184309344470b2c96953e124aa",
            signature:        "273313af9d0c265c531e11db70bbd653f3ba074c1009239e8559d3987039cad7",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=273313af9d0c265c531e11db70bbd653f3ba074c1009239e8559d3987039cad7",
        },

        // post-vanilla-empty-query-value
        V4SignerSuiteCase{
            label: "post-vanilla-empty-query-value",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/?foo=bar",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "POST\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ncd4f39132d8e60bb388831d734230460872b564871c47f5de62e62d1a68dbe1e",
            signature:        "b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
        },

        // post-vanilla-query
        V4SignerSuiteCase{
            label: "post-vanilla-query",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/?foo=bar",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "POST\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ncd4f39132d8e60bb388831d734230460872b564871c47f5de62e62d1a68dbe1e",
            signature:        "b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
        },

        // post-vanilla
        V4SignerSuiteCase{
            label: "post-vanilla",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
            },
            canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n05da62cee468d24ae84faff3c39f1b85540de60243c1bcaace39c0a2acc7b2c4",
            signature:        "22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
        },

        // post-x-www-form-urlencoded-parameters
        V4SignerSuiteCase{
            label: "post-x-www-form-urlencoded-parameters",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"Content-Type:application/x-www-form-urlencoded; charset=utf8", "Date:Mon, 09 Sep 2011 23:36:00 GMT"},
                body:    "foo=bar",
            },
            canonicalRequest: "POST\n/\n\ncontent-type:application/x-www-form-urlencoded; charset=utf8\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ncontent-type;date;host\n3ba8907e7a252327488df390ed517c45b96dead033600219bdca7107d1d3f88a",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nc4115f9e54b5cecf192b1eaa23b8e88ed8dc5391bd4fde7b3fff3d9c9fe0af1f",
            signature:        "b105eb10c6d318d2294de9d49dd8b031b55e3c3fe139f2e637da70511e9e7b71",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=content-type;date;host, Signature=b105eb10c6d318d2294de9d49dd8b031b55e3c3fe139f2e637da70511e9e7b71",
        },

        // post-x-www-form-urlencoded
        V4SignerSuiteCase{
            label: "post-x-www-form-urlencoded",
            request: V4SignerSuiteCaseRequest{
                method:  "POST",
                host:    "host.foo.com",
                url:     "/",
                headers: []string{"Content-Type:application/x-www-form-urlencoded", "Date:Mon, 09 Sep 2011 23:36:00 GMT"},
                body:    "foo=bar",
            },
            canonicalRequest: "POST\n/\n\ncontent-type:application/x-www-form-urlencoded\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ncontent-type;date;host\n3ba8907e7a252327488df390ed517c45b96dead033600219bdca7107d1d3f88a",
            stringToSign:     "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n4c5c6e4b52fb5fb947a8733982a8a5a61b14f04345cbfe6e739236c76dd48f74",
            signature:        "5a15b22cf462f047318703b92e6f4f38884e4a7ab7b1d6426ca46a8bd1c26cbc",
            authorization:    "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=content-type;date;host, Signature=5a15b22cf462f047318703b92e6f4f38884e4a7ab7b1d6426ca46a8bd1c26cbc",
        },
    )
}

func (s *V4SignerSuite) TestCases(c *C) {
    signer := aws.NewV4Signer(s.auth, "host", s.region)

    for _, testCase := range s.cases {

        req, err := http.NewRequest(testCase.request.method, "http://"+testCase.request.host+testCase.request.url, strings.NewReader(testCase.request.body))
        c.Assert(err, IsNil, Commentf("Testcase: %s", testCase.label))
        for _, v := range testCase.request.headers {
            h := strings.SplitN(v, ":", 2)
            req.Header.Add(h[0], h[1])
        }
        req.Header.Set("host", req.Host)

        t := signer.RequestTime(req)

        canonicalRequest := signer.CanonicalRequest(req)
        c.Check(canonicalRequest, Equals, testCase.canonicalRequest, Commentf("Testcase: %s", testCase.label))

        stringToSign := signer.StringToSign(t, canonicalRequest)
        c.Check(stringToSign, Equals, testCase.stringToSign, Commentf("Testcase: %s", testCase.label))

        signature := signer.Signature(t, stringToSign)
        c.Check(signature, Equals, testCase.signature, Commentf("Testcase: %s", testCase.label))

        authorization := signer.Authorization(req.Header, t, signature)
        c.Check(authorization, Equals, testCase.authorization, Commentf("Testcase: %s", testCase.label))

        signer.Sign(req)
        c.Check(req.Header.Get("Authorization"), Equals, testCase.authorization, Commentf("Testcase: %s", testCase.label))
    }
}

func main() {
    // Get auth from env vars
    auth, err := aws.EnvAuth()
    if err != nil {
        fmt.Println(err)
    }

    // Create a signer with the auth, name of the service, and aws region
    signer := aws.NewV4Signer(auth, "dynamodb", aws.USEast)

    // Create a request
    req, err := http.NewRequest("POST", aws.USEast.DynamoDBEndpoint, strings.NewReader("sample_request"))
    if err != nil {
        fmt.Println(err)
    }

    // Date or x-amz-date header is required to sign a request
    req.Header.Add("Date", time.Now().UTC().Format(http.TimeFormat))

    // Sign the request
    signer.Sign(req)

    // Issue signed request
    http.DefaultClient.Do(req)
}

func NewV4Signer Uses

func NewV4Signer(auth Auth, serviceName string, region Region) *V4Signer

Return a new instance of a V4Signer capable of signing AWS requests.

func (*V4Signer) Sign Uses

func (s *V4Signer) Sign(req *http.Request)

Sign a request according to the AWS Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)

The signed request will include an "x-amz-date" header with a current timestamp if a valid "x-amz-date" or "date" header was not available in the original request. In addition, AWS Signature Version 4 requires the "host" header to be a signed header, therefor the Sign method will manually set a "host" header from the request.Host.

The signed request will include a new "Authorization" header indicating that the request has been signed.

Any changes to the request after signing the request will invalidate the signature.

type WaitFunc Uses

type WaitFunc func(try int)

Package aws imports 19 packages (graph) and is imported by 883 packages. Updated 2019-06-23. Refresh now. Tools for package owners.