func (s *V4Signer) authorization(header http.Header, t time.Time, signature, accessKey string) string {
	w := new(bytes.Buffer)
	fmt.Fprint(w, "AWS4-HMAC-SHA256 ")
	fmt.Fprintf(w, "Credential=%s/%s, ", accessKey, s.credentialScope(t))
	fmt.Fprintf(w, "SignedHeaders=%s, ", s.signedHeaders(header))
	fmt.Fprintf(w, "Signature=%s", signature)
	return w.String()
}
/*
authorization method generates the authorization header value.
package aws
import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"path"
	"sort"
	"strings"
	"time"
)
type V2Signer struct {
	auth    *Auth
	service ServiceInfo
	host    string
}
var b64 = base64.StdEncoding
func NewV2Signer(auth *Auth, service ServiceInfo) (*V2Signer, error) {
	u, err := url.Parse(service.Endpoint)
	if err != nil {
		return nil, err
	}
	return &V2Signer{auth: auth, service: service, host: u.Host}, nil
}
func (s *V2Signer) Sign(method, path string, params map[string]string) {
	accessKey, secretKey, token := s.auth.Credentials()
	params["AWSAccessKeyId"] = accessKey
	params["SignatureVersion"] = "2"
	params["SignatureMethod"] = "HmacSHA256"
	if token != "" {
		params["SecurityToken"] = token
	}
	var keys, sarray []string
	for k, _ := range params {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		sarray = append(sarray, Encode(k)+"="+Encode(params[k]))
	}
	joined := strings.Join(sarray, "&")
	payload := method + "\n" + s.host + "\n" + path + "\n" + joined
	hash := hmac.New(sha256.New, []byte(secretKey))
	hash.Write([]byte(payload))
	signature := make([]byte, b64.EncodedLen(hash.Size()))
	b64.Encode(signature, hash.Sum(nil))
	params["Signature"] = string(signature)
}
const (
	ISO8601BasicFormat      = "20060102T150405Z"
	ISO8601BasicFormatShort = "20060102"
)
type Route53Signer struct {
	auth *Auth
}
func NewRoute53Signer(auth *Auth) *Route53Signer {
	return &Route53Signer{auth: auth}
}
func (s *Route53Signer) getCurrentDate() string {
	response, err := http.Get("https://route53.amazonaws.com/date")
	if err != nil {
		fmt.Print("Unable to get date from amazon: ", err)
		return ""
	}
	response.Body.Close()
	return response.Header.Get("Date")
}
func (s *Route53Signer) getHeaderAuthorize(message, secretKey string) string {
	hmacSha256 := hmac.New(sha256.New, []byte(secretKey))
	hmacSha256.Write([]byte(message))
	cryptedString := hmacSha256.Sum(nil)
	return base64.StdEncoding.EncodeToString(cryptedString)
}
func (s *Route53Signer) Sign(req *http.Request) {
	accessKey, secretKey, _ := s.auth.Credentials()
	date := s.getCurrentDate()
	authHeader := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=%s,Signature=%s",
		accessKey, "HmacSHA256", s.getHeaderAuthorize(date, secretKey))
	req.Header.Set("Host", req.Host)
	req.Header.Set("X-Amzn-Authorization", authHeader)
	req.Header.Set("X-Amz-Date", date)
	req.Header.Set("Content-Type", "application/xml")
}
type V4Signer struct {
	auth        *Auth
	serviceName string
	region      Region
}
func NewV4Signer(auth *Auth, serviceName string, region Region) *V4Signer {
	return &V4Signer{auth: auth, serviceName: serviceName, region: region}
}
func (s *V4Signer) Sign(req *http.Request) {
	accessKey, secretKey, token := s.auth.Credentials()
	if token != "" {
		req.Header.Set("X-Amz-Security-Token", token)
	}
	req.Header.Set("host", req.Host)                              
	t := s.requestTime(req)                                       
	creq := s.canonicalRequest(req)                               
	sts := s.stringToSign(t, creq)                                
	signature := s.signature(t, sts, secretKey)                   
	auth := s.authorization(req.Header, t, signature, accessKey)  
	req.Header.Set("Authorization", auth)                         
}
func (s *V4Signer) requestTime(req *http.Request) time.Time {
	date := req.Header.Get("x-amz-date")
	t, err := time.Parse(ISO8601BasicFormat, date)
	if err == nil {
		return t
	}
	t, err = time.Parse(http.TimeFormat, date)
	if err == nil {
		req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
		return t
	}
	date = req.Header.Get("date")
	t, err = time.Parse(http.TimeFormat, date)
	if err == nil {
		return t
	}
	t = time.Now().UTC()
	req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
	return t
}
func (s *V4Signer) canonicalRequest(req *http.Request) string {
	c := new(bytes.Buffer)
	fmt.Fprintf(c, "%s\n", req.Method)
	fmt.Fprintf(c, "%s\n", s.canonicalURI(req.URL))
	fmt.Fprintf(c, "%s\n", s.canonicalQueryString(req.URL))
	fmt.Fprintf(c, "%s\n\n", s.canonicalHeaders(req.Header))
	fmt.Fprintf(c, "%s\n", s.signedHeaders(req.Header))
	fmt.Fprintf(c, "%s", s.payloadHash(req))
	return c.String()
}
func (s *V4Signer) canonicalURI(u *url.URL) string {
	canonicalPath := u.RequestURI()
	if u.RawQuery != "" {
		canonicalPath = canonicalPath[:len(canonicalPath)-len(u.RawQuery)-1]
	}
	slash := strings.HasSuffix(canonicalPath, "/")
	canonicalPath = path.Clean(canonicalPath)
	if canonicalPath != "/" && slash {
		canonicalPath += "/"
	}
	return canonicalPath
}
func (s *V4Signer) canonicalQueryString(u *url.URL) string {
	var a []string
	for k, vs := range u.Query() {
		k = url.QueryEscape(k)
		for _, v := range vs {
			if v == "" {
				a = append(a, k+"=")
			} else {
				v = url.QueryEscape(v)
				a = append(a, k+"="+v)
			}
		}
	}
	sort.Strings(a)
	return strings.Join(a, "&")
}
func (s *V4Signer) canonicalHeaders(h http.Header) string {
	i, a := 0, make([]string, len(h))
	for k, v := range h {
		for j, w := range v {
			v[j] = strings.Trim(w, " ")
		}
		sort.Strings(v)
		a[i] = strings.ToLower(k) + ":" + strings.Join(v, ",")
		i++
	}
	sort.Strings(a)
	return strings.Join(a, "\n")
}
func (s *V4Signer) signedHeaders(h http.Header) string {
	i, a := 0, make([]string, len(h))
	for k, _ := range h {
		a[i] = strings.ToLower(k)
		i++
	}
	sort.Strings(a)
	return strings.Join(a, ";")
}
func (s *V4Signer) payloadHash(req *http.Request) string {
	var b []byte
	if req.Body == nil {
		b = []byte("")
	} else {
		var err error
		b, err = ioutil.ReadAll(req.Body)
		if err != nil {
			panic(err)
		}
	}
	req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
	return s.hash(string(b))
}
func (s *V4Signer) stringToSign(t time.Time, creq string) string {
	w := new(bytes.Buffer)
	fmt.Fprint(w, "AWS4-HMAC-SHA256\n")
	fmt.Fprintf(w, "%s\n", t.Format(ISO8601BasicFormat))
	fmt.Fprintf(w, "%s\n", s.credentialScope(t))
	fmt.Fprintf(w, "%s", s.hash(creq))
	return w.String()
}
func (s *V4Signer) credentialScope(t time.Time) string {
	return fmt.Sprintf("%s/%s/%s/aws4_request", t.Format(ISO8601BasicFormatShort), s.region.Name, s.serviceName)
}
func (s *V4Signer) signature(t time.Time, sts, secretKey string) string {
	h := s.hmac(s.derivedKey(t, secretKey), []byte(sts))
	return fmt.Sprintf("%x", h)
}
func (s *V4Signer) derivedKey(t time.Time, secretKey string) []byte {
	h := s.hmac([]byte("AWS4"+secretKey), []byte(t.Format(ISO8601BasicFormatShort)))
	h = s.hmac(h, []byte(s.region.Name))
	h = s.hmac(h, []byte(s.serviceName))
	h = s.hmac(h, []byte("aws4_request"))
	return h
}