Этот коммит содержится в:
=Corey Hulen
2015-06-14 23:53:32 -08:00
Коммит 56e74239d6
646 изменённых файлов: 127767 добавлений и 0 удалений

24
Godeps/_workspace/src/github.com/anachronistic/apns/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.pem

21
Godeps/_workspace/src/github.com/anachronistic/apns/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013 Alan Harris
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

167
Godeps/_workspace/src/github.com/anachronistic/apns/client.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,167 @@
package apns
import (
"crypto/tls"
"errors"
"net"
"strings"
"time"
)
var _ APNSClient = &Client{}
// APNSClient is an APNS client.
type APNSClient interface {
ConnectAndWrite(resp *PushNotificationResponse, payload []byte) (err error)
Send(pn *PushNotification) (resp *PushNotificationResponse)
}
// Client contains the fields necessary to communicate
// with Apple, such as the gateway to use and your
// certificate contents.
//
// You'll need to provide your own CertificateFile
// and KeyFile to send notifications. Ideally, you'll
// just set the CertificateFile and KeyFile fields to
// a location on drive where the certs can be loaded,
// but if you prefer you can use the CertificateBase64
// and KeyBase64 fields to store the actual contents.
type Client struct {
Gateway string
CertificateFile string
CertificateBase64 string
KeyFile string
KeyBase64 string
}
// BareClient can be used to set the contents of your
// certificate and key blocks manually.
func BareClient(gateway, certificateBase64, keyBase64 string) (c *Client) {
c = new(Client)
c.Gateway = gateway
c.CertificateBase64 = certificateBase64
c.KeyBase64 = keyBase64
return
}
// NewClient assumes you'll be passing in paths that
// point to your certificate and key.
func NewClient(gateway, certificateFile, keyFile string) (c *Client) {
c = new(Client)
c.Gateway = gateway
c.CertificateFile = certificateFile
c.KeyFile = keyFile
return
}
// Send connects to the APN service and sends your push notification.
// Remember that if the submission is successful, Apple won't reply.
func (client *Client) Send(pn *PushNotification) (resp *PushNotificationResponse) {
resp = new(PushNotificationResponse)
payload, err := pn.ToBytes()
if err != nil {
resp.Success = false
resp.Error = err
return
}
err = client.ConnectAndWrite(resp, payload)
if err != nil {
resp.Success = false
resp.Error = err
return
}
resp.Success = true
resp.Error = nil
return
}
// ConnectAndWrite establishes the connection to Apple and handles the
// transmission of your push notification, as well as waiting for a reply.
//
// In lieu of a timeout (which would be available in Go 1.1)
// we use a timeout channel pattern instead. We start two goroutines,
// one of which just sleeps for TimeoutSeconds seconds, while the other
// waits for a response from the Apple servers.
//
// Whichever channel puts data on first is the "winner". As such, it's
// possible to get a false positive if Apple takes a long time to respond.
// It's probably not a deal-breaker, but something to be aware of.
func (client *Client) ConnectAndWrite(resp *PushNotificationResponse, payload []byte) (err error) {
var cert tls.Certificate
if len(client.CertificateBase64) == 0 && len(client.KeyBase64) == 0 {
// The user did not specify raw block contents, so check the filesystem.
cert, err = tls.LoadX509KeyPair(client.CertificateFile, client.KeyFile)
} else {
// The user provided the raw block contents, so use that.
cert, err = tls.X509KeyPair([]byte(client.CertificateBase64), []byte(client.KeyBase64))
}
if err != nil {
return err
}
gatewayParts := strings.Split(client.Gateway, ":")
conf := &tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: gatewayParts[0],
}
conn, err := net.Dial("tcp", client.Gateway)
if err != nil {
return err
}
defer conn.Close()
tlsConn := tls.Client(conn, conf)
err = tlsConn.Handshake()
if err != nil {
return err
}
defer tlsConn.Close()
_, err = tlsConn.Write(payload)
if err != nil {
return err
}
// Create one channel that will serve to handle
// timeouts when the notification succeeds.
timeoutChannel := make(chan bool, 1)
go func() {
time.Sleep(time.Second * TimeoutSeconds)
timeoutChannel <- true
}()
// This channel will contain the binary response
// from Apple in the event of a failure.
responseChannel := make(chan []byte, 1)
go func() {
buffer := make([]byte, 6, 6)
tlsConn.Read(buffer)
responseChannel <- buffer
}()
// First one back wins!
// The data structure for an APN response is as follows:
//
// command -> 1 byte
// status -> 1 byte
// identifier -> 4 bytes
//
// The first byte will always be set to 8.
select {
case r := <-responseChannel:
resp.Success = false
resp.AppleResponse = ApplePushResponses[r[1]]
err = errors.New(resp.AppleResponse)
case <-timeoutChannel:
resp.Success = true
}
return err
}

21
Godeps/_workspace/src/github.com/anachronistic/apns/client_mock.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
package apns
import "github.com/stretchr/testify/mock"
type MockClient struct {
mock.Mock
}
func (m *MockClient) ConnectAndWrite(resp *PushNotificationResponse, payload []byte) (err error) {
return m.Called(resp, payload).Error(0)
}
func (m *MockClient) Send(pn *PushNotification) (resp *PushNotificationResponse) {
r := m.Called(pn).Get(0)
if r != nil {
if r, ok := r.(*PushNotificationResponse); ok {
return r
}
}
return nil
}

24
Godeps/_workspace/src/github.com/anachronistic/apns/client_mock_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,24 @@
package apns
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
)
func TestMockClientConnectAndWrite(t *testing.T) {
m := &MockClient{}
m.On("ConnectAndWrite", (*PushNotificationResponse)(nil), []byte(nil)).Return(nil)
assert.Nil(t, m.ConnectAndWrite(nil, nil))
m.On("ConnectAndWrite", &PushNotificationResponse{}, []byte{}).Return(errors.New("test"))
assert.Equal(t, errors.New("test"), m.ConnectAndWrite(&PushNotificationResponse{}, []byte{}))
}
func TestMockClientSend(t *testing.T) {
m := &MockClient{}
m.On("Send", (*PushNotification)(nil)).Return(nil)
assert.Nil(t, m.Send(nil))
m.On("Send", &PushNotification{}).Return(&PushNotificationResponse{})
assert.Equal(t, &PushNotificationResponse{}, m.Send(&PushNotification{}))
}

102
Godeps/_workspace/src/github.com/anachronistic/apns/feedback.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,102 @@
package apns
import (
"bytes"
"crypto/tls"
"encoding/binary"
"encoding/hex"
"errors"
"net"
"strings"
"time"
)
// Wait at most this many seconds for feedback data from Apple.
const FeedbackTimeoutSeconds = 5
// FeedbackChannel will receive individual responses from Apple.
var FeedbackChannel = make(chan (*FeedbackResponse))
// If there's nothing to read, ShutdownChannel gets a true.
var ShutdownChannel = make(chan bool)
// FeedbackResponse represents a device token that Apple has
// indicated should not be sent to in the future.
type FeedbackResponse struct {
Timestamp uint32
DeviceToken string
}
// NewFeedbackResponse creates and returns a FeedbackResponse structure.
func NewFeedbackResponse() (resp *FeedbackResponse) {
resp = new(FeedbackResponse)
return
}
// ListenForFeedback connects to the Apple Feedback Service
// and checks for device tokens.
//
// Feedback consists of device tokens that should
// not be sent to in the future; Apple *does* monitor that
// you respect this so you should be checking it ;)
func (client *Client) ListenForFeedback() (err error) {
var cert tls.Certificate
if len(client.CertificateBase64) == 0 && len(client.KeyBase64) == 0 {
// The user did not specify raw block contents, so check the filesystem.
cert, err = tls.LoadX509KeyPair(client.CertificateFile, client.KeyFile)
} else {
// The user provided the raw block contents, so use that.
cert, err = tls.X509KeyPair([]byte(client.CertificateBase64), []byte(client.KeyBase64))
}
if err != nil {
return err
}
gatewayParts := strings.Split(client.Gateway, ":")
conf := &tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: gatewayParts[0],
}
conn, err := net.Dial("tcp", client.Gateway)
if err != nil {
return err
}
defer conn.Close()
conn.SetReadDeadline(time.Now().Add(FeedbackTimeoutSeconds * time.Second))
tlsConn := tls.Client(conn, conf)
err = tlsConn.Handshake()
if err != nil {
return err
}
var tokenLength uint16
buffer := make([]byte, 38, 38)
deviceToken := make([]byte, 32, 32)
for {
_, err := tlsConn.Read(buffer)
if err != nil {
ShutdownChannel <- true
break
}
resp := NewFeedbackResponse()
r := bytes.NewReader(buffer)
binary.Read(r, binary.BigEndian, &resp.Timestamp)
binary.Read(r, binary.BigEndian, &tokenLength)
binary.Read(r, binary.BigEndian, &deviceToken)
if tokenLength != 32 {
return errors.New("token length should be equal to 32, but isn't")
}
resp.DeviceToken = hex.EncodeToString(deviceToken)
FeedbackChannel <- resp
}
return nil
}

15
Godeps/_workspace/src/github.com/anachronistic/apns/legacy.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
package apns
// This file exists to support backward-compatibility
// as I gradually refactor and overhaul. Ideally, golint
// should only complain about this file (and we should
// try to keep its complaints to a minimum).
// These variables map old identifiers to their current format.
var (
APPLE_PUSH_RESPONSES = ApplePushResponses
FEEDBACK_TIMEOUT_SECONDS = FeedbackTimeoutSeconds
IDENTIFIER_UBOUND = IdentifierUbound
MAX_PAYLOAD_SIZE_BYTES = MaxPayloadSizeBytes
TIMEOUT_SECONDS = TimeoutSeconds
)

27
Godeps/_workspace/src/github.com/anachronistic/apns/legacy_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,27 @@
package apns
import (
"reflect"
"testing"
)
// These identifiers were changed to resolve golint violations.
// However, it's possible that legacy code may rely on them. This
// will help avoid springing a breaking change on people.
func TestLegacyConstants(t *testing.T) {
if !reflect.DeepEqual(APPLE_PUSH_RESPONSES, ApplePushResponses) {
t.Error("expected APPLE_PUSH_RESPONSES to equal ApplePushResponses")
}
if !reflect.DeepEqual(FEEDBACK_TIMEOUT_SECONDS, FeedbackTimeoutSeconds) {
t.Error("expected FEEDBACK_TIMEOUT_SECONDS to equal FeedbackTimeoutSeconds")
}
if !reflect.DeepEqual(IDENTIFIER_UBOUND, IdentifierUbound) {
t.Error("expected IDENTIFIER_UBOUND to equal IdentifierUbound")
}
if !reflect.DeepEqual(MAX_PAYLOAD_SIZE_BYTES, MaxPayloadSizeBytes) {
t.Error("expected MAX_PAYLOAD_SIZE_BYTES to equal MaxPayloadSizeBytes")
}
if !reflect.DeepEqual(TIMEOUT_SECONDS, TimeoutSeconds) {
t.Error("expected TIMEOUT_SECONDS to equal TimeoutSeconds")
}
}

53
Godeps/_workspace/src/github.com/anachronistic/apns/mock_feedback_server.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,53 @@
package apns
import (
"bytes"
"crypto/tls"
"encoding/binary"
"log"
"net"
"time"
)
// StartMockFeedbackServer spins up a simple stand-in for the Apple
// feedback service that can be used for testing purposes. Doesn't
// handle many errors, etc. Just for the sake of having something "live"
// to hit.
func StartMockFeedbackServer(certFile, keyFile string) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
log.Panic(err)
}
config := tls.Config{Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAnyClientCert}
log.Print("- starting Mock Apple Feedback TCP server at 0.0.0.0:5555")
srv, _ := tls.Listen("tcp", "0.0.0.0:5555", &config)
for {
conn, err := srv.Accept()
if err != nil {
log.Panic(err)
}
go loop(conn)
}
}
// Writes binary data to the client in the same
// manner as the Apple service would.
//
// [4 bytes, 2 bytes, 32 bytes] = 38 bytes total
func loop(conn net.Conn) {
defer conn.Close()
for {
timeT := uint32(1368809290) // 2013-05-17 12:48:10 -0400
token := "abcd1234efab5678abcd1234efab5678"
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, timeT)
binary.Write(buf, binary.BigEndian, uint16(len(token)))
binary.Write(buf, binary.BigEndian, []byte(token))
conn.Write(buf.Bytes())
dur, _ := time.ParseDuration("1s")
time.Sleep(dur)
}
}

175
Godeps/_workspace/src/github.com/anachronistic/apns/push_notification.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,175 @@
package apns
import (
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"math/rand"
"strconv"
"time"
)
// Push commands always start with command value 2.
const pushCommandValue = 2
// Your total notification payload cannot exceed 2 KB.
const MaxPayloadSizeBytes = 2048
// Every push notification gets a pseudo-unique identifier;
// this establishes the upper boundary for it. Apple will return
// this identifier if there is an issue sending your notification.
const IdentifierUbound = 9999
// Constants related to the payload fields and their lengths.
const (
deviceTokenItemid = 1
payloadItemid = 2
notificationIdentifierItemid = 3
expirationDateItemid = 4
priorityItemid = 5
deviceTokenLength = 32
notificationIdentifierLength = 4
expirationDateLength = 4
priorityLength = 1
)
// Payload contains the notification data for your request.
//
// Alert is an interface here because it supports either a string
// or a dictionary, represented within by an AlertDictionary struct.
type Payload struct {
Alert interface{} `json:"alert,omitempty"`
Badge int `json:"badge,omitempty"`
Sound string `json:"sound,omitempty"`
ContentAvailable int `json:"content-available,omitempty"`
Category string `json:"category,omitempty"`
}
// NewPayload creates and returns a Payload structure.
func NewPayload() *Payload {
return new(Payload)
}
// AlertDictionary is a more complex notification payload.
//
// From the APN docs: "Use the ... alert dictionary in general only if you absolutely need to."
// The AlertDictionary is suitable for specific localization needs.
type AlertDictionary struct {
Body string `json:"body,omitempty"`
ActionLocKey string `json:"action-loc-key,omitempty"`
LocKey string `json:"loc-key,omitempty"`
LocArgs []string `json:"loc-args,omitempty"`
LaunchImage string `json:"launch-image,omitempty"`
}
// NewAlertDictionary creates and returns an AlertDictionary structure.
func NewAlertDictionary() *AlertDictionary {
return new(AlertDictionary)
}
// PushNotification is the wrapper for the Payload.
// The length fields are computed in ToBytes() and aren't represented here.
type PushNotification struct {
Identifier int32
Expiry uint32
DeviceToken string
payload map[string]interface{}
Priority uint8
}
// NewPushNotification creates and returns a PushNotification structure.
// It also initializes the pseudo-random identifier.
func NewPushNotification() (pn *PushNotification) {
pn = new(PushNotification)
pn.payload = make(map[string]interface{})
pn.Identifier = rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(IdentifierUbound)
pn.Priority = 10
return
}
// AddPayload sets the "aps" payload section of the request. It also
// has a hack described within to deal with specific zero values.
func (pn *PushNotification) AddPayload(p *Payload) {
// This deserves some explanation.
//
// Setting an exported field of type int to 0
// triggers the omitempty behavior if you've set it.
// Since the badge is optional, we should omit it if
// it's not set. However, we want to include it if the
// value is 0, so there's a hack in push_notification.go
// that exploits the fact that Apple treats -1 for a
// badge value as though it were 0 (i.e. it clears the
// badge but doesn't stop the notification from going
// through successfully.)
//
// Still a hack though :)
if p.Badge == 0 {
p.Badge = -1
}
pn.Set("aps", p)
}
// Get returns the value of a payload key, if it exists.
func (pn *PushNotification) Get(key string) interface{} {
return pn.payload[key]
}
// Set defines the value of a payload key.
func (pn *PushNotification) Set(key string, value interface{}) {
pn.payload[key] = value
}
// PayloadJSON returns the current payload in JSON format.
func (pn *PushNotification) PayloadJSON() ([]byte, error) {
return json.Marshal(pn.payload)
}
// PayloadString returns the current payload in string format.
func (pn *PushNotification) PayloadString() (string, error) {
j, err := pn.PayloadJSON()
return string(j), err
}
// ToBytes returns a byte array of the complete PushNotification
// struct. This array is what should be transmitted to the APN Service.
func (pn *PushNotification) ToBytes() ([]byte, error) {
token, err := hex.DecodeString(pn.DeviceToken)
if err != nil {
return nil, err
}
if len(token) != deviceTokenLength {
return nil, errors.New("device token has incorrect length")
}
payload, err := pn.PayloadJSON()
if err != nil {
return nil, err
}
if len(payload) > MaxPayloadSizeBytes {
return nil, errors.New("payload is larger than the " + strconv.Itoa(MaxPayloadSizeBytes) + " byte limit")
}
frameBuffer := new(bytes.Buffer)
binary.Write(frameBuffer, binary.BigEndian, uint8(deviceTokenItemid))
binary.Write(frameBuffer, binary.BigEndian, uint16(deviceTokenLength))
binary.Write(frameBuffer, binary.BigEndian, token)
binary.Write(frameBuffer, binary.BigEndian, uint8(payloadItemid))
binary.Write(frameBuffer, binary.BigEndian, uint16(len(payload)))
binary.Write(frameBuffer, binary.BigEndian, payload)
binary.Write(frameBuffer, binary.BigEndian, uint8(notificationIdentifierItemid))
binary.Write(frameBuffer, binary.BigEndian, uint16(notificationIdentifierLength))
binary.Write(frameBuffer, binary.BigEndian, pn.Identifier)
binary.Write(frameBuffer, binary.BigEndian, uint8(expirationDateItemid))
binary.Write(frameBuffer, binary.BigEndian, uint16(expirationDateLength))
binary.Write(frameBuffer, binary.BigEndian, pn.Expiry)
binary.Write(frameBuffer, binary.BigEndian, uint8(priorityItemid))
binary.Write(frameBuffer, binary.BigEndian, uint16(priorityLength))
binary.Write(frameBuffer, binary.BigEndian, pn.Priority)
buffer := bytes.NewBuffer([]byte{})
binary.Write(buffer, binary.BigEndian, uint8(pushCommandValue))
binary.Write(buffer, binary.BigEndian, uint32(frameBuffer.Len()))
binary.Write(buffer, binary.BigEndian, frameBuffer.Bytes())
return buffer.Bytes(), nil
}

36
Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_response.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,36 @@
package apns
// The maximum number of seconds we're willing to wait for a response
// from the Apple Push Notification Service.
const TimeoutSeconds = 5
// This enumerates the response codes that Apple defines
// for push notification attempts.
var ApplePushResponses = map[uint8]string{
0: "NO_ERRORS",
1: "PROCESSING_ERROR",
2: "MISSING_DEVICE_TOKEN",
3: "MISSING_TOPIC",
4: "MISSING_PAYLOAD",
5: "INVALID_TOKEN_SIZE",
6: "INVALID_TOPIC_SIZE",
7: "INVALID_PAYLOAD_SIZE",
8: "INVALID_TOKEN",
10: "SHUTDOWN",
255: "UNKNOWN",
}
// PushNotificationResponse details what Apple had to say, if anything.
type PushNotificationResponse struct {
Success bool
AppleResponse string
Error error
}
// NewPushNotificationResponse creates and returns a new PushNotificationResponse
// structure; it defaults to being unsuccessful at first.
func NewPushNotificationResponse() (resp *PushNotificationResponse) {
resp = new(PushNotificationResponse)
resp.Success = false
return
}

111
Godeps/_workspace/src/github.com/anachronistic/apns/push_notification_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,111 @@
package apns
import (
"testing"
)
const testDeviceToken = "e93b7686988b4b5fd334298e60e73d90035f6d12628a80b4029bde0dec514df9"
// Create a new Payload that specifies simple text,
// a badge counter, and a custom notification sound.
func mockPayload() (payload *Payload) {
payload = NewPayload()
payload.Alert = "You have mail!"
payload.Badge = 42
payload.Sound = "bingbong.aiff"
return
}
// See the commentary in push_notification.go for information
// on why we're testing a badge of value 0.
func mockZeroBadgePayload() (payload *Payload) {
payload = mockPayload()
payload.Badge = 0
return
}
// Create a new AlertDictionary. Apple recommends you not use
// the more complex alert style unless absolutely necessary.
func mockAlertDictionary() (dict *AlertDictionary) {
args := make([]string, 1)
args[0] = "localized args"
dict = NewAlertDictionary()
dict.Body = "Complex Message"
dict.ActionLocKey = "Play a Game!"
dict.LocKey = "localized key"
dict.LocArgs = args
dict.LaunchImage = "image.jpg"
return
}
func TestBasicAlert(t *testing.T) {
payload := mockPayload()
pn := NewPushNotification()
pn.DeviceToken = testDeviceToken
pn.AddPayload(payload)
bytes, _ := pn.ToBytes()
json, _ := pn.PayloadJSON()
if len(bytes) != 130 {
t.Error("expected 130 bytes; got", len(bytes))
}
if len(json) != 69 {
t.Error("expected 69 bytes; got", len(json))
}
}
func TestAlertDictionary(t *testing.T) {
dict := mockAlertDictionary()
payload := mockPayload()
payload.Alert = dict
pn := NewPushNotification()
pn.DeviceToken = testDeviceToken
pn.AddPayload(payload)
bytes, _ := pn.ToBytes()
json, _ := pn.PayloadJSON()
if len(bytes) != 255 {
t.Error("expected 255 bytes; got", len(bytes))
}
if len(json) != 194 {
t.Error("expected 194 bytes; got", len(bytes))
}
}
func TestCustomParameters(t *testing.T) {
payload := mockPayload()
pn := NewPushNotification()
pn.DeviceToken = testDeviceToken
pn.AddPayload(payload)
pn.Set("foo", "bar")
if pn.Get("foo") != "bar" {
t.Error("unable to set a custom property")
}
if pn.Get("not_set") != nil {
t.Error("expected a missing key to return nil")
}
bytes, _ := pn.ToBytes()
json, _ := pn.PayloadJSON()
if len(bytes) != 142 {
t.Error("expected 110 bytes; got", len(bytes))
}
if len(json) != 81 {
t.Error("expected 81 bytes; got", len(json))
}
}
func TestZeroBadgeChangesToNegativeOne(t *testing.T) {
payload := mockZeroBadgePayload()
pn := NewPushNotification()
pn.AddPayload(payload)
if payload.Badge != -1 {
t.Error("expected 0 badge value to be converted to -1; got", payload.Badge)
}
}

142
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/awsutil/path_value.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,142 @@
package awsutil
import (
"reflect"
"regexp"
"strconv"
"strings"
)
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
func rValuesAtPath(v interface{}, path string, create bool) []reflect.Value {
pathparts := strings.Split(path, "||")
if len(pathparts) > 1 {
for _, pathpart := range pathparts {
vals := rValuesAtPath(v, pathpart, create)
if vals != nil && len(vals) > 0 {
return vals
}
}
return nil
}
values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))}
components := strings.Split(path, ".")
for len(values) > 0 && len(components) > 0 {
var index *int64
var indexStar bool
c := strings.TrimSpace(components[0])
if c == "" { // no actual component, illegal syntax
return nil
} else if c != "*" && strings.ToLower(c[0:1]) == c[0:1] {
// TODO normalize case for user
return nil // don't support unexported fields
}
// parse this component
if m := indexRe.FindStringSubmatch(c); m != nil {
c = m[1]
if m[2] == "" {
index = nil
indexStar = true
} else {
i, _ := strconv.ParseInt(m[2], 10, 32)
index = &i
indexStar = false
}
}
nextvals := []reflect.Value{}
for _, value := range values {
// pull component name out of struct member
if value.Kind() != reflect.Struct {
continue
}
if c == "*" { // pull all members
for i := 0; i < value.NumField(); i++ {
if f := reflect.Indirect(value.Field(i)); f.IsValid() {
nextvals = append(nextvals, f)
}
}
continue
}
value = value.FieldByName(c)
if create && value.Kind() == reflect.Ptr && value.IsNil() {
value.Set(reflect.New(value.Type().Elem()))
value = value.Elem()
} else {
value = reflect.Indirect(value)
}
if value.IsValid() {
nextvals = append(nextvals, value)
}
}
values = nextvals
if indexStar || index != nil {
nextvals = []reflect.Value{}
for _, value := range values {
value := reflect.Indirect(value)
if value.Kind() != reflect.Slice {
continue
}
if indexStar { // grab all indices
for i := 0; i < value.Len(); i++ {
idx := reflect.Indirect(value.Index(i))
if idx.IsValid() {
nextvals = append(nextvals, idx)
}
}
continue
}
// pull out index
i := int(*index)
if i >= value.Len() { // check out of bounds
if create {
// TODO resize slice
} else {
continue
}
} else if i < 0 { // support negative indexing
i = value.Len() + i
}
value = reflect.Indirect(value.Index(i))
if value.IsValid() {
nextvals = append(nextvals, value)
}
}
values = nextvals
}
components = components[1:]
}
return values
}
// ValuesAtPath returns a list of objects at the lexical path inside of a structure
func ValuesAtPath(i interface{}, path string) []interface{} {
if rvals := rValuesAtPath(i, path, false); rvals != nil {
vals := make([]interface{}, len(rvals))
for i, rval := range rvals {
vals[i] = rval.Interface()
}
return vals
}
return nil
}
// SetValueAtPath sets an object at the lexical path inside of a structure
func SetValueAtPath(i interface{}, path string, v interface{}) {
if rvals := rValuesAtPath(i, path, true); rvals != nil {
for _, rval := range rvals {
rval.Set(reflect.ValueOf(v))
}
}
}

60
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/awsutil/path_value_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,60 @@
package awsutil_test
import (
"testing"
"github.com/awslabs/aws-sdk-go/aws/awsutil"
"github.com/stretchr/testify/assert"
)
type Struct struct {
A []Struct
a []Struct
B *Struct
D *Struct
C string
}
var data = Struct{
A: []Struct{Struct{C: "value1"}, Struct{C: "value2"}, Struct{C: "value3"}},
a: []Struct{Struct{C: "value1"}, Struct{C: "value2"}, Struct{C: "value3"}},
B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}},
C: "initial",
}
func TestValueAtPathSuccess(t *testing.T) {
assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "C"))
assert.Equal(t, []interface{}{"value1"}, awsutil.ValuesAtPath(data, "A[0].C"))
assert.Equal(t, []interface{}{"value2"}, awsutil.ValuesAtPath(data, "A[1].C"))
assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[2].C"))
assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[-1].C"))
assert.Equal(t, []interface{}{"value1", "value2", "value3"}, awsutil.ValuesAtPath(data, "A[].C"))
assert.Equal(t, []interface{}{"terminal"}, awsutil.ValuesAtPath(data, "B . B . C"))
assert.Equal(t, []interface{}{"terminal", "terminal2"}, awsutil.ValuesAtPath(data, "B.*.C"))
assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "A.D.X || C"))
}
func TestValueAtPathFailure(t *testing.T) {
assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "C.x"))
assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, ".x"))
assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "X.Y.Z"))
assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[100].C"))
assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[3].C"))
assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "B.B.C.Z"))
assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "a[-1].C"))
assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(nil, "A.B.C"))
}
func TestSetValueAtPathSuccess(t *testing.T) {
var s Struct
awsutil.SetValueAtPath(&s, "C", "test1")
awsutil.SetValueAtPath(&s, "B.B.C", "test2")
awsutil.SetValueAtPath(&s, "B.D.C", "test3")
assert.Equal(t, "test1", s.C)
assert.Equal(t, "test2", s.B.B.C)
assert.Equal(t, "test3", s.B.D.C)
awsutil.SetValueAtPath(&s, "B.*.C", "test0")
assert.Equal(t, "test0", s.B.B.C)
assert.Equal(t, "test0", s.B.D.C)
}

88
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/awsutil/string_value.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,88 @@
package awsutil
import (
"bytes"
"fmt"
"reflect"
"strings"
)
func StringValue(i interface{}) string {
var buf bytes.Buffer
stringValue(reflect.ValueOf(i), 0, &buf)
return buf.String()
}
func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
case reflect.Struct:
buf.WriteString("{\n")
names := []string{}
for i := 0; i < v.Type().NumField(); i++ {
name := v.Type().Field(i).Name
f := v.Field(i)
if name[0:1] == strings.ToLower(name[0:1]) {
continue // ignore unexported fields
}
if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice) && f.IsNil() {
continue // ignore unset fields
}
names = append(names, name)
}
for i, n := range names {
val := v.FieldByName(n)
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(n + ": ")
stringValue(val, indent+2, buf)
if i < len(names)-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
case reflect.Slice:
nl, id, id2 := "", "", ""
if v.Len() > 3 {
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
}
buf.WriteString("[" + nl)
for i := 0; i < v.Len(); i++ {
buf.WriteString(id2)
stringValue(v.Index(i), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString("," + nl)
}
}
buf.WriteString(nl + id + "]")
case reflect.Map:
buf.WriteString("{\n")
for i, k := range v.MapKeys() {
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(k.String() + ": ")
stringValue(v.MapIndex(k), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
default:
format := "%v"
switch v.Interface().(type) {
case string:
format = "%q"
}
fmt.Fprintf(buf, format, v.Interface())
}
}

101
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/config.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,101 @@
package aws
import (
"io"
"net/http"
"os"
)
const DEFAULT_RETRIES = -1
var DefaultConfig = &Config{
Credentials: DefaultCreds(),
Endpoint: "",
Region: os.Getenv("AWS_REGION"),
DisableSSL: false,
ManualSend: false,
HTTPClient: http.DefaultClient,
LogLevel: 0,
Logger: os.Stdout,
MaxRetries: DEFAULT_RETRIES,
DisableParamValidation: false,
}
type Config struct {
Credentials CredentialsProvider
Endpoint string
Region string
DisableSSL bool
ManualSend bool
HTTPClient *http.Client
LogLevel uint
Logger io.Writer
MaxRetries int
DisableParamValidation bool
}
func (c Config) Merge(newcfg *Config) *Config {
cfg := Config{}
if newcfg != nil && newcfg.Credentials != nil {
cfg.Credentials = newcfg.Credentials
} else {
cfg.Credentials = c.Credentials
}
if newcfg != nil && newcfg.Endpoint != "" {
cfg.Endpoint = newcfg.Endpoint
} else {
cfg.Endpoint = c.Endpoint
}
if newcfg != nil && newcfg.Region != "" {
cfg.Region = newcfg.Region
} else {
cfg.Region = c.Region
}
if newcfg != nil && newcfg.DisableSSL {
cfg.DisableSSL = newcfg.DisableSSL
} else {
cfg.DisableSSL = c.DisableSSL
}
if newcfg != nil && newcfg.ManualSend {
cfg.ManualSend = newcfg.ManualSend
} else {
cfg.ManualSend = c.ManualSend
}
if newcfg != nil && newcfg.HTTPClient != nil {
cfg.HTTPClient = newcfg.HTTPClient
} else {
cfg.HTTPClient = c.HTTPClient
}
if newcfg != nil && newcfg.LogLevel != 0 {
cfg.LogLevel = newcfg.LogLevel
} else {
cfg.LogLevel = c.LogLevel
}
if newcfg != nil && newcfg.Logger != nil {
cfg.Logger = newcfg.Logger
} else {
cfg.Logger = c.Logger
}
if newcfg != nil && newcfg.MaxRetries != DEFAULT_RETRIES {
cfg.MaxRetries = newcfg.MaxRetries
} else {
cfg.MaxRetries = c.MaxRetries
}
if newcfg != nil && newcfg.DisableParamValidation {
cfg.DisableParamValidation = newcfg.DisableParamValidation
} else {
cfg.DisableParamValidation = c.DisableParamValidation
}
return &cfg
}

288
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/credentials.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,288 @@
package aws
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"sync"
"time"
"github.com/vaughan0/go-ini"
)
var currentTime = time.Now
// Credentials are used to authenticate and authorize calls that you make to
// AWS.
type Credentials struct {
AccessKeyID string
SecretAccessKey string
SessionToken string
}
// A CredentialsProvider is a provider of credentials.
type CredentialsProvider interface {
// Credentials returns a set of credentials (or an error if no credentials
// could be provided).
Credentials() (*Credentials, error)
}
var (
// ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be
// found in the process's environment.
ErrAccessKeyIDNotFound = fmt.Errorf("AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
// ErrSecretAccessKeyNotFound is returned when the AWS Secret Access Key
// can't be found in the process's environment.
ErrSecretAccessKeyNotFound = fmt.Errorf("AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
)
type DefaultCredentialsProvider struct {
}
func (p *DefaultCredentialsProvider) Credentials() (*Credentials, error) {
env, err := EnvCreds()
if err == nil {
return env.Credentials()
}
profile, err := ProfileCreds("", "", 10*time.Minute)
if err == nil {
profileCreds, err := profile.Credentials()
if err == nil {
return profileCreds, nil
}
}
return IAMCreds().Credentials()
}
func DefaultCreds() CredentialsProvider {
return &DefaultCredentialsProvider{}
}
// DetectCreds returns a CredentialsProvider based on the available information.
//
// If the access key ID and secret access key are provided, it returns a basic
// provider.
//
// If credentials are available via environment variables, it returns an
// environment provider.
//
// If a profile configuration file is available in the default location and has
// a default profile configured, it returns a profile provider.
//
// Otherwise, it returns an IAM instance provider.
func DetectCreds(accessKeyID, secretAccessKey, sessionToken string) CredentialsProvider {
if accessKeyID != "" && secretAccessKey != "" {
return Creds(accessKeyID, secretAccessKey, sessionToken)
}
env, err := EnvCreds()
if err == nil {
return env
}
profile, err := ProfileCreds("", "", 10*time.Minute)
if err != nil {
return IAMCreds()
}
_, err = profile.Credentials()
if err != nil {
return IAMCreds()
}
return profile
}
// EnvCreds returns a static provider of AWS credentials from the process's
// environment, or an error if none are found.
func EnvCreds() (CredentialsProvider, error) {
id := os.Getenv("AWS_ACCESS_KEY_ID")
if id == "" {
id = os.Getenv("AWS_ACCESS_KEY")
}
secret := os.Getenv("AWS_SECRET_ACCESS_KEY")
if secret == "" {
secret = os.Getenv("AWS_SECRET_KEY")
}
if id == "" {
return nil, ErrAccessKeyIDNotFound
}
if secret == "" {
return nil, ErrSecretAccessKeyNotFound
}
return Creds(id, secret, os.Getenv("AWS_SESSION_TOKEN")), nil
}
// Creds returns a static provider of credentials.
func Creds(accessKeyID, secretAccessKey, sessionToken string) CredentialsProvider {
return staticCredentialsProvider{
creds: Credentials{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
SessionToken: sessionToken,
},
}
}
// IAMCreds returns a provider which pulls credentials from the local EC2
// instance's IAM roles.
func IAMCreds() CredentialsProvider {
return &iamProvider{}
}
// ProfileCreds returns a provider which pulls credentials from the profile
// configuration file.
func ProfileCreds(filename, profile string, expiry time.Duration) (CredentialsProvider, error) {
if filename == "" {
homeDir := os.Getenv("HOME") // *nix
if homeDir == "" { // Windows
homeDir = os.Getenv("USERPROFILE")
}
if homeDir == "" {
return nil, errors.New("User home directory not found.")
}
filename = filepath.Join(homeDir, ".aws", "credentials")
}
if profile == "" {
profile = "default"
}
return &profileProvider{
filename: filename,
profile: profile,
expiry: expiry,
}, nil
}
type profileProvider struct {
filename string
profile string
expiry time.Duration
creds Credentials
m sync.Mutex
expiration time.Time
}
func (p *profileProvider) Credentials() (*Credentials, error) {
p.m.Lock()
defer p.m.Unlock()
if p.expiration.After(currentTime()) {
return &p.creds, nil
}
config, err := ini.LoadFile(p.filename)
if err != nil {
return nil, err
}
profile := config.Section(p.profile)
accessKeyID, ok := profile["aws_access_key_id"]
if !ok {
return nil, fmt.Errorf("profile %s in %s did not contain aws_access_key_id", p.profile, p.filename)
}
secretAccessKey, ok := profile["aws_secret_access_key"]
if !ok {
return nil, fmt.Errorf("profile %s in %s did not contain aws_secret_access_key", p.profile, p.filename)
}
sessionToken := profile["aws_session_token"]
p.creds = Credentials{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
SessionToken: sessionToken,
}
p.expiration = currentTime().Add(p.expiry)
return &p.creds, nil
}
type iamProvider struct {
creds Credentials
m sync.Mutex
expiration time.Time
}
var metadataCredentialsEndpoint = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
// IAMClient is the HTTP client used to query the metadata endpoint for IAM
// credentials.
var IAMClient = http.Client{
Timeout: 1 * time.Second,
}
func (p *iamProvider) Credentials() (*Credentials, error) {
p.m.Lock()
defer p.m.Unlock()
if p.expiration.After(currentTime()) {
return &p.creds, nil
}
var body struct {
Expiration time.Time
AccessKeyID string
SecretAccessKey string
Token string
}
resp, err := IAMClient.Get(metadataCredentialsEndpoint)
if err != nil {
return nil, fmt.Errorf("listing IAM credentials")
}
defer func() {
_ = resp.Body.Close()
}()
// Take the first line of the body of the metadata endpoint
s := bufio.NewScanner(resp.Body)
if !s.Scan() {
return nil, fmt.Errorf("unable to find default IAM credentials")
} else if s.Err() != nil {
return nil, fmt.Errorf("%s listing IAM credentials", s.Err())
}
resp, err = IAMClient.Get(metadataCredentialsEndpoint + s.Text())
if err != nil {
return nil, fmt.Errorf("getting %s IAM credentials", s.Text())
}
defer func() {
_ = resp.Body.Close()
}()
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
return nil, fmt.Errorf("decoding %s IAM credentials", s.Text())
}
p.creds = Credentials{
AccessKeyID: body.AccessKeyID,
SecretAccessKey: body.SecretAccessKey,
SessionToken: body.Token,
}
p.expiration = body.Expiration
return &p.creds, nil
}
type staticCredentialsProvider struct {
creds Credentials
}
func (p staticCredentialsProvider) Credentials() (*Credentials, error) {
return &p.creds, nil
}

236
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/credentials_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,236 @@
package aws
import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
)
func TestEnvCreds(t *testing.T) {
os.Clearenv()
os.Setenv("AWS_ACCESS_KEY_ID", "access")
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
os.Setenv("AWS_SESSION_TOKEN", "token")
prov, err := EnvCreds()
if err != nil {
t.Fatal(err)
}
creds, err := prov.Credentials()
if err != nil {
t.Fatal(err)
}
if v, want := creds.AccessKeyID, "access"; v != want {
t.Errorf("Access key ID was %v, expected %v", v, want)
}
if v, want := creds.SecretAccessKey, "secret"; v != want {
t.Errorf("Secret access key was %v, expected %v", v, want)
}
if v, want := creds.SessionToken, "token"; v != want {
t.Errorf("Security token was %v, expected %v", v, want)
}
}
func TestEnvCredsNoAccessKeyID(t *testing.T) {
os.Clearenv()
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
prov, err := EnvCreds()
if err != ErrAccessKeyIDNotFound {
t.Fatalf("ErrAccessKeyIDNotFound expected, but was %#v/%#v", prov, err)
}
}
func TestEnvCredsNoSecretAccessKey(t *testing.T) {
os.Clearenv()
os.Setenv("AWS_ACCESS_KEY_ID", "access")
prov, err := EnvCreds()
if err != ErrSecretAccessKeyNotFound {
t.Fatalf("ErrSecretAccessKeyNotFound expected, but was %#v/%#v", prov, err)
}
}
func TestEnvCredsAlternateNames(t *testing.T) {
os.Clearenv()
os.Setenv("AWS_ACCESS_KEY", "access")
os.Setenv("AWS_SECRET_KEY", "secret")
prov, err := EnvCreds()
if err != nil {
t.Fatal(err)
}
creds, err := prov.Credentials()
if err != nil {
t.Fatal(err)
}
if v, want := creds.AccessKeyID, "access"; v != want {
t.Errorf("Access key ID was %v, expected %v", v, want)
}
if v, want := creds.SecretAccessKey, "secret"; v != want {
t.Errorf("Secret access key was %v, expected %v", v, want)
}
}
func TestIAMCreds(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.RequestURI == "/" {
fmt.Fprintln(w, "/creds")
} else {
fmt.Fprintln(w, `{
"AccessKeyId" : "accessKey",
"SecretAccessKey" : "secret",
"Token" : "token",
"Expiration" : "2014-12-16T01:51:37Z"
}`)
}
}))
defer server.Close()
defer func(s string) {
metadataCredentialsEndpoint = s
}(metadataCredentialsEndpoint)
metadataCredentialsEndpoint = server.URL
defer func() {
currentTime = time.Now
}()
currentTime = func() time.Time {
return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC)
}
prov := IAMCreds()
creds, err := prov.Credentials()
if err != nil {
t.Fatal(err)
}
if v, want := creds.AccessKeyID, "accessKey"; v != want {
t.Errorf("AcccessKeyID was %v, but expected %v", v, want)
}
if v, want := creds.SecretAccessKey, "secret"; v != want {
t.Errorf("SecretAccessKey was %v, but expected %v", v, want)
}
if v, want := creds.SessionToken, "token"; v != want {
t.Errorf("SessionToken was %v, but expected %v", v, want)
}
}
func TestProfileCreds(t *testing.T) {
prov, err := ProfileCreds("example.ini", "", 10*time.Minute)
if err != nil {
t.Fatal(err)
}
creds, err := prov.Credentials()
if err != nil {
t.Fatal(err)
}
if v, want := creds.AccessKeyID, "accessKey"; v != want {
t.Errorf("AcccessKeyID was %v, but expected %v", v, want)
}
if v, want := creds.SecretAccessKey, "secret"; v != want {
t.Errorf("SecretAccessKey was %v, but expected %v", v, want)
}
if v, want := creds.SessionToken, "token"; v != want {
t.Errorf("SessionToken was %v, but expected %v", v, want)
}
}
func TestProfileCredsWithoutToken(t *testing.T) {
prov, err := ProfileCreds("example.ini", "no_token", 10*time.Minute)
if err != nil {
t.Fatal(err)
}
creds, err := prov.Credentials()
if err != nil {
t.Fatal(err)
}
if v, want := creds.AccessKeyID, "accessKey"; v != want {
t.Errorf("AcccessKeyID was %v, but expected %v", v, want)
}
if v, want := creds.SecretAccessKey, "secret"; v != want {
t.Errorf("SecretAccessKey was %v, but expected %v", v, want)
}
if v, want := creds.SessionToken, ""; v != want {
t.Errorf("SessionToken was %v, but expected %v", v, want)
}
}
func BenchmarkProfileCreds(b *testing.B) {
prov, err := ProfileCreds("example.ini", "", 10*time.Minute)
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := prov.Credentials()
if err != nil {
b.Fatal(err)
}
}
})
}
func BenchmarkIAMCreds(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.RequestURI == "/" {
fmt.Fprintln(w, "/creds")
} else {
fmt.Fprintln(w, `{
"AccessKeyId" : "accessKey",
"SecretAccessKey" : "secret",
"Token" : "token",
"Expiration" : "2014-12-16T01:51:37Z"
}`)
}
}))
defer server.Close()
defer func(s string) {
metadataCredentialsEndpoint = s
}(metadataCredentialsEndpoint)
metadataCredentialsEndpoint = server.URL
defer func() {
currentTime = time.Now
}()
currentTime = func() time.Time {
return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC)
}
b.ResetTimer()
prov := IAMCreds()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := prov.Credentials()
if err != nil {
b.Fatal(err)
}
}
})
}

26
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/error.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,26 @@
package aws
import "time"
// An APIError is an error returned by an AWS API.
type APIError struct {
StatusCode int // HTTP status code e.g. 200
Code string
Message string
RequestID string
Retryable bool
RetryDelay time.Duration
RetryCount uint
}
func (e APIError) Error() string {
return e.Message
}
func Error(e error) *APIError {
if err, ok := e.(APIError); ok {
return &err
} else {
return nil
}
}

8
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/example.ini сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,8 @@
[default]
aws_access_key_id = accessKey
aws_secret_access_key = secret
aws_session_token = token
[no_token]
aws_access_key_id = accessKey
aws_secret_access_key = secret

78
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/handler_functions.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,78 @@
package aws
import (
"fmt"
"io"
"time"
)
var sleepDelay = func(delay time.Duration) {
time.Sleep(delay)
}
type lener interface {
Len() int
}
func BuildContentLength(r *Request) {
if r.HTTPRequest.Header.Get("Content-Length") != "" {
return
}
var length int64
switch body := r.Body.(type) {
case nil:
length = 0
case lener:
length = int64(body.Len())
case io.Seeker:
cur, _ := body.Seek(0, 1)
end, _ := body.Seek(0, 2)
body.Seek(cur, 0) // make sure to seek back to original location
length = end - cur
default:
panic("Cannot get length of body, must provide `ContentLength`")
}
r.HTTPRequest.ContentLength = length
r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
}
func UserAgentHandler(r *Request) {
r.HTTPRequest.Header.Set("User-Agent", SDKName+"/"+SDKVersion)
}
func SendHandler(r *Request) {
r.HTTPResponse, r.Error = r.Service.Config.HTTPClient.Do(r.HTTPRequest)
}
func ValidateResponseHandler(r *Request) {
if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 400 {
err := APIError{
StatusCode: r.HTTPResponse.StatusCode,
RetryCount: r.RetryCount,
}
r.Error = err
err.Retryable = r.Service.ShouldRetry(r)
err.RetryDelay = r.Service.RetryRules(r)
r.Error = err
}
}
func AfterRetryHandler(r *Request) {
delay := 0 * time.Second
willRetry := false
if err := Error(r.Error); err != nil {
delay = err.RetryDelay
if err.Retryable && r.RetryCount < r.Service.MaxRetries() {
r.RetryCount++
willRetry = true
}
}
if willRetry {
r.Error = nil
sleepDelay(delay)
}
}

65
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/handlers.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,65 @@
package aws
import "container/list"
type Handlers struct {
Validate HandlerList
Build HandlerList
Sign HandlerList
Send HandlerList
ValidateResponse HandlerList
Unmarshal HandlerList
UnmarshalMeta HandlerList
UnmarshalError HandlerList
Retry HandlerList
AfterRetry HandlerList
}
func (h *Handlers) copy() Handlers {
return Handlers{
Validate: h.Validate.copy(),
Build: h.Build.copy(),
Sign: h.Sign.copy(),
Send: h.Send.copy(),
ValidateResponse: h.ValidateResponse.copy(),
Unmarshal: h.Unmarshal.copy(),
UnmarshalError: h.UnmarshalError.copy(),
UnmarshalMeta: h.UnmarshalMeta.copy(),
Retry: h.Retry.copy(),
AfterRetry: h.AfterRetry.copy(),
}
}
// Clear removes callback functions for all handlers
func (h *Handlers) Clear() {
h.Validate.Init()
h.Build.Init()
h.Send.Init()
h.Sign.Init()
h.Unmarshal.Init()
h.UnmarshalMeta.Init()
h.UnmarshalError.Init()
h.ValidateResponse.Init()
h.Retry.Init()
h.AfterRetry.Init()
}
type HandlerList struct {
list.List
}
func (l HandlerList) copy() HandlerList {
var n HandlerList
for e := l.Front(); e != nil; e = e.Next() {
h := e.Value.(func(*Request))
n.PushBack(h)
}
return n
}
func (l *HandlerList) Run(r *Request) {
for e := l.Front(); e != nil; e = e.Next() {
h := e.Value.(func(*Request))
h(r)
}
}

24
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/handlers_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,24 @@
package aws
import "testing"
func TestHandlerList(t *testing.T) {
r := &Request{}
l := HandlerList{}
l.PushBack(func(r *Request) { r.Data = Boolean(true) })
l.Run(r)
if r.Data == nil {
t.Error("Expected handler to execute")
}
}
func TestMultipleHandlers(t *testing.T) {
r := &Request{}
l := HandlerList{}
l.PushBack(func(r *Request) { r.Data = Boolean(true) })
l.PushBack(func(r *Request) { r.Data = nil })
l.Run(r)
if r.Data != nil {
t.Error("Expected handler to execute")
}
}

80
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/param_validator.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,80 @@
package aws
import (
"fmt"
"reflect"
"strings"
)
func ValidateParameters(r *Request) {
if r.ParamsFilled() {
v := validator{errors: []string{}}
v.validateAny(reflect.ValueOf(r.Params), "")
if count := len(v.errors); count > 0 {
format := "%d validation errors:\n- %s"
msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- "))
r.Error = APIError{Code: "InvalidParameter", Message: msg}
}
}
}
type validator struct {
errors []string
}
func (v *validator) validateAny(value reflect.Value, path string) {
value = reflect.Indirect(value)
if !value.IsValid() {
return
}
switch value.Kind() {
case reflect.Struct:
v.validateStruct(value, path)
case reflect.Slice:
for i := 0; i < value.Len(); i++ {
v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i))
}
case reflect.Map:
for _, n := range value.MapKeys() {
v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String()))
}
}
}
func (v *validator) validateStruct(value reflect.Value, path string) {
prefix := "."
if path == "" {
prefix = ""
}
for i := 0; i < value.Type().NumField(); i++ {
f := value.Type().Field(i)
if strings.ToLower(f.Name[0:1]) == f.Name[0:1] {
continue
}
fvalue := value.FieldByName(f.Name)
notset := false
if f.Tag.Get("required") != "" {
switch fvalue.Kind() {
case reflect.Ptr, reflect.Slice:
if fvalue.IsNil() {
notset = true
}
default:
if !fvalue.IsValid() {
notset = true
}
}
}
if notset {
msg := "missing required parameter: " + path + prefix + f.Name
v.errors = append(v.errors, msg)
} else {
v.validateAny(fvalue, path+prefix+f.Name)
}
}
}

85
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/param_validator_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,85 @@
package aws_test
import (
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/stretchr/testify/assert"
)
var service = func() *aws.Service {
s := &aws.Service{
Config: &aws.Config{},
ServiceName: "mock-service",
APIVersion: "2015-01-01",
}
return s
}()
type StructShape struct {
RequiredList []*ConditionalStructShape `required:"true"`
RequiredMap *map[string]*ConditionalStructShape `required:"true"`
RequiredBool *bool `required:"true"`
OptionalStruct *ConditionalStructShape
hiddenParameter *string
metadataStructureShape
}
type metadataStructureShape struct {
SDKShapeTraits bool
}
type ConditionalStructShape struct {
Name *string `required:"true"`
SDKShapeTraits bool
}
func TestNoErrors(t *testing.T) {
input := &StructShape{
RequiredList: []*ConditionalStructShape{},
RequiredMap: &map[string]*ConditionalStructShape{
"key1": &ConditionalStructShape{Name: aws.String("Name")},
"key2": &ConditionalStructShape{Name: aws.String("Name")},
},
RequiredBool: aws.Boolean(true),
OptionalStruct: &ConditionalStructShape{Name: aws.String("Name")},
}
req := aws.NewRequest(service, &aws.Operation{}, input, nil)
aws.ValidateParameters(req)
assert.NoError(t, req.Error)
}
func TestMissingRequiredParameters(t *testing.T) {
input := &StructShape{}
req := aws.NewRequest(service, &aws.Operation{}, input, nil)
aws.ValidateParameters(req)
err := aws.Error(req.Error)
assert.Error(t, err)
assert.Equal(t, "InvalidParameter", err.Code)
assert.Equal(t, "3 validation errors:\n- missing required parameter: RequiredList\n- missing required parameter: RequiredMap\n- missing required parameter: RequiredBool", err.Message)
}
func TestNestedMissingRequiredParameters(t *testing.T) {
input := &StructShape{
RequiredList: []*ConditionalStructShape{&ConditionalStructShape{}},
RequiredMap: &map[string]*ConditionalStructShape{
"key1": &ConditionalStructShape{Name: aws.String("Name")},
"key2": &ConditionalStructShape{},
},
RequiredBool: aws.Boolean(true),
OptionalStruct: &ConditionalStructShape{},
}
req := aws.NewRequest(service, &aws.Operation{}, input, nil)
aws.ValidateParameters(req)
err := aws.Error(req.Error)
assert.Error(t, err)
assert.Equal(t, "InvalidParameter", err.Code)
assert.Equal(t, "3 validation errors:\n- missing required parameter: RequiredList[0].Name\n- missing required parameter: RequiredMap[\"key2\"].Name\n- missing required parameter: OptionalStruct.Name", err.Message)
}

149
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/request.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,149 @@
package aws
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"net/url"
"reflect"
"time"
)
type Request struct {
*Service
Handlers Handlers
Time time.Time
ExpireTime time.Duration
Operation *Operation
HTTPRequest *http.Request
HTTPResponse *http.Response
Body io.ReadSeeker
Params interface{}
Error error
Data interface{}
RequestID string
RetryCount uint
built bool
}
type Operation struct {
Name string
HTTPMethod string
HTTPPath string
}
func NewRequest(service *Service, operation *Operation, params interface{}, data interface{}) *Request {
method := operation.HTTPMethod
if method == "" {
method = "POST"
}
p := operation.HTTPPath
if p == "" {
p = "/"
}
httpReq, _ := http.NewRequest(method, "", nil)
httpReq.URL, _ = url.Parse(service.Endpoint + p)
r := &Request{
Service: service,
Handlers: service.Handlers.copy(),
Time: time.Now(),
ExpireTime: 0,
Operation: operation,
HTTPRequest: httpReq,
Body: nil,
Params: params,
Error: nil,
Data: data,
}
r.SetBufferBody([]byte{})
return r
}
func (r *Request) ParamsFilled() bool {
return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid()
}
func (r *Request) DataFilled() bool {
return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid()
}
func (r *Request) SetBufferBody(buf []byte) {
r.SetReaderBody(bytes.NewReader(buf))
}
func (r *Request) SetReaderBody(reader io.ReadSeeker) {
r.HTTPRequest.Body = ioutil.NopCloser(reader)
r.Body = reader
}
func (r *Request) Presign(expireTime time.Duration) (string, error) {
r.ExpireTime = expireTime
r.Sign()
if r.Error != nil {
return "", r.Error
} else {
return r.HTTPRequest.URL.String(), nil
}
}
func (r *Request) Build() error {
if !r.built {
r.Error = nil
r.Handlers.Validate.Run(r)
if r.Error != nil {
return r.Error
}
r.Handlers.Build.Run(r)
r.built = true
}
return r.Error
}
func (r *Request) Sign() error {
r.Build()
if r.Error != nil {
return r.Error
}
r.Handlers.Sign.Run(r)
return r.Error
}
func (r *Request) Send() error {
r.Sign()
if r.Error != nil {
return r.Error
}
for {
r.Handlers.Send.Run(r)
if r.Error != nil {
return r.Error
}
r.Handlers.UnmarshalMeta.Run(r)
r.Handlers.ValidateResponse.Run(r)
if r.Error != nil {
r.Handlers.Retry.Run(r)
r.Handlers.AfterRetry.Run(r)
if r.Error != nil {
r.Handlers.UnmarshalError.Run(r)
return r.Error
}
continue
}
r.Handlers.Unmarshal.Run(r)
if r.Error != nil {
return r.Error
}
return nil
}
}

118
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/request_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,118 @@
package aws
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"reflect"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
type testData struct {
Data string
}
func body(str string) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(str)))
}
func unmarshal(req *Request) {
defer req.HTTPResponse.Body.Close()
if req.Data != nil {
json.NewDecoder(req.HTTPResponse.Body).Decode(req.Data)
}
return
}
func unmarshalError(req *Request) {
bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body)
if err != nil {
req.Error = err
return
}
if len(bodyBytes) == 0 {
req.Error = APIError{
StatusCode: req.HTTPResponse.StatusCode,
Message: req.HTTPResponse.Status,
}
return
}
var jsonErr jsonErrorResponse
if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil {
req.Error = err
return
}
req.Error = APIError{
StatusCode: req.HTTPResponse.StatusCode,
Code: jsonErr.Code,
Message: jsonErr.Message,
}
}
type jsonErrorResponse struct {
Code string `json:"__type"`
Message string `json:"message"`
}
func TestRequestRecoverRetry(t *testing.T) {
reqNum := 0
reqs := []http.Response{
http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
http.Response{StatusCode: 200, Body: body(`{"data":"valid"}`)},
}
s := NewService(&Config{MaxRetries: -1})
s.Handlers.Unmarshal.PushBack(unmarshal)
s.Handlers.UnmarshalError.PushBack(unmarshalError)
s.Handlers.Send.Init() // mock sending
s.Handlers.Send.PushBack(func(r *Request) {
r.HTTPResponse = &reqs[reqNum]
reqNum++
})
out := &testData{}
r := NewRequest(s, &Operation{Name: "Operation"}, nil, out)
err := r.Send()
assert.Nil(t, err)
assert.Equal(t, 2, int(r.RetryCount))
assert.Equal(t, "valid", out.Data)
}
func TestRequestExhaustRetries(t *testing.T) {
delays := []time.Duration{}
sleepDelay = func(delay time.Duration) {
delays = append(delays, delay)
}
reqNum := 0
reqs := []http.Response{
http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
}
s := NewService(&Config{MaxRetries: -1})
s.Handlers.Unmarshal.PushBack(unmarshal)
s.Handlers.UnmarshalError.PushBack(unmarshalError)
s.Handlers.Send.Init() // mock sending
s.Handlers.Send.PushBack(func(r *Request) {
r.HTTPResponse = &reqs[reqNum]
reqNum++
})
r := NewRequest(s, &Operation{Name: "Operation"}, nil, nil)
err := r.Send()
apiErr := Error(err)
assert.NotNil(t, err)
assert.NotNil(t, apiErr)
assert.Equal(t, 500, apiErr.StatusCode)
assert.Equal(t, "UnknownError", apiErr.Code)
assert.Equal(t, "An error occurred.", apiErr.Message)
assert.Equal(t, 3, int(r.RetryCount))
assert.True(t, reflect.DeepEqual([]time.Duration{30 * time.Millisecond, 60 * time.Millisecond, 120 * time.Millisecond}, delays))
}

142
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/service.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,142 @@
package aws
import (
"fmt"
"math"
"net/http"
"net/http/httputil"
"regexp"
"time"
"github.com/awslabs/aws-sdk-go/internal/endpoints"
)
type Service struct {
Config *Config
Handlers Handlers
ManualSend bool
ServiceName string
APIVersion string
Endpoint string
JSONVersion string
TargetPrefix string
RetryRules func(*Request) time.Duration
ShouldRetry func(*Request) bool
DefaultMaxRetries uint
}
var schemeRE = regexp.MustCompile("^([^:]+)://")
func NewService(config *Config) *Service {
svc := &Service{Config: config}
svc.Initialize()
return svc
}
func (s *Service) Initialize() {
if s.Config == nil {
s.Config = &Config{}
}
if s.Config.HTTPClient == nil {
s.Config.HTTPClient = http.DefaultClient
}
if s.RetryRules == nil {
s.RetryRules = retryRules
}
if s.ShouldRetry == nil {
s.ShouldRetry = shouldRetry
}
s.DefaultMaxRetries = 3
s.Handlers.Build.PushBack(UserAgentHandler)
s.Handlers.Sign.PushBack(BuildContentLength)
s.Handlers.Send.PushBack(SendHandler)
s.Handlers.AfterRetry.PushBack(AfterRetryHandler)
s.Handlers.ValidateResponse.PushBack(ValidateResponseHandler)
s.AddDebugHandlers()
s.buildEndpoint()
if !s.Config.DisableParamValidation {
s.Handlers.Validate.PushBack(ValidateParameters)
}
}
func (s *Service) buildEndpoint() {
if s.Config.Endpoint != "" {
s.Endpoint = s.Config.Endpoint
} else {
s.Endpoint = endpoints.EndpointForRegion(s.ServiceName, s.Config.Region)
}
if !schemeRE.MatchString(s.Endpoint) {
scheme := "https"
if s.Config.DisableSSL {
scheme = "http"
}
s.Endpoint = scheme + "://" + s.Endpoint
}
}
func (s *Service) AddDebugHandlers() {
out := s.Config.Logger
if s.Config.LogLevel == 0 {
return
}
s.Handlers.Sign.PushBack(func(r *Request) {
dumpedBody, _ := httputil.DumpRequest(r.HTTPRequest, true)
fmt.Fprintf(out, "=> [%s] %s.%s(%+v)\n", r.Time,
r.Service.ServiceName, r.Operation.Name, r.Params)
fmt.Fprintf(out, "---[ REQUEST PRE-SIGN ]------------------------------\n")
fmt.Fprintf(out, "%s\n", string(dumpedBody))
fmt.Fprintf(out, "-----------------------------------------------------\n")
})
s.Handlers.Send.PushFront(func(r *Request) {
dumpedBody, _ := httputil.DumpRequest(r.HTTPRequest, true)
fmt.Fprintf(out, "---[ REQUEST POST-SIGN ]-----------------------------\n")
fmt.Fprintf(out, "%s\n", string(dumpedBody))
fmt.Fprintf(out, "-----------------------------------------------------\n")
})
s.Handlers.Send.PushBack(func(r *Request) {
fmt.Fprintf(out, "---[ RESPONSE ]--------------------------------------\n")
if r.HTTPResponse != nil {
dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, true)
fmt.Fprintf(out, "%s\n", string(dumpedBody))
} else if r.Error != nil {
fmt.Fprintf(out, "%s\n", r.Error)
}
fmt.Fprintf(out, "-----------------------------------------------------\n")
})
}
func (s *Service) MaxRetries() uint {
if s.Config.MaxRetries < 0 {
return s.DefaultMaxRetries
} else {
return uint(s.Config.MaxRetries)
}
}
func retryRules(r *Request) time.Duration {
delay := time.Duration(math.Pow(2, float64(r.RetryCount))) * 30
return delay * time.Millisecond
}
func shouldRetry(r *Request) bool {
if err := Error(r.Error); err != nil {
if err.StatusCode >= 500 {
return true
}
switch err.Code {
case "ExpiredTokenException":
case "ProvisionedThroughputExceededException", "Throttling":
return true
}
}
return false
}

63
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/types.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,63 @@
package aws
import (
"io"
"time"
)
// String converts a Go string into a string pointer.
func String(v string) *string {
return &v
}
// Boolean converts a Go bool into a boolean pointer.
func Boolean(v bool) *bool {
return &v
}
// Long converts a Go int64 into a long pointer.
func Long(v int64) *int64 {
return &v
}
// Double converts a Go float64 into a double pointer.
func Double(v float64) *float64 {
return &v
}
// Time converts a Go Time into a Time pointer
func Time(t time.Time) *time.Time {
return &t
}
func ReadSeekCloser(r io.Reader) ReaderSeekerCloser {
return ReaderSeekerCloser{r}
}
type ReaderSeekerCloser struct {
r io.Reader
}
func (r ReaderSeekerCloser) Read(p []byte) (int, error) {
switch t := r.r.(type) {
case io.Reader:
return t.Read(p)
}
return 0, nil
}
func (r ReaderSeekerCloser) Seek(offset int64, whence int) (int64, error) {
switch t := r.r.(type) {
case io.Seeker:
return t.Seek(offset, whence)
}
return int64(0), nil
}
func (r ReaderSeekerCloser) Close() error {
switch t := r.r.(type) {
case io.Closer:
return t.Close()
}
return nil
}

5
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/version.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,5 @@
// Package aws provides core functionality for making requests to AWS services.
package aws
const SDKName = "aws-sdk-go"
const SDKVersion = "0.5.0"

24
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,24 @@
package endpoints
//go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go
import "strings"
func EndpointForRegion(svcName, region string) string {
derivedKeys := []string{
region + "/" + svcName,
region + "/*",
"*/" + svcName,
"*/*",
}
for _, key := range derivedKeys {
if val, ok := endpointsMap.Endpoints[key]; ok {
ep := val.Endpoint
ep = strings.Replace(ep, "{region}", region, -1)
ep = strings.Replace(ep, "{service}", svcName, -1)
return ep
}
}
return ""
}

67
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.json сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,67 @@
{
"version": 2,
"endpoints": {
"*/*": {
"endpoint": "{service}.{region}.amazonaws.com"
},
"cn-north-1/*": {
"endpoint": "{service}.{region}.amazonaws.com.cn",
"signatureVersion": "v4"
},
"us-gov-west-1/iam": {
"endpoint": "iam.us-gov.amazonaws.com"
},
"us-gov-west-1/sts": {
"endpoint": "sts.us-gov-west-1.amazonaws.com"
},
"us-gov-west-1/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"*/cloudfront": {
"endpoint": "cloudfront.amazonaws.com"
},
"*/iam": {
"endpoint": "iam.amazonaws.com"
},
"*/importexport": {
"endpoint": "importexport.amazonaws.com"
},
"*/route53": {
"endpoint": "route53.amazonaws.com"
},
"*/sts": {
"endpoint": "sts.amazonaws.com"
},
"us-east-1/sdb": {
"endpoint": "sdb.amazonaws.com"
},
"us-east-1/s3": {
"endpoint": "s3.amazonaws.com"
},
"us-west-1/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"us-west-2/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"eu-west-1/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"ap-southeast-1/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"ap-southeast-2/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"ap-northeast-1/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"sa-east-1/s3": {
"endpoint": "s3-{region}.amazonaws.com"
},
"eu-central-1/s3": {
"endpoint": "{service}.{region}.amazonaws.com",
"signatureVersion": "v4"
}
}
}

78
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_map.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,78 @@
package endpoints
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
type endpointStruct struct {
Version int
Endpoints map[string]endpointEntry
}
type endpointEntry struct {
Endpoint string
}
var endpointsMap = endpointStruct{
Version: 2,
Endpoints: map[string]endpointEntry{
"*/*": endpointEntry{
Endpoint: "{service}.{region}.amazonaws.com",
},
"*/cloudfront": endpointEntry{
Endpoint: "cloudfront.amazonaws.com",
},
"*/iam": endpointEntry{
Endpoint: "iam.amazonaws.com",
},
"*/importexport": endpointEntry{
Endpoint: "importexport.amazonaws.com",
},
"*/route53": endpointEntry{
Endpoint: "route53.amazonaws.com",
},
"*/sts": endpointEntry{
Endpoint: "sts.amazonaws.com",
},
"ap-northeast-1/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
"ap-southeast-1/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
"ap-southeast-2/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
"cn-north-1/*": endpointEntry{
Endpoint: "{service}.{region}.amazonaws.com.cn",
},
"eu-central-1/s3": endpointEntry{
Endpoint: "{service}.{region}.amazonaws.com",
},
"eu-west-1/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
"sa-east-1/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
"us-east-1/s3": endpointEntry{
Endpoint: "s3.amazonaws.com",
},
"us-east-1/sdb": endpointEntry{
Endpoint: "sdb.amazonaws.com",
},
"us-gov-west-1/iam": endpointEntry{
Endpoint: "iam.us-gov.amazonaws.com",
},
"us-gov-west-1/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
"us-gov-west-1/sts": endpointEntry{
Endpoint: "sts.us-gov-west-1.amazonaws.com",
},
"us-west-1/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
"us-west-2/s3": endpointEntry{
Endpoint: "s3-{region}.amazonaws.com",
},
},
}

25
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,25 @@
package endpoints
import "testing"
func TestGlobalEndpoints(t *testing.T) {
region := "mock-region-1"
svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts"}
for _, name := range svcs {
if EndpointForRegion(name, region) != name+".amazonaws.com" {
t.Errorf("expected endpoint for %s to equal %s.amazonaws.com", name, name)
}
}
}
func TestServicesInCN(t *testing.T) {
region := "cn-north-1"
svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "s3"}
for _, name := range svcs {
if EndpointForRegion(name, region) != name+"."+region+".amazonaws.com.cn" {
t.Errorf("expected endpoint for %s to equal %s.%s.amazonaws.com.cn", name, name, region)
}
}
}

30
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/query/build.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,30 @@
package query
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/query.json build_test.go
import (
"net/url"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/internal/protocol/query/queryutil"
)
func Build(r *aws.Request) {
body := url.Values{
"Action": {r.Operation.Name},
"Version": {r.Service.APIVersion},
}
if err := queryutil.Parse(body, r.Params, false); err != nil {
r.Error = err
return
}
if r.ExpireTime == 0 {
r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode()))
} else { // This is a pre-signed request
r.HTTPRequest.Method = "GET"
r.HTTPRequest.URL.RawQuery = body.Encode()
}
}

1167
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/query/build_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

198
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/query/queryutil/queryutil.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,198 @@
package queryutil
import (
"encoding/base64"
"fmt"
"net/url"
"reflect"
"sort"
"strconv"
"strings"
"time"
)
func Parse(body url.Values, i interface{}, isEC2 bool) error {
q := queryParser{isEC2: isEC2}
return q.parseValue(body, reflect.ValueOf(i), "", "")
}
func elemOf(value reflect.Value) reflect.Value {
for value.Kind() == reflect.Ptr {
value = value.Elem()
}
return value
}
type queryParser struct {
isEC2 bool
}
func (q *queryParser) parseValue(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
value = elemOf(value)
// no need to handle zero values
if !value.IsValid() {
return nil
}
t := tag.Get("type")
if t == "" {
switch value.Kind() {
case reflect.Struct:
t = "structure"
case reflect.Slice:
t = "list"
case reflect.Map:
t = "map"
}
}
switch t {
case "structure":
return q.parseStruct(v, value, prefix)
case "list":
return q.parseList(v, value, prefix, tag)
case "map":
return q.parseMap(v, value, prefix, tag)
default:
return q.parseScalar(v, value, prefix, tag)
}
}
func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix string) error {
if !value.IsValid() {
return nil
}
t := value.Type()
for i := 0; i < value.NumField(); i++ {
if c := t.Field(i).Name[0:1]; strings.ToLower(c) == c {
continue // ignore unexported fields
}
value := elemOf(value.Field(i))
field := t.Field(i)
var name string
if q.isEC2 {
name = field.Tag.Get("queryName")
}
if name == "" {
if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" {
name = field.Tag.Get("locationNameList")
} else if locName := field.Tag.Get("locationName"); locName != "" {
name = locName
}
if name != "" && q.isEC2 {
name = strings.ToUpper(name[0:1]) + name[1:]
}
}
if name == "" {
name = field.Name
}
if prefix != "" {
name = prefix + "." + name
}
if err := q.parseValue(v, value, name, field.Tag); err != nil {
return err
}
}
return nil
}
func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
// check for unflattened list member
if !q.isEC2 && tag.Get("flattened") == "" {
prefix += ".member"
}
for i := 0; i < value.Len(); i++ {
slicePrefix := prefix
if slicePrefix == "" {
slicePrefix = strconv.Itoa(i + 1)
} else {
slicePrefix = slicePrefix + "." + strconv.Itoa(i+1)
}
if err := q.parseValue(v, value.Index(i), slicePrefix, ""); err != nil {
return err
}
}
return nil
}
func (q *queryParser) parseMap(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
// check for unflattened list member
if !q.isEC2 && tag.Get("flattened") == "" {
prefix += ".entry"
}
// sort keys for improved serialization consistency.
// this is not strictly necessary for protocol support.
mapKeyValues := value.MapKeys()
mapKeys := map[string]reflect.Value{}
mapKeyNames := make([]string, len(mapKeyValues))
for i, mapKey := range mapKeyValues {
name := mapKey.String()
mapKeys[name] = mapKey
mapKeyNames[i] = name
}
sort.Strings(mapKeyNames)
for i, mapKeyName := range mapKeyNames {
mapKey := mapKeys[mapKeyName]
mapValue := value.MapIndex(mapKey)
// serialize key
var keyName string
if prefix == "" {
keyName = strconv.Itoa(i+1) + ".key"
} else {
keyName = prefix + "." + strconv.Itoa(i+1) + ".key"
}
if err := q.parseValue(v, mapKey, keyName, ""); err != nil {
return err
}
// serialize value
var valueName string
if prefix == "" {
valueName = strconv.Itoa(i+1) + ".value"
} else {
valueName = prefix + "." + strconv.Itoa(i+1) + ".value"
}
if err := q.parseValue(v, mapValue, valueName, ""); err != nil {
return err
}
}
return nil
}
func (q *queryParser) parseScalar(v url.Values, r reflect.Value, name string, tag reflect.StructTag) error {
switch value := r.Interface().(type) {
case string:
v.Set(name, value)
case []byte:
v.Set(name, base64.StdEncoding.EncodeToString(value))
case bool:
v.Set(name, strconv.FormatBool(value))
case int64:
v.Set(name, strconv.FormatInt(value, 10))
case int:
v.Set(name, strconv.Itoa(value))
case float64:
v.Set(name, strconv.FormatFloat(value, 'f', -1, 64))
case float32:
v.Set(name, strconv.FormatFloat(float64(value), 'f', -1, 32))
case time.Time:
const ISO8601UTC = "2006-01-02T15:04:05Z"
v.Set(name, value.UTC().Format(ISO8601UTC))
default:
return fmt.Errorf("unsupported value for param %s: %v (%s)", name, r.Interface(), r.Type().Name())
}
return nil
}

26
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/query/unmarshal.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,26 @@
package query
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/query.json unmarshal_test.go
import (
"encoding/xml"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/internal/protocol/xml/xmlutil"
)
func Unmarshal(r *aws.Request) {
defer r.HTTPResponse.Body.Close()
if r.DataFilled() {
decoder := xml.NewDecoder(r.HTTPResponse.Body)
err := xmlutil.UnmarshalXML(r.Data, decoder, r.Operation.Name+"Result")
if err != nil {
r.Error = err
return
}
}
}
func UnmarshalMeta(r *aws.Request) {
// TODO implement unmarshaling of request IDs
}

31
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/query/unmarshal_error.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,31 @@
package query
import (
"encoding/xml"
"io"
"github.com/awslabs/aws-sdk-go/aws"
)
type xmlErrorResponse struct {
XMLName xml.Name `xml:"ErrorResponse"`
Code string `xml:"Error>Code"`
Message string `xml:"Error>Message"`
RequestID string `xml:"RequestId"`
}
func UnmarshalError(r *aws.Request) {
defer r.HTTPResponse.Body.Close()
resp := &xmlErrorResponse{}
err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp)
if err != nil && err != io.EOF {
r.Error = err
} else {
r.Error = aws.APIError{
StatusCode: r.HTTPResponse.StatusCode,
Code: resp.Code,
Message: resp.Message,
}
}
}

1361
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/query/unmarshal_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

215
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/rest/build.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,215 @@
package rest
import (
"bytes"
"encoding/base64"
"fmt"
"io"
"net/url"
"path"
"reflect"
"strconv"
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
)
// RFC822 returns an RFC822 formatted timestamp for AWS protocols
const RFC822 = "Mon, 2 Jan 2006 15:04:05 GMT"
func Build(r *aws.Request) {
if r.ParamsFilled() {
v := reflect.ValueOf(r.Params).Elem()
buildLocationElements(r, v)
buildBody(r, v)
}
}
func buildLocationElements(r *aws.Request, v reflect.Value) {
query := r.HTTPRequest.URL.Query()
for i := 0; i < v.NumField(); i++ {
m := v.Field(i)
if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) {
continue
}
if m.IsValid() {
field := v.Type().Field(i)
name := field.Tag.Get("locationName")
if name == "" {
name = field.Name
}
if m.Kind() == reflect.Ptr {
m = m.Elem()
}
if !m.IsValid() {
continue
}
switch field.Tag.Get("location") {
case "headers": // header maps
buildHeaderMap(r, m, field.Tag.Get("locationName"))
case "header":
buildHeader(r, m, name)
case "uri":
buildURI(r, m, name)
case "querystring":
buildQueryString(r, m, name, query)
}
}
if r.Error != nil {
return
}
}
r.HTTPRequest.URL.RawQuery = query.Encode()
updatePath(r.HTTPRequest.URL, r.HTTPRequest.URL.Path)
}
func buildBody(r *aws.Request, v reflect.Value) {
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
if payloadName := field.Tag.Get("payload"); payloadName != "" {
pfield, _ := v.Type().FieldByName(payloadName)
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
payload := reflect.Indirect(v.FieldByName(payloadName))
if payload.IsValid() && payload.Interface() != nil {
switch reader := payload.Interface().(type) {
case io.ReadSeeker:
r.SetReaderBody(reader)
case []byte:
r.SetBufferBody(reader)
case string:
r.SetBufferBody([]byte(reader))
default:
r.Error = fmt.Errorf("unknown payload type %s", payload.Type())
}
}
}
}
}
}
func buildHeader(r *aws.Request, v reflect.Value, name string) {
str, err := convertType(v)
if err != nil {
r.Error = err
} else if str != nil {
r.HTTPRequest.Header.Add(name, *str)
}
}
func buildHeaderMap(r *aws.Request, v reflect.Value, prefix string) {
for _, key := range v.MapKeys() {
str, err := convertType(v.MapIndex(key))
if err != nil {
r.Error = err
} else if str != nil {
r.HTTPRequest.Header.Add(prefix+key.String(), *str)
}
}
}
func buildURI(r *aws.Request, v reflect.Value, name string) {
value, err := convertType(v)
if err != nil {
r.Error = err
} else if value != nil {
uri := r.HTTPRequest.URL.Path
uri = strings.Replace(uri, "{"+name+"}", escapePath(*value, true), -1)
uri = strings.Replace(uri, "{"+name+"+}", escapePath(*value, false), -1)
r.HTTPRequest.URL.Path = uri
}
}
func buildQueryString(r *aws.Request, v reflect.Value, name string, query url.Values) {
str, err := convertType(v)
if err != nil {
r.Error = err
} else if str != nil {
query.Set(name, *str)
}
}
func updatePath(url *url.URL, urlPath string) {
scheme, query := url.Scheme, url.RawQuery
// clean up path
urlPath = path.Clean(urlPath)
// get formatted URL minus scheme so we can build this into Opaque
url.Scheme, url.Path, url.RawQuery = "", "", ""
s := url.String()
url.Scheme = scheme
url.RawQuery = query
// build opaque URI
url.Opaque = s + urlPath
}
// Whether the byte value can be sent without escaping in AWS URLs
var noEscape [256]bool
var noEscapeInitialized = false
// initialise noEscape
func initNoEscape() {
for i := range noEscape {
// Amazon expects every character except these escaped
noEscape[i] = (i >= 'A' && i <= 'Z') ||
(i >= 'a' && i <= 'z') ||
(i >= '0' && i <= '9') ||
i == '-' ||
i == '.' ||
i == '_' ||
i == '~'
}
}
// escapePath escapes part of a URL path in Amazon style
func escapePath(path string, encodeSep bool) string {
if !noEscapeInitialized {
initNoEscape()
noEscapeInitialized = true
}
var buf bytes.Buffer
for i := 0; i < len(path); i++ {
c := path[i]
if noEscape[c] || (c == '/' && !encodeSep) {
buf.WriteByte(c)
} else {
buf.WriteByte('%')
buf.WriteString(strings.ToUpper(strconv.FormatUint(uint64(c), 16)))
}
}
return buf.String()
}
func convertType(v reflect.Value) (*string, error) {
v = reflect.Indirect(v)
if !v.IsValid() {
return nil, nil
}
var str string
switch value := v.Interface().(type) {
case string:
str = value
case []byte:
str = base64.StdEncoding.EncodeToString(value)
case bool:
str = strconv.FormatBool(value)
case int64:
str = strconv.FormatInt(value, 10)
case float64:
str = strconv.FormatFloat(value, 'f', -1, 64)
case time.Time:
str = value.UTC().Format(RFC822)
default:
err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type())
return nil, err
}
return &str, nil
}

43
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/rest/payload.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
package rest
import "reflect"
func PayloadMember(i interface{}) interface{} {
if i == nil {
return nil
}
v := reflect.ValueOf(i).Elem()
if !v.IsValid() {
return nil
}
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
if payloadName := field.Tag.Get("payload"); payloadName != "" {
field, _ := v.Type().FieldByName(payloadName)
if field.Tag.Get("type") != "structure" {
return nil
}
payload := v.FieldByName(payloadName)
if payload.IsValid() || (payload.Kind() == reflect.Ptr && !payload.IsNil()) {
return payload.Interface()
}
}
}
return nil
}
func PayloadType(i interface{}) string {
v := reflect.Indirect(reflect.ValueOf(i))
if !v.IsValid() {
return ""
}
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
if payloadName := field.Tag.Get("payload"); payloadName != "" {
if member, ok := v.Type().FieldByName(payloadName); ok {
return member.Tag.Get("type")
}
}
}
return ""
}

174
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/rest/unmarshal.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,174 @@
package rest
import (
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strconv"
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
)
func Unmarshal(r *aws.Request) {
if r.DataFilled() {
v := reflect.Indirect(reflect.ValueOf(r.Data))
unmarshalBody(r, v)
unmarshalLocationElements(r, v)
}
}
func unmarshalBody(r *aws.Request, v reflect.Value) {
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
if payloadName := field.Tag.Get("payload"); payloadName != "" {
pfield, _ := v.Type().FieldByName(payloadName)
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
payload := reflect.Indirect(v.FieldByName(payloadName))
if payload.IsValid() {
switch payload.Interface().(type) {
case []byte:
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
r.Error = err
} else {
payload.Set(reflect.ValueOf(b))
}
case string:
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
r.Error = err
} else {
payload.Set(reflect.ValueOf(string(b)))
}
default:
switch payload.Type().String() {
case "io.ReadSeeker":
payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body)))
case "aws.ReadSeekCloser", "io.ReadCloser":
payload.Set(reflect.ValueOf(r.HTTPResponse.Body))
default:
r.Error = fmt.Errorf("unknown payload type %s", payload.Type())
}
}
}
}
}
}
}
func unmarshalLocationElements(r *aws.Request, v reflect.Value) {
for i := 0; i < v.NumField(); i++ {
m, field := v.Field(i), v.Type().Field(i)
if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) {
continue
}
if m.IsValid() {
name := field.Tag.Get("locationName")
if name == "" {
name = field.Name
}
switch field.Tag.Get("location") {
case "statusCode":
unmarshalStatusCode(m, r.HTTPResponse.StatusCode)
case "header":
err := unmarshalHeader(m, r.HTTPResponse.Header.Get(name))
if err != nil {
r.Error = err
break
}
case "headers":
prefix := field.Tag.Get("locationName")
err := unmarshalHeaderMap(m, r.HTTPResponse.Header, prefix)
if err != nil {
r.Error = err
break
}
}
}
if r.Error != nil {
return
}
}
}
func unmarshalStatusCode(v reflect.Value, statusCode int) {
if !v.IsValid() {
return
}
switch v.Interface().(type) {
case *int64:
s := int64(statusCode)
v.Set(reflect.ValueOf(&s))
}
}
func unmarshalHeaderMap(r reflect.Value, headers http.Header, prefix string) error {
switch r.Interface().(type) {
case *map[string]*string: // we only support string map value types
out := map[string]*string{}
for k, v := range headers {
k = http.CanonicalHeaderKey(k)
if strings.HasPrefix(strings.ToLower(k), strings.ToLower(prefix)) {
out[k[len(prefix):]] = &v[0]
}
}
r.Set(reflect.ValueOf(&out))
}
return nil
}
func unmarshalHeader(v reflect.Value, header string) error {
if !v.IsValid() || (header == "" && v.Elem().Kind() != reflect.String) {
return nil
}
switch v.Interface().(type) {
case *string:
v.Set(reflect.ValueOf(&header))
case []byte:
b, err := base64.StdEncoding.DecodeString(header)
if err != nil {
return err
} else {
v.Set(reflect.ValueOf(&b))
}
case *bool:
b, err := strconv.ParseBool(header)
if err != nil {
return err
} else {
v.Set(reflect.ValueOf(&b))
}
case *int64:
i, err := strconv.ParseInt(header, 10, 64)
if err != nil {
return err
} else {
v.Set(reflect.ValueOf(&i))
}
case *float64:
f, err := strconv.ParseFloat(header, 64)
if err != nil {
return err
} else {
v.Set(reflect.ValueOf(&f))
}
case *time.Time:
t, err := time.Parse(RFC822, header)
if err != nil {
return err
} else {
v.Set(reflect.ValueOf(&t))
}
default:
err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type())
return err
}
return nil
}

2571
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/restxml/build_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

48
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/restxml/restxml.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,48 @@
package restxml
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/rest-xml.json build_test.go
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/rest-xml.json unmarshal_test.go
import (
"bytes"
"encoding/xml"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/internal/protocol/query"
"github.com/awslabs/aws-sdk-go/internal/protocol/rest"
"github.com/awslabs/aws-sdk-go/internal/protocol/xml/xmlutil"
)
func Build(r *aws.Request) {
rest.Build(r)
if t := rest.PayloadType(r.Params); t == "structure" || t == "" {
var buf bytes.Buffer
err := xmlutil.BuildXML(r.Params, xml.NewEncoder(&buf))
if err != nil {
r.Error = err
return
}
r.SetBufferBody(buf.Bytes())
}
}
func Unmarshal(r *aws.Request) {
if t := rest.PayloadType(r.Data); t == "structure" || t == "" {
defer r.HTTPResponse.Body.Close()
decoder := xml.NewDecoder(r.HTTPResponse.Body)
err := xmlutil.UnmarshalXML(r.Data, decoder, "")
if err != nil {
r.Error = err
return
}
}
}
func UnmarshalMeta(r *aws.Request) {
rest.Unmarshal(r)
}
func UnmarshalError(r *aws.Request) {
query.UnmarshalError(r)
}

1171
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/restxml/unmarshal_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

262
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/xml/xmlutil/build.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,262 @@
package xmlutil
import (
"encoding/base64"
"encoding/xml"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"time"
)
func BuildXML(params interface{}, e *xml.Encoder) error {
b := xmlBuilder{encoder: e, namespaces: map[string]string{}}
root := NewXMLElement(xml.Name{})
if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil {
return err
}
for _, c := range root.Children {
for _, v := range c {
return StructToXML(e, v, false)
}
}
return nil
}
func elemOf(value reflect.Value) reflect.Value {
for value.Kind() == reflect.Ptr {
value = value.Elem()
}
return value
}
type xmlBuilder struct {
encoder *xml.Encoder
namespaces map[string]string
}
func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
value = elemOf(value)
if !value.IsValid() { // no need to handle zero values
return nil
} else if tag.Get("location") != "" { // don't handle non-body location values
return nil
}
t := tag.Get("type")
if t == "" {
switch value.Kind() {
case reflect.Struct:
t = "structure"
case reflect.Slice:
t = "list"
case reflect.Map:
t = "map"
}
}
switch t {
case "structure":
if field, ok := value.Type().FieldByName("SDKShapeTraits"); ok {
tag = tag + reflect.StructTag(" ") + field.Tag
}
return b.buildStruct(value, current, tag)
case "list":
return b.buildList(value, current, tag)
case "map":
return b.buildMap(value, current, tag)
default:
return b.buildScalar(value, current, tag)
}
}
func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
if !value.IsValid() {
return nil
}
fieldAdded := false
// unwrap payloads
if payload := tag.Get("payload"); payload != "" {
field, _ := value.Type().FieldByName(payload)
tag = field.Tag
value = elemOf(value.FieldByName(payload))
if !value.IsValid() {
return nil
}
}
child := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
// there is an xmlNamespace associated with this struct
if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" {
ns := xml.Attr{
Name: xml.Name{Local: "xmlns"},
Value: uri,
}
if prefix != "" {
b.namespaces[prefix] = uri // register the namespace
ns.Name.Local = "xmlns:" + prefix
}
child.Attr = append(child.Attr, ns)
}
t := value.Type()
for i := 0; i < value.NumField(); i++ {
if c := t.Field(i).Name[0:1]; strings.ToLower(c) == c {
continue // ignore unexported fields
}
member := elemOf(value.Field(i))
field := t.Field(i)
mTag := field.Tag
if mTag.Get("location") != "" { // skip non-body members
continue
}
memberName := mTag.Get("locationName")
if memberName == "" {
memberName = field.Name
mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`)
}
if err := b.buildValue(member, child, mTag); err != nil {
return err
}
fieldAdded = true
}
if fieldAdded { // only append this child if we have one ore more valid members
current.AddChild(child)
}
return nil
}
func (b *xmlBuilder) buildList(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
if value.IsNil() { // don't build omitted lists
return nil
}
// check for unflattened list member
flattened := tag.Get("flattened") != ""
xname := xml.Name{Local: tag.Get("locationName")}
if flattened {
for i := 0; i < value.Len(); i++ {
child := NewXMLElement(xname)
current.AddChild(child)
if err := b.buildValue(value.Index(i), child, ""); err != nil {
return err
}
}
} else {
list := NewXMLElement(xname)
current.AddChild(list)
for i := 0; i < value.Len(); i++ {
iname := tag.Get("locationNameList")
if iname == "" {
iname = "member"
}
child := NewXMLElement(xml.Name{Local: iname})
list.AddChild(child)
if err := b.buildValue(value.Index(i), child, ""); err != nil {
return err
}
}
}
return nil
}
func (b *xmlBuilder) buildMap(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
if value.IsNil() { // don't build omitted maps
return nil
}
maproot := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
current.AddChild(maproot)
current = maproot
kname, vname := "key", "value"
if n := tag.Get("locationNameKey"); n != "" {
kname = n
}
if n := tag.Get("locationNameValue"); n != "" {
vname = n
}
// sorting is not required for compliance, but it makes testing easier
keys := make([]string, value.Len())
for i, k := range value.MapKeys() {
keys[i] = k.String()
}
sort.Strings(keys)
for _, k := range keys {
v := value.MapIndex(reflect.ValueOf(k))
fmt.Println(k, v.Interface())
mapcur := current
if tag.Get("flattened") == "" { // add "entry" tag to non-flat maps
child := NewXMLElement(xml.Name{Local: "entry"})
mapcur.AddChild(child)
mapcur = child
}
kchild := NewXMLElement(xml.Name{Local: kname})
kchild.Text = k
vchild := NewXMLElement(xml.Name{Local: vname})
mapcur.AddChild(kchild)
mapcur.AddChild(vchild)
if err := b.buildValue(v, vchild, ""); err != nil {
return err
}
}
return nil
}
func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
var str string
switch converted := value.Interface().(type) {
case string:
str = converted
case []byte:
str = base64.StdEncoding.EncodeToString(converted)
case bool:
str = strconv.FormatBool(converted)
case int64:
str = strconv.FormatInt(converted, 10)
case int:
str = strconv.Itoa(converted)
case float64:
str = strconv.FormatFloat(converted, 'f', -1, 64)
case float32:
str = strconv.FormatFloat(float64(converted), 'f', -1, 32)
case time.Time:
const ISO8601UTC = "2006-01-02T15:04:05Z"
str = converted.UTC().Format(ISO8601UTC)
default:
return fmt.Errorf("unsupported value for param %s: %v (%s)",
tag.Get("locationName"), value.Interface(), value.Type().Name())
}
xname := xml.Name{Local: tag.Get("locationName")}
if tag.Get("xmlAttribute") != "" { // put into current node's attribute list
attr := xml.Attr{Name: xname, Value: str}
current.Attr = append(current.Attr, attr)
} else { // regular text node
current.AddChild(&XMLNode{Name: xname, Text: str})
}
return nil
}

251
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/xml/xmlutil/unmarshal.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,251 @@
package xmlutil
import (
"encoding/base64"
"encoding/xml"
"fmt"
"io"
"reflect"
"strconv"
"strings"
"time"
)
func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error {
n, _ := XMLToStruct(d, nil)
if n.Children != nil {
for _, root := range n.Children {
for _, c := range root {
if wrappedChild, ok := c.Children[wrapper]; ok {
c = wrappedChild[0] // pull out wrapped element
}
err := parse(reflect.ValueOf(v), c, "")
if err != nil {
if err == io.EOF {
return nil
}
return err
}
}
}
return nil
}
return nil
}
func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
rtype := r.Type()
if rtype.Kind() == reflect.Ptr {
rtype = rtype.Elem() // check kind of actual element type
}
t := tag.Get("type")
if t == "" {
switch rtype.Kind() {
case reflect.Struct:
t = "structure"
case reflect.Slice:
t = "list"
case reflect.Map:
t = "map"
}
}
switch t {
case "structure":
if field, ok := rtype.FieldByName("SDKShapeTraits"); ok {
tag = field.Tag
}
return parseStruct(r, node, tag)
case "list":
return parseList(r, node, tag)
case "map":
return parseMap(r, node, tag)
default:
return parseScalar(r, node, tag)
}
}
func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
t := r.Type()
if r.Kind() == reflect.Ptr {
if r.IsNil() { // create the structure if it's nil
s := reflect.New(r.Type().Elem())
r.Set(s)
r = s
}
r = r.Elem()
t = t.Elem()
}
// unwrap any payloads
if payload := tag.Get("payload"); payload != "" {
field, _ := t.FieldByName(payload)
return parseStruct(r.FieldByName(payload), node, field.Tag)
}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if c := field.Name[0:1]; strings.ToLower(c) == c {
continue // ignore unexported fields
}
// figure out what this field is called
name := field.Name
if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" {
name = field.Tag.Get("locationNameList")
} else if locName := field.Tag.Get("locationName"); locName != "" {
name = locName
}
// try to find the field by name in elements
elems := node.Children[name]
if elems == nil { // try to find the field in attributes
for _, a := range node.Attr {
if name == a.Name.Local {
// turn this into a text node for de-serializing
elems = []*XMLNode{&XMLNode{Text: a.Value}}
}
}
}
member := r.FieldByName(field.Name)
for _, elem := range elems {
err := parse(member, elem, field.Tag)
if err != nil {
return err
}
}
}
return nil
}
func parseList(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
t := r.Type()
if tag.Get("flattened") == "" { // look at all item entries
mname := "member"
if name := tag.Get("locationNameList"); name != "" {
mname = name
}
if Children, ok := node.Children[mname]; ok {
if r.IsNil() {
r.Set(reflect.MakeSlice(t, len(Children), len(Children)))
}
for i, c := range Children {
err := parse(r.Index(i), c, "")
if err != nil {
return err
}
}
}
} else { // flattened list means this is a single element
if r.IsNil() {
r.Set(reflect.MakeSlice(t, 0, 0))
}
childR := reflect.Zero(t.Elem())
r.Set(reflect.Append(r, childR))
err := parse(r.Index(r.Len()-1), node, "")
if err != nil {
return err
}
}
return nil
}
func parseMap(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
t := r.Type()
if r.Kind() == reflect.Ptr {
t = t.Elem()
if r.IsNil() {
r.Set(reflect.New(t))
r.Elem().Set(reflect.MakeMap(t))
}
r = r.Elem()
}
if tag.Get("flattened") == "" { // look at all child entries
for _, entry := range node.Children["entry"] {
parseMapEntry(r, entry, tag)
}
} else { // this element is itself an entry
parseMapEntry(r, node, tag)
}
return nil
}
func parseMapEntry(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
kname, vname := "key", "value"
if n := tag.Get("locationNameKey"); n != "" {
kname = n
}
if n := tag.Get("locationNameValue"); n != "" {
vname = n
}
keys, ok := node.Children[kname]
values := node.Children[vname]
if ok {
for i, key := range keys {
keyR := reflect.ValueOf(key.Text)
value := values[i]
valueR := reflect.New(r.Type().Elem()).Elem()
parse(valueR, value, "")
r.SetMapIndex(keyR, valueR)
}
}
return nil
}
func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
switch r.Interface().(type) {
case *string:
r.Set(reflect.ValueOf(&node.Text))
return nil
case []byte:
b, err := base64.StdEncoding.DecodeString(node.Text)
if err != nil {
return err
}
r.Set(reflect.ValueOf(b))
case *bool:
v, err := strconv.ParseBool(node.Text)
if err != nil {
return err
}
r.Set(reflect.ValueOf(&v))
case *int64:
v, err := strconv.ParseInt(node.Text, 10, 64)
if err != nil {
return err
}
r.Set(reflect.ValueOf(&v))
case *float64:
v, err := strconv.ParseFloat(node.Text, 64)
if err != nil {
return err
}
r.Set(reflect.ValueOf(&v))
case *time.Time:
const ISO8601UTC = "2006-01-02T15:04:05Z"
t, err := time.Parse(ISO8601UTC, node.Text)
if err != nil {
return err
} else {
r.Set(reflect.ValueOf(&t))
}
default:
return fmt.Errorf("unsupported value: %v (%s)", r.Interface(), r.Type())
}
return nil
}

100
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/xml/xmlutil/xml_to_struct.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,100 @@
package xmlutil
import (
"encoding/xml"
"io"
"sort"
)
type XMLNode struct {
Name xml.Name `json:",omitempty"`
Children map[string][]*XMLNode `json:",omitempty"`
Text string `json:",omitempty"`
Attr []xml.Attr `json:",omitempty"`
}
func NewXMLElement(name xml.Name) *XMLNode {
return &XMLNode{
Name: name,
Children: map[string][]*XMLNode{},
Attr: []xml.Attr{},
}
}
func (n *XMLNode) AddChild(child *XMLNode) {
if _, ok := n.Children[child.Name.Local]; !ok {
n.Children[child.Name.Local] = []*XMLNode{}
}
n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child)
}
func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
out := &XMLNode{}
for {
tok, err := d.Token()
if tok == nil || err == io.EOF {
break
}
if err != nil {
return out, err
}
switch typed := tok.(type) {
case xml.CharData:
out.Text = string(typed.Copy())
case xml.StartElement:
el := typed.Copy()
out.Attr = el.Attr
if out.Children == nil {
out.Children = map[string][]*XMLNode{}
}
name := typed.Name.Local
slice := out.Children[name]
if slice == nil {
slice = []*XMLNode{}
}
node, e := XMLToStruct(d, &el)
if e != nil {
return out, e
}
node.Name = typed.Name
slice = append(slice, node)
out.Children[name] = slice
case xml.EndElement:
if s != nil && s.Name.Local == typed.Name.Local { // matching end token
return out, nil
}
}
}
return out, nil
}
func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})
if node.Text != "" {
e.EncodeToken(xml.CharData([]byte(node.Text)))
} else if sorted {
sortedNames := []string{}
for k, _ := range node.Children {
sortedNames = append(sortedNames, k)
}
sort.Strings(sortedNames)
for _, k := range sortedNames {
for _, v := range node.Children[k] {
StructToXML(e, v, sorted)
}
}
} else {
for _, c := range node.Children {
for _, v := range c {
StructToXML(e, v, sorted)
}
}
}
e.EncodeToken(xml.EndElement{Name: node.Name})
return e.Flush()
}

296
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,296 @@
package v4
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
)
const (
authHeaderPrefix = "AWS4-HMAC-SHA256"
timeFormat = "20060102T150405Z"
shortTimeFormat = "20060102"
)
var ignoredHeaders = map[string]bool{
"Authorization": true,
"Content-Type": true,
"Content-Length": true,
"User-Agent": true,
}
type signer struct {
Request *http.Request
Time time.Time
ExpireTime time.Duration
ServiceName string
Region string
AccessKeyID string
SecretAccessKey string
SessionToken string
Query url.Values
Body io.ReadSeeker
Debug uint
Logger io.Writer
isPresign bool
formattedTime string
formattedShortTime string
signedHeaders string
canonicalHeaders string
canonicalString string
credentialString string
stringToSign string
signature string
authorization string
}
// Sign requests with signature version 4.
func Sign(req *aws.Request) {
creds, err := req.Service.Config.Credentials.Credentials()
if err != nil {
req.Error = err
return
}
s := signer{
Request: req.HTTPRequest,
Time: req.Time,
ExpireTime: req.ExpireTime,
Query: req.HTTPRequest.URL.Query(),
Body: req.Body,
ServiceName: req.Service.ServiceName,
Region: req.Service.Config.Region,
AccessKeyID: creds.AccessKeyID,
SecretAccessKey: creds.SecretAccessKey,
SessionToken: creds.SessionToken,
Debug: req.Service.Config.LogLevel,
Logger: req.Service.Config.Logger,
}
s.sign()
return
}
func (v4 *signer) sign() {
if v4.ExpireTime != 0 {
v4.isPresign = true
}
if v4.isPresign {
v4.Query.Set("X-Amz-Algorithm", authHeaderPrefix)
if v4.SessionToken != "" {
v4.Query.Set("X-Amz-Security-Token", v4.SessionToken)
} else {
v4.Query.Del("X-Amz-Security-Token")
}
} else if v4.SessionToken != "" {
v4.Request.Header.Set("X-Amz-Security-Token", v4.SessionToken)
}
v4.build()
if v4.Debug > 0 {
out := v4.Logger
fmt.Fprintf(out, "---[ CANONICAL STRING ]-----------------------------\n")
fmt.Fprintln(out, v4.canonicalString)
fmt.Fprintf(out, "---[ STRING TO SIGN ]--------------------------------\n")
fmt.Fprintln(out, v4.stringToSign)
fmt.Fprintf(out, "---[ SIGNED URL ]--------------------------------\n")
fmt.Fprintln(out, v4.Request.URL)
fmt.Fprintf(out, "-----------------------------------------------------\n")
}
}
func (v4 *signer) build() {
v4.buildTime() // no depends
v4.buildCredentialString() // no depends
if v4.isPresign {
v4.buildQuery() // no depends
}
v4.buildCanonicalHeaders() // depends on cred string
v4.buildCanonicalString() // depends on canon headers / signed headers
v4.buildStringToSign() // depends on canon string
v4.buildSignature() // depends on string to sign
if v4.isPresign {
v4.Request.URL.RawQuery += "&X-Amz-Signature=" + v4.signature
} else {
parts := []string{
authHeaderPrefix + " Credential=" + v4.AccessKeyID + "/" + v4.credentialString,
"SignedHeaders=" + v4.signedHeaders,
"Signature=" + v4.signature,
}
v4.Request.Header.Set("Authorization", strings.Join(parts, ", "))
}
}
func (v4 *signer) buildTime() {
v4.formattedTime = v4.Time.UTC().Format(timeFormat)
v4.formattedShortTime = v4.Time.UTC().Format(shortTimeFormat)
if v4.isPresign {
duration := int64(v4.ExpireTime / time.Second)
v4.Query.Set("X-Amz-Date", v4.formattedTime)
v4.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10))
} else {
v4.Request.Header.Set("X-Amz-Date", v4.formattedTime)
}
}
func (v4 *signer) buildCredentialString() {
v4.credentialString = strings.Join([]string{
v4.formattedShortTime,
v4.Region,
v4.ServiceName,
"aws4_request",
}, "/")
if v4.isPresign {
v4.Query.Set("X-Amz-Credential", v4.AccessKeyID+"/"+v4.credentialString)
}
}
func (v4 *signer) buildQuery() {
for k, h := range v4.Request.Header {
if strings.HasPrefix(http.CanonicalHeaderKey(k), "X-Amz-") {
continue // never hoist x-amz-* headers, they must be signed
}
if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
continue // never hoist ignored headers
}
v4.Request.Header.Del(k)
v4.Query.Del(k)
for _, v := range h {
v4.Query.Add(k, v)
}
}
}
func (v4 *signer) buildCanonicalHeaders() {
headers := make([]string, 0)
headers = append(headers, "host")
for k, _ := range v4.Request.Header {
if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
continue // ignored header
}
headers = append(headers, strings.ToLower(k))
}
sort.Strings(headers)
v4.signedHeaders = strings.Join(headers, ";")
if v4.isPresign {
v4.Query.Set("X-Amz-SignedHeaders", v4.signedHeaders)
}
headerValues := make([]string, len(headers))
for i, k := range headers {
if k == "host" {
headerValues[i] = "host:" + v4.Request.URL.Host
} else {
headerValues[i] = k + ":" +
strings.Join(v4.Request.Header[http.CanonicalHeaderKey(k)], ",")
}
}
v4.canonicalHeaders = strings.Join(headerValues, "\n")
}
func (v4 *signer) buildCanonicalString() {
v4.Request.URL.RawQuery = v4.Query.Encode()
uri := v4.Request.URL.Opaque
if uri != "" {
uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/")
} else {
uri = v4.Request.URL.Path
}
if uri == "" {
uri = "/"
}
v4.canonicalString = strings.Join([]string{
v4.Request.Method,
uri,
v4.Request.URL.RawQuery,
v4.canonicalHeaders + "\n",
v4.signedHeaders,
v4.bodyDigest(),
}, "\n")
}
func (v4 *signer) buildStringToSign() {
v4.stringToSign = strings.Join([]string{
authHeaderPrefix,
v4.formattedTime,
v4.credentialString,
hex.EncodeToString(makeSha256([]byte(v4.canonicalString))),
}, "\n")
}
func (v4 *signer) buildSignature() {
secret := v4.SecretAccessKey
date := makeHmac([]byte("AWS4"+secret), []byte(v4.formattedShortTime))
region := makeHmac(date, []byte(v4.Region))
service := makeHmac(region, []byte(v4.ServiceName))
credentials := makeHmac(service, []byte("aws4_request"))
signature := makeHmac(credentials, []byte(v4.stringToSign))
v4.signature = hex.EncodeToString(signature)
}
func (v4 *signer) bodyDigest() string {
hash := v4.Request.Header.Get("X-Amz-Content-Sha256")
if hash == "" {
if v4.isPresign && v4.ServiceName == "s3" {
hash = "UNSIGNED-PAYLOAD"
} else if v4.Body == nil {
hash = hex.EncodeToString(makeSha256([]byte{}))
} else {
hash = hex.EncodeToString(makeSha256Reader(v4.Body))
}
v4.Request.Header.Add("X-Amz-Content-Sha256", hash)
}
return hash
}
func makeHmac(key []byte, data []byte) []byte {
hash := hmac.New(sha256.New, key)
hash.Write(data)
return hash.Sum(nil)
}
func makeSha256(data []byte) []byte {
hash := sha256.New()
hash.Write(data)
return hash.Sum(nil)
}
func makeSha256Reader(reader io.ReadSeeker) []byte {
packet := make([]byte, 4096)
hash := sha256.New()
reader.Seek(0, 0)
for {
n, err := reader.Read(packet)
if n > 0 {
hash.Write(packet[0:n])
}
if err == io.EOF || n == 0 {
break
}
}
reader.Seek(0, 0)
return hash.Sum(nil)
}

89
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,89 @@
package v4
import (
"net/http"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func buildSigner(serviceName string, region string, signTime time.Time, expireTime time.Duration, body string) signer {
endpoint := "https://" + serviceName + "." + region + ".amazonaws.com"
reader := strings.NewReader(body)
req, _ := http.NewRequest("POST", endpoint, reader)
req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()"
req.Header.Add("X-Amz-Target", "prefix.Operation")
req.Header.Add("Content-Type", "application/x-amz-json-1.0")
req.Header.Add("Content-Length", string(len(body)))
req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* ()")
return signer{
Request: req,
Time: signTime,
ExpireTime: expireTime,
Query: req.URL.Query(),
Body: reader,
ServiceName: serviceName,
Region: region,
AccessKeyID: "AKID",
SecretAccessKey: "SECRET",
SessionToken: "SESSION",
}
}
func removeWS(text string) string {
text = strings.Replace(text, " ", "", -1)
text = strings.Replace(text, "\n", "", -1)
text = strings.Replace(text, "\t", "", -1)
return text
}
func assertEqual(t *testing.T, expected, given string) {
if removeWS(expected) != removeWS(given) {
t.Errorf("\nExpected: %s\nGiven: %s", expected, given)
}
}
func TestPresignRequest(t *testing.T) {
signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 300*time.Second, "{}")
signer.sign()
expectedDate := "19700101T000000Z"
expectedHeaders := "host;x-amz-meta-other-header;x-amz-target"
expectedSig := "41c18d68f9191079dfeead4e3f034328f89d86c79f8e9d51dd48bb70eaf623fc"
expectedCred := "AKID/19700101/us-east-1/dynamodb/aws4_request"
q := signer.Request.URL.Query()
assert.Equal(t, expectedSig, q.Get("X-Amz-Signature"))
assert.Equal(t, expectedCred, q.Get("X-Amz-Credential"))
assert.Equal(t, expectedHeaders, q.Get("X-Amz-SignedHeaders"))
assert.Equal(t, expectedDate, q.Get("X-Amz-Date"))
}
func TestSignRequest(t *testing.T) {
signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 0, "{}")
signer.sign()
expectedDate := "19700101T000000Z"
expectedSig := "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/dynamodb/aws4_request, SignedHeaders=host;x-amz-date;x-amz-meta-other-header;x-amz-security-token;x-amz-target, Signature=0196959cabd964bd10c05217b40ed151882dd394190438bab0c658dafdbff7a1"
q := signer.Request.Header
assert.Equal(t, expectedSig, q.Get("Authorization"))
assert.Equal(t, expectedDate, q.Get("X-Amz-Date"))
}
func BenchmarkPresignRequest(b *testing.B) {
signer := buildSigner("dynamodb", "us-east-1", time.Now(), 300*time.Second, "{}")
for i := 0; i < b.N; i++ {
signer.sign()
}
}
func BenchmarkSignRequest(b *testing.B) {
signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "{}")
for i := 0; i < b.N; i++ {
signer.sign()
}
}

2738
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/service/route53/api.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

20
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/service/route53/customizations.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,20 @@
package route53
import (
"regexp"
"github.com/awslabs/aws-sdk-go/aws"
)
func init() {
initService = func(s *aws.Service) {
s.Handlers.Build.PushBack(sanitizeURL)
}
}
var reSanitizeURL = regexp.MustCompile(`\/%2F\w+%2F`)
func sanitizeURL(r *aws.Request) {
r.HTTPRequest.URL.Opaque =
reSanitizeURL.ReplaceAllString(r.HTTPRequest.URL.Opaque, "/")
}

20
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/service/route53/customizations_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,20 @@
package route53_test
import (
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/internal/util/utilassert"
"github.com/awslabs/aws-sdk-go/service/route53"
)
func TestBuildCorrectURI(t *testing.T) {
svc := route53.New(nil)
req, _ := svc.GetHostedZoneRequest(&route53.GetHostedZoneInput{
ID: aws.String("/hostedzone/ABCDEFG"),
})
req.Build()
utilassert.Match(t, `\/hostedzone\/ABCDEFG$`, req.HTTPRequest.URL.String())
}

714
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/service/route53/examples_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,714 @@
package route53_test
import (
"bytes"
"fmt"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awsutil"
"github.com/awslabs/aws-sdk-go/service/route53"
)
var _ time.Duration
var _ bytes.Buffer
func ExampleRoute53_AssociateVPCWithHostedZone() {
svc := route53.New(nil)
params := &route53.AssociateVPCWithHostedZoneInput{
HostedZoneID: aws.String("ResourceId"), // Required
VPC: &route53.VPC{ // Required
VPCID: aws.String("VPCId"),
VPCRegion: aws.String("VPCRegion"),
},
Comment: aws.String("AssociateVPCComment"),
}
resp, err := svc.AssociateVPCWithHostedZone(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ChangeResourceRecordSets() {
svc := route53.New(nil)
params := &route53.ChangeResourceRecordSetsInput{
ChangeBatch: &route53.ChangeBatch{ // Required
Changes: []*route53.Change{ // Required
&route53.Change{ // Required
Action: aws.String("ChangeAction"), // Required
ResourceRecordSet: &route53.ResourceRecordSet{ // Required
Name: aws.String("DNSName"), // Required
Type: aws.String("RRType"), // Required
AliasTarget: &route53.AliasTarget{
DNSName: aws.String("DNSName"), // Required
EvaluateTargetHealth: aws.Boolean(true), // Required
HostedZoneID: aws.String("ResourceId"), // Required
},
Failover: aws.String("ResourceRecordSetFailover"),
GeoLocation: &route53.GeoLocation{
ContinentCode: aws.String("GeoLocationContinentCode"),
CountryCode: aws.String("GeoLocationCountryCode"),
SubdivisionCode: aws.String("GeoLocationSubdivisionCode"),
},
HealthCheckID: aws.String("HealthCheckId"),
Region: aws.String("ResourceRecordSetRegion"),
ResourceRecords: []*route53.ResourceRecord{
&route53.ResourceRecord{ // Required
Value: aws.String("RData"), // Required
},
// More values...
},
SetIdentifier: aws.String("ResourceRecordSetIdentifier"),
TTL: aws.Long(1),
Weight: aws.Long(1),
},
},
// More values...
},
Comment: aws.String("ResourceDescription"),
},
HostedZoneID: aws.String("ResourceId"), // Required
}
resp, err := svc.ChangeResourceRecordSets(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ChangeTagsForResource() {
svc := route53.New(nil)
params := &route53.ChangeTagsForResourceInput{
ResourceID: aws.String("TagResourceId"), // Required
ResourceType: aws.String("TagResourceType"), // Required
AddTags: []*route53.Tag{
&route53.Tag{ // Required
Key: aws.String("TagKey"),
Value: aws.String("TagValue"),
},
// More values...
},
RemoveTagKeys: []*string{
aws.String("TagKey"), // Required
// More values...
},
}
resp, err := svc.ChangeTagsForResource(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_CreateHealthCheck() {
svc := route53.New(nil)
params := &route53.CreateHealthCheckInput{
CallerReference: aws.String("HealthCheckNonce"), // Required
HealthCheckConfig: &route53.HealthCheckConfig{ // Required
Type: aws.String("HealthCheckType"), // Required
FailureThreshold: aws.Long(1),
FullyQualifiedDomainName: aws.String("FullyQualifiedDomainName"),
IPAddress: aws.String("IPAddress"),
Port: aws.Long(1),
RequestInterval: aws.Long(1),
ResourcePath: aws.String("ResourcePath"),
SearchString: aws.String("SearchString"),
},
}
resp, err := svc.CreateHealthCheck(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_CreateHostedZone() {
svc := route53.New(nil)
params := &route53.CreateHostedZoneInput{
CallerReference: aws.String("Nonce"), // Required
Name: aws.String("DNSName"), // Required
DelegationSetID: aws.String("ResourceId"),
HostedZoneConfig: &route53.HostedZoneConfig{
Comment: aws.String("ResourceDescription"),
PrivateZone: aws.Boolean(true),
},
VPC: &route53.VPC{
VPCID: aws.String("VPCId"),
VPCRegion: aws.String("VPCRegion"),
},
}
resp, err := svc.CreateHostedZone(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_CreateReusableDelegationSet() {
svc := route53.New(nil)
params := &route53.CreateReusableDelegationSetInput{
CallerReference: aws.String("Nonce"), // Required
HostedZoneID: aws.String("ResourceId"),
}
resp, err := svc.CreateReusableDelegationSet(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_DeleteHealthCheck() {
svc := route53.New(nil)
params := &route53.DeleteHealthCheckInput{
HealthCheckID: aws.String("HealthCheckId"), // Required
}
resp, err := svc.DeleteHealthCheck(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_DeleteHostedZone() {
svc := route53.New(nil)
params := &route53.DeleteHostedZoneInput{
ID: aws.String("ResourceId"), // Required
}
resp, err := svc.DeleteHostedZone(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_DeleteReusableDelegationSet() {
svc := route53.New(nil)
params := &route53.DeleteReusableDelegationSetInput{
ID: aws.String("ResourceId"), // Required
}
resp, err := svc.DeleteReusableDelegationSet(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_DisassociateVPCFromHostedZone() {
svc := route53.New(nil)
params := &route53.DisassociateVPCFromHostedZoneInput{
HostedZoneID: aws.String("ResourceId"), // Required
VPC: &route53.VPC{ // Required
VPCID: aws.String("VPCId"),
VPCRegion: aws.String("VPCRegion"),
},
Comment: aws.String("DisassociateVPCComment"),
}
resp, err := svc.DisassociateVPCFromHostedZone(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetChange() {
svc := route53.New(nil)
params := &route53.GetChangeInput{
ID: aws.String("ResourceId"), // Required
}
resp, err := svc.GetChange(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetCheckerIPRanges() {
svc := route53.New(nil)
var params *route53.GetCheckerIPRangesInput
resp, err := svc.GetCheckerIPRanges(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetGeoLocation() {
svc := route53.New(nil)
params := &route53.GetGeoLocationInput{
ContinentCode: aws.String("GeoLocationContinentCode"),
CountryCode: aws.String("GeoLocationCountryCode"),
SubdivisionCode: aws.String("GeoLocationSubdivisionCode"),
}
resp, err := svc.GetGeoLocation(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetHealthCheck() {
svc := route53.New(nil)
params := &route53.GetHealthCheckInput{
HealthCheckID: aws.String("HealthCheckId"), // Required
}
resp, err := svc.GetHealthCheck(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetHealthCheckCount() {
svc := route53.New(nil)
var params *route53.GetHealthCheckCountInput
resp, err := svc.GetHealthCheckCount(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetHealthCheckLastFailureReason() {
svc := route53.New(nil)
params := &route53.GetHealthCheckLastFailureReasonInput{
HealthCheckID: aws.String("HealthCheckId"), // Required
}
resp, err := svc.GetHealthCheckLastFailureReason(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetHealthCheckStatus() {
svc := route53.New(nil)
params := &route53.GetHealthCheckStatusInput{
HealthCheckID: aws.String("HealthCheckId"), // Required
}
resp, err := svc.GetHealthCheckStatus(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetHostedZone() {
svc := route53.New(nil)
params := &route53.GetHostedZoneInput{
ID: aws.String("ResourceId"), // Required
}
resp, err := svc.GetHostedZone(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetHostedZoneCount() {
svc := route53.New(nil)
var params *route53.GetHostedZoneCountInput
resp, err := svc.GetHostedZoneCount(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_GetReusableDelegationSet() {
svc := route53.New(nil)
params := &route53.GetReusableDelegationSetInput{
ID: aws.String("ResourceId"), // Required
}
resp, err := svc.GetReusableDelegationSet(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListGeoLocations() {
svc := route53.New(nil)
params := &route53.ListGeoLocationsInput{
MaxItems: aws.String("PageMaxItems"),
StartContinentCode: aws.String("GeoLocationContinentCode"),
StartCountryCode: aws.String("GeoLocationCountryCode"),
StartSubdivisionCode: aws.String("GeoLocationSubdivisionCode"),
}
resp, err := svc.ListGeoLocations(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListHealthChecks() {
svc := route53.New(nil)
params := &route53.ListHealthChecksInput{
Marker: aws.String("PageMarker"),
MaxItems: aws.String("PageMaxItems"),
}
resp, err := svc.ListHealthChecks(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListHostedZones() {
svc := route53.New(nil)
params := &route53.ListHostedZonesInput{
DelegationSetID: aws.String("ResourceId"),
Marker: aws.String("PageMarker"),
MaxItems: aws.String("PageMaxItems"),
}
resp, err := svc.ListHostedZones(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListHostedZonesByName() {
svc := route53.New(nil)
params := &route53.ListHostedZonesByNameInput{
DNSName: aws.String("DNSName"),
HostedZoneID: aws.String("ResourceId"),
MaxItems: aws.String("PageMaxItems"),
}
resp, err := svc.ListHostedZonesByName(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListResourceRecordSets() {
svc := route53.New(nil)
params := &route53.ListResourceRecordSetsInput{
HostedZoneID: aws.String("ResourceId"), // Required
MaxItems: aws.String("PageMaxItems"),
StartRecordIdentifier: aws.String("ResourceRecordSetIdentifier"),
StartRecordName: aws.String("DNSName"),
StartRecordType: aws.String("RRType"),
}
resp, err := svc.ListResourceRecordSets(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListReusableDelegationSets() {
svc := route53.New(nil)
params := &route53.ListReusableDelegationSetsInput{
Marker: aws.String("PageMarker"),
MaxItems: aws.String("PageMaxItems"),
}
resp, err := svc.ListReusableDelegationSets(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListTagsForResource() {
svc := route53.New(nil)
params := &route53.ListTagsForResourceInput{
ResourceID: aws.String("TagResourceId"), // Required
ResourceType: aws.String("TagResourceType"), // Required
}
resp, err := svc.ListTagsForResource(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_ListTagsForResources() {
svc := route53.New(nil)
params := &route53.ListTagsForResourcesInput{
ResourceIDs: []*string{ // Required
aws.String("TagResourceId"), // Required
// More values...
},
ResourceType: aws.String("TagResourceType"), // Required
}
resp, err := svc.ListTagsForResources(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_UpdateHealthCheck() {
svc := route53.New(nil)
params := &route53.UpdateHealthCheckInput{
HealthCheckID: aws.String("HealthCheckId"), // Required
FailureThreshold: aws.Long(1),
FullyQualifiedDomainName: aws.String("FullyQualifiedDomainName"),
HealthCheckVersion: aws.Long(1),
IPAddress: aws.String("IPAddress"),
Port: aws.Long(1),
ResourcePath: aws.String("ResourcePath"),
SearchString: aws.String("SearchString"),
}
resp, err := svc.UpdateHealthCheck(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}
func ExampleRoute53_UpdateHostedZoneComment() {
svc := route53.New(nil)
params := &route53.UpdateHostedZoneCommentInput{
ID: aws.String("ResourceId"), // Required
Comment: aws.String("ResourceDescription"),
}
resp, err := svc.UpdateHostedZoneComment(params)
if awserr := aws.Error(err); awserr != nil {
// A service error occurred.
fmt.Println("Error:", awserr.Code, awserr.Message)
} else if err != nil {
// A non-service error occurred.
panic(err)
}
// Pretty-print the response data.
fmt.Println(awsutil.StringValue(resp))
}

59
Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/service/route53/service.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,59 @@
package route53
import (
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/internal/protocol/restxml"
"github.com/awslabs/aws-sdk-go/internal/signer/v4"
)
// Route53 is a client for Route 53.
type Route53 struct {
*aws.Service
}
// Used for custom service initialization logic
var initService func(*aws.Service)
// Used for custom request initialization logic
var initRequest func(*aws.Request)
// New returns a new Route53 client.
func New(config *aws.Config) *Route53 {
if config == nil {
config = &aws.Config{}
}
service := &aws.Service{
Config: aws.DefaultConfig.Merge(config),
ServiceName: "route53",
APIVersion: "2013-04-01",
}
service.Initialize()
// Handlers
service.Handlers.Sign.PushBack(v4.Sign)
service.Handlers.Build.PushBack(restxml.Build)
service.Handlers.Unmarshal.PushBack(restxml.Unmarshal)
service.Handlers.UnmarshalMeta.PushBack(restxml.UnmarshalMeta)
service.Handlers.UnmarshalError.PushBack(restxml.UnmarshalError)
// Run custom service initialization if present
if initService != nil {
initService(service)
}
return &Route53{service}
}
// newRequest creates a new request for a Route53 operation and runs any
// custom request initialization.
func (c *Route53) newRequest(op *aws.Operation, params, data interface{}) *aws.Request {
req := aws.NewRequest(c.Service, op, params, data)
// Run custom request initialization if present
if initRequest != nil {
initRequest(req)
}
return req
}

19
Godeps/_workspace/src/github.com/braintree/manners/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,19 @@
Copyright (c) 2014 Braintree, a division of PayPal, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

34
Godeps/_workspace/src/github.com/braintree/manners/helper_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,34 @@
package manners
import (
"net/http"
"time"
)
// A response handler that blocks until it receives a signal; simulates an
// arbitrarily long web request. The "ready" channel is to prevent a race
// condition in the test where the test moves on before the server is ready
// to handle the request.
func newBlockingHandler(ready, done chan bool) *blockingHandler {
return &blockingHandler{ready, done}
}
type blockingHandler struct {
ready chan bool
done chan bool
}
func (h *blockingHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
h.ready <- true
time.Sleep(1e2)
h.done <- true
}
// A response handler that does nothing.
func newTestHandler() testHandler {
return testHandler{}
}
type testHandler struct{}
func (h testHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {}

49
Godeps/_workspace/src/github.com/braintree/manners/listener.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,49 @@
package manners
import (
"net"
"sync"
)
func NewListener(l net.Listener, s *GracefulServer) *GracefulListener {
return &GracefulListener{l, true, s, sync.RWMutex{}}
}
// A GracefulListener differs from a standard net.Listener in one way: if
// Accept() is called after it is gracefully closed, it returns a
// listenerAlreadyClosed error. The GracefulServer will ignore this
// error.
type GracefulListener struct {
net.Listener
open bool
server *GracefulServer
rw sync.RWMutex
}
func (l *GracefulListener) Accept() (net.Conn, error) {
conn, err := l.Listener.Accept()
if err != nil {
l.rw.RLock()
defer l.rw.RUnlock()
if !l.open {
err = listenerAlreadyClosed{err}
}
return nil, err
}
return conn, nil
}
func (l *GracefulListener) Close() error {
l.rw.Lock()
defer l.rw.Unlock()
if !l.open {
return nil
}
l.open = false
err := l.Listener.Close()
return err
}
type listenerAlreadyClosed struct {
error
}

83
Godeps/_workspace/src/github.com/braintree/manners/server.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,83 @@
package manners
import (
"net"
"net/http"
"sync"
)
// Creates a new GracefulServer. The server will begin shutting down when
// a value is passed to the Shutdown channel.
func NewServer() *GracefulServer {
return &GracefulServer{
Shutdown: make(chan bool),
}
}
// A GracefulServer maintains a WaitGroup that counts how many in-flight
// requests the server is handling. When it receives a shutdown signal,
// it stops accepting new requests but does not actually shut down until
// all in-flight requests terminate.
type GracefulServer struct {
Shutdown chan bool
wg sync.WaitGroup
shutdownHandler func()
InnerServer http.Server
}
// A helper function that emulates the functionality of http.ListenAndServe.
func (s *GracefulServer) ListenAndServe(addr string, handler http.Handler) error {
oldListener, err := net.Listen("tcp", addr)
if err != nil {
return err
}
listener := NewListener(oldListener, s)
err = s.Serve(listener, handler)
return err
}
// Similar to http.Serve. The listener passed must wrap a GracefulListener.
func (s *GracefulServer) Serve(listener net.Listener, handler http.Handler) error {
s.shutdownHandler = func() { listener.Close() }
s.listenForShutdown()
s.InnerServer.Handler = handler
s.InnerServer.ConnState = func(conn net.Conn, newState http.ConnState) {
switch newState {
case http.StateNew:
s.StartRoutine()
case http.StateClosed, http.StateHijacked:
s.FinishRoutine()
}
}
err := s.InnerServer.Serve(listener)
// This block is reached when the server has received a shut down command.
if err == nil {
s.wg.Wait()
return nil
} else if _, ok := err.(listenerAlreadyClosed); ok {
s.wg.Wait()
return nil
}
return err
}
// Increments the server's WaitGroup. Use this if a web request starts more
// goroutines and these goroutines are not guaranteed to finish before the
// request.
func (s *GracefulServer) StartRoutine() {
s.wg.Add(1)
}
// Decrement the server's WaitGroup. Used this to complement StartRoutine().
func (s *GracefulServer) FinishRoutine() {
s.wg.Done()
}
func (s *GracefulServer) listenForShutdown() {
go func() {
<-s.Shutdown
s.shutdownHandler()
}()
}

71
Godeps/_workspace/src/github.com/braintree/manners/server_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,71 @@
package manners
import (
"net/http"
"testing"
)
// Tests that the server allows in-flight requests to complete before shutting
// down.
func TestGracefulness(t *testing.T) {
ready := make(chan bool)
done := make(chan bool)
exited := false
handler := newBlockingHandler(ready, done)
server := NewServer()
go func() {
err := server.ListenAndServe(":7000", handler)
if err != nil {
t.Error(err)
}
exited = true
}()
go func() {
_, err := http.Get("http://localhost:7000")
if err != nil {
t.Error(err)
}
}()
// This will block until the server is inside the handler function.
<-ready
server.Shutdown <- true
<-done
if exited {
t.Fatal("The request did not complete before server exited")
} else {
// The handler is being allowed to run to completion; test passes.
}
}
// Tests that the server begins to shut down when told to and does not accept
// new requests
func TestShutdown(t *testing.T) {
handler := newTestHandler()
server := NewServer()
exited := make(chan bool)
go func() {
err := server.ListenAndServe(":7100", handler)
if err != nil {
t.Error(err)
}
exited <- true
}()
server.Shutdown <- true
<-exited
_, err := http.Get("http://localhost:7100")
if err == nil {
t.Fatal("Did not receive an error when trying to connect to server.")
}
}

8
Godeps/_workspace/src/github.com/go-gorp/gorp/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,8 @@
_test
_testmain.go
_obj
*~
*.6
6.out
gorptest.bin
tmp

23
Godeps/_workspace/src/github.com/go-gorp/gorp/.travis.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,23 @@
language: go
go:
- 1.2
- 1.3
- 1.4
- tip
services:
- mysql
- postgres
- sqlite3
before_script:
- mysql -e "CREATE DATABASE gorptest;"
- mysql -u root -e "GRANT ALL ON gorptest.* TO gorptest@localhost IDENTIFIED BY 'gorptest'"
- psql -c "CREATE DATABASE gorptest;" -U postgres
- psql -c "CREATE USER "gorptest" WITH SUPERUSER PASSWORD 'gorptest';" -U postgres
- go get github.com/lib/pq
- go get github.com/mattn/go-sqlite3
- go get github.com/ziutek/mymysql/godrv
- go get github.com/go-sql-driver/mysql
script: ./test_all.sh

22
Godeps/_workspace/src/github.com/go-gorp/gorp/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2012 James Cooper <james@bitmechanic.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

6
Godeps/_workspace/src/github.com/go-gorp/gorp/Makefile сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,6 @@
include $(GOROOT)/src/Make.inc
TARG = github.com/go-gorp/gorp
GOFILES = gorp.go dialect.go
include $(GOROOT)/src/Make.pkg

696
Godeps/_workspace/src/github.com/go-gorp/gorp/dialect.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,696 @@
package gorp
import (
"errors"
"fmt"
"reflect"
"strings"
)
// The Dialect interface encapsulates behaviors that differ across
// SQL databases. At present the Dialect is only used by CreateTables()
// but this could change in the future
type Dialect interface {
// adds a suffix to any query, usually ";"
QuerySuffix() string
// ToSqlType returns the SQL column type to use when creating a
// table of the given Go Type. maxsize can be used to switch based on
// size. For example, in MySQL []byte could map to BLOB, MEDIUMBLOB,
// or LONGBLOB depending on the maxsize
ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string
// string to append to primary key column definitions
AutoIncrStr() string
// string to bind autoincrement columns to. Empty string will
// remove reference to those columns in the INSERT statement.
AutoIncrBindValue() string
AutoIncrInsertSuffix(col *ColumnMap) string
// string to append to "create table" statement for vendor specific
// table attributes
CreateTableSuffix() string
// string to truncate tables
TruncateClause() string
// bind variable string to use when forming SQL statements
// in many dbs it is "?", but Postgres appears to use $1
//
// i is a zero based index of the bind variable in this statement
//
BindVar(i int) string
// Handles quoting of a field name to ensure that it doesn't raise any
// SQL parsing exceptions by using a reserved word as a field name.
QuoteField(field string) string
// Handles building up of a schema.database string that is compatible with
// the given dialect
//
// schema - The schema that <table> lives in
// table - The table name
QuotedTableForQuery(schema string, table string) string
// Existance clause for table creation / deletion
IfSchemaNotExists(command, schema string) string
IfTableExists(command, schema, table string) string
IfTableNotExists(command, schema, table string) string
}
// IntegerAutoIncrInserter is implemented by dialects that can perform
// inserts with automatically incremented integer primary keys. If
// the dialect can handle automatic assignment of more than just
// integers, see TargetedAutoIncrInserter.
type IntegerAutoIncrInserter interface {
InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error)
}
// TargetedAutoIncrInserter is implemented by dialects that can
// perform automatic assignment of any primary key type (i.e. strings
// for uuids, integers for serials, etc).
type TargetedAutoIncrInserter interface {
// InsertAutoIncrToTarget runs an insert operation and assigns the
// automatically generated primary key directly to the passed in
// target. The target should be a pointer to the primary key
// field of the value being inserted.
InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error
}
func standardInsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
res, err := exec.Exec(insertSql, params...)
if err != nil {
return 0, err
}
return res.LastInsertId()
}
///////////////////////////////////////////////////////
// sqlite3 //
/////////////
type SqliteDialect struct {
suffix string
}
func (d SqliteDialect) QuerySuffix() string { return ";" }
func (d SqliteDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
switch val.Kind() {
case reflect.Ptr:
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
case reflect.Bool:
return "integer"
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return "integer"
case reflect.Float64, reflect.Float32:
return "real"
case reflect.Slice:
if val.Elem().Kind() == reflect.Uint8 {
return "blob"
}
}
switch val.Name() {
case "NullInt64":
return "integer"
case "NullFloat64":
return "real"
case "NullBool":
return "integer"
case "Time":
return "datetime"
}
if maxsize < 1 {
maxsize = 255
}
return fmt.Sprintf("varchar(%d)", maxsize)
}
// Returns autoincrement
func (d SqliteDialect) AutoIncrStr() string {
return "autoincrement"
}
func (d SqliteDialect) AutoIncrBindValue() string {
return "null"
}
func (d SqliteDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
return ""
}
// Returns suffix
func (d SqliteDialect) CreateTableSuffix() string {
return d.suffix
}
// With sqlite, there technically isn't a TRUNCATE statement,
// but a DELETE FROM uses a truncate optimization:
// http://www.sqlite.org/lang_delete.html
func (d SqliteDialect) TruncateClause() string {
return "delete from"
}
// Returns "?"
func (d SqliteDialect) BindVar(i int) string {
return "?"
}
func (d SqliteDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
return standardInsertAutoIncr(exec, insertSql, params...)
}
func (d SqliteDialect) QuoteField(f string) string {
return `"` + f + `"`
}
// sqlite does not have schemas like PostgreSQL does, so just escape it like normal
func (d SqliteDialect) QuotedTableForQuery(schema string, table string) string {
return d.QuoteField(table)
}
func (d SqliteDialect) IfSchemaNotExists(command, schema string) string {
return fmt.Sprintf("%s if not exists", command)
}
func (d SqliteDialect) IfTableExists(command, schema, table string) string {
return fmt.Sprintf("%s if exists", command)
}
func (d SqliteDialect) IfTableNotExists(command, schema, table string) string {
return fmt.Sprintf("%s if not exists", command)
}
///////////////////////////////////////////////////////
// PostgreSQL //
////////////////
type PostgresDialect struct {
suffix string
}
func (d PostgresDialect) QuerySuffix() string { return ";" }
func (d PostgresDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
switch val.Kind() {
case reflect.Ptr:
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
case reflect.Bool:
return "boolean"
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32:
if isAutoIncr {
return "serial"
}
return "integer"
case reflect.Int64, reflect.Uint64:
if isAutoIncr {
return "bigserial"
}
return "bigint"
case reflect.Float64:
return "double precision"
case reflect.Float32:
return "real"
case reflect.Slice:
if val.Elem().Kind() == reflect.Uint8 {
return "bytea"
}
}
switch val.Name() {
case "NullInt64":
return "bigint"
case "NullFloat64":
return "double precision"
case "NullBool":
return "boolean"
case "Time", "NullTime":
return "timestamp with time zone"
}
if maxsize > 0 {
return fmt.Sprintf("varchar(%d)", maxsize)
} else {
return "text"
}
}
// Returns empty string
func (d PostgresDialect) AutoIncrStr() string {
return ""
}
func (d PostgresDialect) AutoIncrBindValue() string {
return "default"
}
func (d PostgresDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
return " returning " + col.ColumnName
}
// Returns suffix
func (d PostgresDialect) CreateTableSuffix() string {
return d.suffix
}
func (d PostgresDialect) TruncateClause() string {
return "truncate"
}
// Returns "$(i+1)"
func (d PostgresDialect) BindVar(i int) string {
return fmt.Sprintf("$%d", i+1)
}
func (d PostgresDialect) InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error {
rows, err := exec.query(insertSql, params...)
if err != nil {
return err
}
defer rows.Close()
if !rows.Next() {
return fmt.Errorf("No serial value returned for insert: %s Encountered error: %s", insertSql, rows.Err())
}
if err := rows.Scan(target); err != nil {
return err
}
if rows.Next() {
return fmt.Errorf("more than two serial value returned for insert: %s", insertSql)
}
return rows.Err()
}
func (d PostgresDialect) QuoteField(f string) string {
return `"` + strings.ToLower(f) + `"`
}
func (d PostgresDialect) QuotedTableForQuery(schema string, table string) string {
if strings.TrimSpace(schema) == "" {
return d.QuoteField(table)
}
return schema + "." + d.QuoteField(table)
}
func (d PostgresDialect) IfSchemaNotExists(command, schema string) string {
return fmt.Sprintf("%s if not exists", command)
}
func (d PostgresDialect) IfTableExists(command, schema, table string) string {
return fmt.Sprintf("%s if exists", command)
}
func (d PostgresDialect) IfTableNotExists(command, schema, table string) string {
return fmt.Sprintf("%s if not exists", command)
}
///////////////////////////////////////////////////////
// MySQL //
///////////
// Implementation of Dialect for MySQL databases.
type MySQLDialect struct {
// Engine is the storage engine to use "InnoDB" vs "MyISAM" for example
Engine string
// Encoding is the character encoding to use for created tables
Encoding string
}
func (d MySQLDialect) QuerySuffix() string { return ";" }
func (d MySQLDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
switch val.Kind() {
case reflect.Ptr:
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
case reflect.Bool:
return "boolean"
case reflect.Int8:
return "tinyint"
case reflect.Uint8:
return "tinyint unsigned"
case reflect.Int16:
return "smallint"
case reflect.Uint16:
return "smallint unsigned"
case reflect.Int, reflect.Int32:
return "int"
case reflect.Uint, reflect.Uint32:
return "int unsigned"
case reflect.Int64:
return "bigint"
case reflect.Uint64:
return "bigint unsigned"
case reflect.Float64, reflect.Float32:
return "double"
case reflect.Slice:
if val.Elem().Kind() == reflect.Uint8 {
return "mediumblob"
}
}
switch val.Name() {
case "NullInt64":
return "bigint"
case "NullFloat64":
return "double"
case "NullBool":
return "tinyint"
case "Time":
return "datetime"
}
if maxsize < 1 {
maxsize = 255
}
return fmt.Sprintf("varchar(%d)", maxsize)
}
// Returns auto_increment
func (d MySQLDialect) AutoIncrStr() string {
return "auto_increment"
}
func (d MySQLDialect) AutoIncrBindValue() string {
return "null"
}
func (d MySQLDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
return ""
}
// Returns engine=%s charset=%s based on values stored on struct
func (d MySQLDialect) CreateTableSuffix() string {
if d.Engine == "" || d.Encoding == "" {
msg := "gorp - undefined"
if d.Engine == "" {
msg += " MySQLDialect.Engine"
}
if d.Engine == "" && d.Encoding == "" {
msg += ","
}
if d.Encoding == "" {
msg += " MySQLDialect.Encoding"
}
msg += ". Check that your MySQLDialect was correctly initialized when declared."
panic(msg)
}
return fmt.Sprintf(" engine=%s charset=%s", d.Engine, d.Encoding)
}
func (d MySQLDialect) TruncateClause() string {
return "truncate"
}
// Returns "?"
func (d MySQLDialect) BindVar(i int) string {
return "?"
}
func (d MySQLDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
return standardInsertAutoIncr(exec, insertSql, params...)
}
func (d MySQLDialect) QuoteField(f string) string {
return "`" + f + "`"
}
func (d MySQLDialect) QuotedTableForQuery(schema string, table string) string {
if strings.TrimSpace(schema) == "" {
return d.QuoteField(table)
}
return schema + "." + d.QuoteField(table)
}
func (d MySQLDialect) IfSchemaNotExists(command, schema string) string {
return fmt.Sprintf("%s if not exists", command)
}
func (d MySQLDialect) IfTableExists(command, schema, table string) string {
return fmt.Sprintf("%s if exists", command)
}
func (d MySQLDialect) IfTableNotExists(command, schema, table string) string {
return fmt.Sprintf("%s if not exists", command)
}
///////////////////////////////////////////////////////
// Sql Server //
////////////////
// Implementation of Dialect for Microsoft SQL Server databases.
// Tested on SQL Server 2008 with driver: github.com/denisenkom/go-mssqldb
type SqlServerDialect struct {
suffix string
}
func (d SqlServerDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
switch val.Kind() {
case reflect.Ptr:
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
case reflect.Bool:
return "bit"
case reflect.Int8:
return "tinyint"
case reflect.Uint8:
return "smallint"
case reflect.Int16:
return "smallint"
case reflect.Uint16:
return "int"
case reflect.Int, reflect.Int32:
return "int"
case reflect.Uint, reflect.Uint32:
return "bigint"
case reflect.Int64:
return "bigint"
case reflect.Uint64:
return "bigint"
case reflect.Float32:
return "real"
case reflect.Float64:
return "float(53)"
case reflect.Slice:
if val.Elem().Kind() == reflect.Uint8 {
return "varbinary"
}
}
switch val.Name() {
case "NullInt64":
return "bigint"
case "NullFloat64":
return "float(53)"
case "NullBool":
return "tinyint"
case "Time":
return "datetime"
}
if maxsize < 1 {
maxsize = 255
}
return fmt.Sprintf("varchar(%d)", maxsize)
}
// Returns auto_increment
func (d SqlServerDialect) AutoIncrStr() string {
return "identity(0,1)"
}
// Empty string removes autoincrement columns from the INSERT statements.
func (d SqlServerDialect) AutoIncrBindValue() string {
return ""
}
func (d SqlServerDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
return ""
}
// Returns suffix
func (d SqlServerDialect) CreateTableSuffix() string {
return d.suffix
}
func (d SqlServerDialect) TruncateClause() string {
return "delete from"
}
// Returns "?"
func (d SqlServerDialect) BindVar(i int) string {
return "?"
}
func (d SqlServerDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
return standardInsertAutoIncr(exec, insertSql, params...)
}
func (d SqlServerDialect) QuoteField(f string) string {
return `"` + f + `"`
}
func (d SqlServerDialect) QuotedTableForQuery(schema string, table string) string {
if strings.TrimSpace(schema) == "" {
return table
}
return schema + "." + table
}
func (d SqlServerDialect) QuerySuffix() string { return ";" }
func (d SqlServerDialect) IfSchemaNotExists(command, schema string) string {
s := fmt.Sprintf("if not exists (select name from sys.schemas where name = '%s') %s", schema, command)
return s
}
func (d SqlServerDialect) IfTableExists(command, schema, table string) string {
var schema_clause string
if strings.TrimSpace(schema) != "" {
schema_clause = fmt.Sprintf("table_schema = '%s' and ", schema)
}
s := fmt.Sprintf("if exists (select * from information_schema.tables where %stable_name = '%s') %s", schema_clause, table, command)
return s
}
func (d SqlServerDialect) IfTableNotExists(command, schema, table string) string {
var schema_clause string
if strings.TrimSpace(schema) != "" {
schema_clause = fmt.Sprintf("table_schema = '%s' and ", schema)
}
s := fmt.Sprintf("if not exists (select * from information_schema.tables where %stable_name = '%s') %s", schema_clause, table, command)
return s
}
///////////////////////////////////////////////////////
// Oracle //
///////////
// Implementation of Dialect for Oracle databases.
type OracleDialect struct{}
func (d OracleDialect) QuerySuffix() string { return "" }
func (d OracleDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
switch val.Kind() {
case reflect.Ptr:
return d.ToSqlType(val.Elem(), maxsize, isAutoIncr)
case reflect.Bool:
return "boolean"
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32:
if isAutoIncr {
return "serial"
}
return "integer"
case reflect.Int64, reflect.Uint64:
if isAutoIncr {
return "bigserial"
}
return "bigint"
case reflect.Float64:
return "double precision"
case reflect.Float32:
return "real"
case reflect.Slice:
if val.Elem().Kind() == reflect.Uint8 {
return "bytea"
}
}
switch val.Name() {
case "NullInt64":
return "bigint"
case "NullFloat64":
return "double precision"
case "NullBool":
return "boolean"
case "NullTime", "Time":
return "timestamp with time zone"
}
if maxsize > 0 {
return fmt.Sprintf("varchar(%d)", maxsize)
} else {
return "text"
}
}
// Returns empty string
func (d OracleDialect) AutoIncrStr() string {
return ""
}
func (d OracleDialect) AutoIncrBindValue() string {
return "default"
}
func (d OracleDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
return " returning " + col.ColumnName
}
// Returns suffix
func (d OracleDialect) CreateTableSuffix() string {
return ""
}
func (d OracleDialect) TruncateClause() string {
return "truncate"
}
// Returns "$(i+1)"
func (d OracleDialect) BindVar(i int) string {
return fmt.Sprintf(":%d", i+1)
}
func (d OracleDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
rows, err := exec.query(insertSql, params...)
if err != nil {
return 0, err
}
defer rows.Close()
if rows.Next() {
var id int64
err := rows.Scan(&id)
return id, err
}
return 0, errors.New("No serial value returned for insert: " + insertSql + " Encountered error: " + rows.Err().Error())
}
func (d OracleDialect) QuoteField(f string) string {
return `"` + strings.ToUpper(f) + `"`
}
func (d OracleDialect) QuotedTableForQuery(schema string, table string) string {
if strings.TrimSpace(schema) == "" {
return d.QuoteField(table)
}
return schema + "." + d.QuoteField(table)
}
func (d OracleDialect) IfSchemaNotExists(command, schema string) string {
return fmt.Sprintf("%s if not exists", command)
}
func (d OracleDialect) IfTableExists(command, schema, table string) string {
return fmt.Sprintf("%s if exists", command)
}
func (d OracleDialect) IfTableNotExists(command, schema, table string) string {
return fmt.Sprintf("%s if not exists", command)
}

26
Godeps/_workspace/src/github.com/go-gorp/gorp/errors.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,26 @@
package gorp
import (
"fmt"
)
// A non-fatal error, when a select query returns columns that do not exist
// as fields in the struct it is being mapped to
type NoFieldInTypeError struct {
TypeName string
MissingColNames []string
}
func (err *NoFieldInTypeError) Error() string {
return fmt.Sprintf("gorp: No fields %+v in type %s", err.MissingColNames, err.TypeName)
}
// returns true if the error is non-fatal (ie, we shouldn't immediately return)
func NonFatalError(err error) bool {
switch err.(type) {
case *NoFieldInTypeError:
return true
default:
return false
}
}

2178
Godeps/_workspace/src/github.com/go-gorp/gorp/gorp.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

2170
Godeps/_workspace/src/github.com/go-gorp/gorp/gorp_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

22
Godeps/_workspace/src/github.com/go-gorp/gorp/test_all.sh сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,22 @@
#!/bin/sh
# on macs, you may need to:
# export GOBUILDFLAG=-ldflags -linkmode=external
set -e
export GORP_TEST_DSN=gorptest/gorptest/gorptest
export GORP_TEST_DIALECT=mysql
go test $GOBUILDFLAG .
export GORP_TEST_DSN=gorptest:gorptest@/gorptest
export GORP_TEST_DIALECT=gomysql
go test $GOBUILDFLAG .
export GORP_TEST_DSN="user=gorptest password=gorptest dbname=gorptest sslmode=disable"
export GORP_TEST_DIALECT=postgres
go test $GOBUILDFLAG .
export GORP_TEST_DSN=/tmp/gorptest.bin
export GORP_TEST_DIALECT=sqlite
go test $GOBUILDFLAG .

8
Godeps/_workspace/src/github.com/go-sql-driver/mysql/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,8 @@
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db

10
Godeps/_workspace/src/github.com/go-sql-driver/mysql/.travis.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,10 @@
sudo: false
language: go
go:
- 1.2
- 1.3
- 1.4
- tip
before_script:
- mysql -e 'create database gotest;'

42
Godeps/_workspace/src/github.com/go-sql-driver/mysql/AUTHORS сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
# This is the official list of Go-MySQL-Driver authors for copyright purposes.
# If you are submitting a patch, please add your name or the name of the
# organization which holds the copyright to this list in alphabetical order.
# Names should be added to this file as
# Name <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
# Individual Persons
Aaron Hopkins <go-sql-driver at die.net>
Arne Hormann <arnehormann at gmail.com>
Carlos Nieto <jose.carlos at menteslibres.net>
Chris Moos <chris at tech9computers.com>
DisposaBoy <disposaboy at dby.me>
Frederick Mayle <frederickmayle at gmail.com>
Gustavo Kristic <gkristic at gmail.com>
Hanno Braun <mail at hannobraun.com>
Henri Yandell <flamefew at gmail.com>
INADA Naoki <songofacandy at gmail.com>
James Harr <james.harr at gmail.com>
Jian Zhen <zhenjl at gmail.com>
Julien Schmidt <go-sql-driver at julienschmidt.com>
Kamil Dziedzic <kamil at klecza.pl>
Leonardo YongUk Kim <dalinaum at gmail.com>
Lucas Liu <extrafliu at gmail.com>
Luke Scott <luke at webconnex.com>
Michael Woolnough <michael.woolnough at gmail.com>
Nicola Peduzzi <thenikso at gmail.com>
Runrioter Wung <runrioter at gmail.com>
Soroush Pour <me at soroushjp.com>
Xiaobing Jiang <s7v7nislands at gmail.com>
Xiuming Chen <cc at cxm.cc>
# Organizations
Barracuda Networks, Inc.
Google Inc.
Stripe Inc.

92
Godeps/_workspace/src/github.com/go-sql-driver/mysql/CHANGELOG.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,92 @@
## HEAD
Changes:
- Go 1.1 is no longer supported
- Use decimals field from MySQL to format time types (#249)
- Buffer optimizations (#269)
- TLS ServerName defaults to the host (#283)
Bugfixes:
- Enable microsecond resolution on TIME, DATETIME and TIMESTAMP (#249)
- Fixed handling of queries without columns and rows (#255)
- Fixed a panic when SetKeepAlive() failed (#298)
New Features:
- Support for returning table alias on Columns() (#289)
- Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318)
## Version 1.2 (2014-06-03)
Changes:
- We switched back to a "rolling release". `go get` installs the current master branch again
- Version v1 of the driver will not be maintained anymore. Go 1.0 is no longer supported by this driver
- Exported errors to allow easy checking from application code
- Enabled TCP Keepalives on TCP connections
- Optimized INFILE handling (better buffer size calculation, lazy init, ...)
- The DSN parser also checks for a missing separating slash
- Faster binary date / datetime to string formatting
- Also exported the MySQLWarning type
- mysqlConn.Close returns the first error encountered instead of ignoring all errors
- writePacket() automatically writes the packet size to the header
- readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets
New Features:
- `RegisterDial` allows the usage of a custom dial function to establish the network connection
- Setting the connection collation is possible with the `collation` DSN parameter. This parameter should be preferred over the `charset` parameter
- Logging of critical errors is configurable with `SetLogger`
- Google CloudSQL support
Bugfixes:
- Allow more than 32 parameters in prepared statements
- Various old_password fixes
- Fixed TestConcurrent test to pass Go's race detection
- Fixed appendLengthEncodedInteger for large numbers
- Renamed readLengthEnodedString to readLengthEncodedString and skipLengthEnodedString to skipLengthEncodedString (fixed typo)
## Version 1.1 (2013-11-02)
Changes:
- Go-MySQL-Driver now requires Go 1.1
- Connections now use the collation `utf8_general_ci` by default. Adding `&charset=UTF8` to the DSN should not be necessary anymore
- Made closing rows and connections error tolerant. This allows for example deferring rows.Close() without checking for errors
- `[]byte(nil)` is now treated as a NULL value. Before, it was treated like an empty string / `[]byte("")`
- DSN parameter values must now be url.QueryEscape'ed. This allows text values to contain special characters, such as '&'.
- Use the IO buffer also for writing. This results in zero allocations (by the driver) for most queries
- Optimized the buffer for reading
- stmt.Query now caches column metadata
- New Logo
- Changed the copyright header to include all contributors
- Improved the LOAD INFILE documentation
- The driver struct is now exported to make the driver directly accessible
- Refactored the driver tests
- Added more benchmarks and moved all to a separate file
- Other small refactoring
New Features:
- Added *old_passwords* support: Required in some cases, but must be enabled by adding `allowOldPasswords=true` to the DSN since it is insecure
- Added a `clientFoundRows` parameter: Return the number of matching rows instead of the number of rows changed on UPDATEs
- Added TLS/SSL support: Use a TLS/SSL encrypted connection to the server. Custom TLS configs can be registered and used
Bugfixes:
- Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification
- Convert to DB timezone when inserting `time.Time`
- Splitted packets (more than 16MB) are now merged correctly
- Fixed false positive `io.EOF` errors when the data was fully read
- Avoid panics on reuse of closed connections
- Fixed empty string producing false nil values
- Fixed sign byte for positive TIME fields
## Version 1.0 (2013-05-14)
Initial Release

40
Godeps/_workspace/src/github.com/go-sql-driver/mysql/CONTRIBUTING.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,40 @@
# Contributing Guidelines
## Reporting Issues
Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed).
Please provide the following minimum information:
* Your Go-MySQL-Driver version (or git SHA)
* Your Go version (run `go version` in your console)
* A detailed issue description
* Error Log if present
* If possible, a short example
## Contributing Code
By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file.
Don't forget to add yourself to the AUTHORS file.
### Pull Requests Checklist
Please check the following points before submitting your pull request:
- [x] Code compiles correctly
- [x] Created tests, if possible
- [x] All tests pass
- [x] Extended the README / documentation, if necessary
- [x] Added yourself to the AUTHORS file
### Code Review
Everyone is invited to review and comment on pull requests.
If it looks fine to you, comment with "LGTM" (Looks good to me).
If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes.
Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM".
## Development Ideas
If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page.

373
Godeps/_workspace/src/github.com/go-sql-driver/mysql/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

19
Godeps/_workspace/src/github.com/go-sql-driver/mysql/appengine.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,19 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build appengine
package mysql
import (
"appengine/cloudsql"
)
func init() {
RegisterDial("cloudsql", cloudsql.Dial)
}

246
Godeps/_workspace/src/github.com/go-sql-driver/mysql/benchmark_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,246 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"bytes"
"database/sql"
"database/sql/driver"
"math"
"strings"
"sync"
"sync/atomic"
"testing"
"time"
)
type TB testing.B
func (tb *TB) check(err error) {
if err != nil {
tb.Fatal(err)
}
}
func (tb *TB) checkDB(db *sql.DB, err error) *sql.DB {
tb.check(err)
return db
}
func (tb *TB) checkRows(rows *sql.Rows, err error) *sql.Rows {
tb.check(err)
return rows
}
func (tb *TB) checkStmt(stmt *sql.Stmt, err error) *sql.Stmt {
tb.check(err)
return stmt
}
func initDB(b *testing.B, queries ...string) *sql.DB {
tb := (*TB)(b)
db := tb.checkDB(sql.Open("mysql", dsn))
for _, query := range queries {
if _, err := db.Exec(query); err != nil {
if w, ok := err.(MySQLWarnings); ok {
b.Logf("Warning on %q: %v", query, w)
} else {
b.Fatalf("Error on %q: %v", query, err)
}
}
}
return db
}
const concurrencyLevel = 10
func BenchmarkQuery(b *testing.B) {
tb := (*TB)(b)
b.StopTimer()
b.ReportAllocs()
db := initDB(b,
"DROP TABLE IF EXISTS foo",
"CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))",
`INSERT INTO foo VALUES (1, "one")`,
`INSERT INTO foo VALUES (2, "two")`,
)
db.SetMaxIdleConns(concurrencyLevel)
defer db.Close()
stmt := tb.checkStmt(db.Prepare("SELECT val FROM foo WHERE id=?"))
defer stmt.Close()
remain := int64(b.N)
var wg sync.WaitGroup
wg.Add(concurrencyLevel)
defer wg.Wait()
b.StartTimer()
for i := 0; i < concurrencyLevel; i++ {
go func() {
for {
if atomic.AddInt64(&remain, -1) < 0 {
wg.Done()
return
}
var got string
tb.check(stmt.QueryRow(1).Scan(&got))
if got != "one" {
b.Errorf("query = %q; want one", got)
wg.Done()
return
}
}
}()
}
}
func BenchmarkExec(b *testing.B) {
tb := (*TB)(b)
b.StopTimer()
b.ReportAllocs()
db := tb.checkDB(sql.Open("mysql", dsn))
db.SetMaxIdleConns(concurrencyLevel)
defer db.Close()
stmt := tb.checkStmt(db.Prepare("DO 1"))
defer stmt.Close()
remain := int64(b.N)
var wg sync.WaitGroup
wg.Add(concurrencyLevel)
defer wg.Wait()
b.StartTimer()
for i := 0; i < concurrencyLevel; i++ {
go func() {
for {
if atomic.AddInt64(&remain, -1) < 0 {
wg.Done()
return
}
if _, err := stmt.Exec(); err != nil {
b.Fatal(err.Error())
}
}
}()
}
}
// data, but no db writes
var roundtripSample []byte
func initRoundtripBenchmarks() ([]byte, int, int) {
if roundtripSample == nil {
roundtripSample = []byte(strings.Repeat("0123456789abcdef", 1024*1024))
}
return roundtripSample, 16, len(roundtripSample)
}
func BenchmarkRoundtripTxt(b *testing.B) {
b.StopTimer()
sample, min, max := initRoundtripBenchmarks()
sampleString := string(sample)
b.ReportAllocs()
tb := (*TB)(b)
db := tb.checkDB(sql.Open("mysql", dsn))
defer db.Close()
b.StartTimer()
var result string
for i := 0; i < b.N; i++ {
length := min + i
if length > max {
length = max
}
test := sampleString[0:length]
rows := tb.checkRows(db.Query(`SELECT "` + test + `"`))
if !rows.Next() {
rows.Close()
b.Fatalf("crashed")
}
err := rows.Scan(&result)
if err != nil {
rows.Close()
b.Fatalf("crashed")
}
if result != test {
rows.Close()
b.Errorf("mismatch")
}
rows.Close()
}
}
func BenchmarkRoundtripBin(b *testing.B) {
b.StopTimer()
sample, min, max := initRoundtripBenchmarks()
b.ReportAllocs()
tb := (*TB)(b)
db := tb.checkDB(sql.Open("mysql", dsn))
defer db.Close()
stmt := tb.checkStmt(db.Prepare("SELECT ?"))
defer stmt.Close()
b.StartTimer()
var result sql.RawBytes
for i := 0; i < b.N; i++ {
length := min + i
if length > max {
length = max
}
test := sample[0:length]
rows := tb.checkRows(stmt.Query(test))
if !rows.Next() {
rows.Close()
b.Fatalf("crashed")
}
err := rows.Scan(&result)
if err != nil {
rows.Close()
b.Fatalf("crashed")
}
if !bytes.Equal(result, test) {
rows.Close()
b.Errorf("mismatch")
}
rows.Close()
}
}
func BenchmarkInterpolation(b *testing.B) {
mc := &mysqlConn{
cfg: &config{
interpolateParams: true,
loc: time.UTC,
},
maxPacketAllowed: maxPacketSize,
maxWriteSize: maxPacketSize - 1,
buf: newBuffer(nil),
}
args := []driver.Value{
int64(42424242),
float64(math.Pi),
false,
time.Unix(1423411542, 807015000),
[]byte("bytes containing special chars ' \" \a \x00"),
"string containing special chars ' \" \a \x00",
}
q := "SELECT ?, ?, ?, ?, ?, ?"
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := mc.interpolateParams(q, args)
if err != nil {
b.Fatal(err)
}
}
}

136
Godeps/_workspace/src/github.com/go-sql-driver/mysql/buffer.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,136 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import "io"
const defaultBufSize = 4096
// A buffer which is used for both reading and writing.
// This is possible since communication on each connection is synchronous.
// In other words, we can't write and read simultaneously on the same connection.
// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
// Also highly optimized for this particular use case.
type buffer struct {
buf []byte
rd io.Reader
idx int
length int
}
func newBuffer(rd io.Reader) buffer {
var b [defaultBufSize]byte
return buffer{
buf: b[:],
rd: rd,
}
}
// fill reads into the buffer until at least _need_ bytes are in it
func (b *buffer) fill(need int) error {
n := b.length
// move existing data to the beginning
if n > 0 && b.idx > 0 {
copy(b.buf[0:n], b.buf[b.idx:])
}
// grow buffer if necessary
// TODO: let the buffer shrink again at some point
// Maybe keep the org buf slice and swap back?
if need > len(b.buf) {
// Round up to the next multiple of the default size
newBuf := make([]byte, ((need/defaultBufSize)+1)*defaultBufSize)
copy(newBuf, b.buf)
b.buf = newBuf
}
b.idx = 0
for {
nn, err := b.rd.Read(b.buf[n:])
n += nn
switch err {
case nil:
if n < need {
continue
}
b.length = n
return nil
case io.EOF:
if n >= need {
b.length = n
return nil
}
return io.ErrUnexpectedEOF
default:
return err
}
}
}
// returns next N bytes from buffer.
// The returned slice is only guaranteed to be valid until the next read
func (b *buffer) readNext(need int) ([]byte, error) {
if b.length < need {
// refill
if err := b.fill(need); err != nil {
return nil, err
}
}
offset := b.idx
b.idx += need
b.length -= need
return b.buf[offset:b.idx], nil
}
// returns a buffer with the requested size.
// If possible, a slice from the existing buffer is returned.
// Otherwise a bigger buffer is made.
// Only one buffer (total) can be used at a time.
func (b *buffer) takeBuffer(length int) []byte {
if b.length > 0 {
return nil
}
// test (cheap) general case first
if length <= defaultBufSize || length <= cap(b.buf) {
return b.buf[:length]
}
if length < maxPacketSize {
b.buf = make([]byte, length)
return b.buf
}
return make([]byte, length)
}
// shortcut which can be used if the requested buffer is guaranteed to be
// smaller than defaultBufSize
// Only one buffer (total) can be used at a time.
func (b *buffer) takeSmallBuffer(length int) []byte {
if b.length == 0 {
return b.buf[:length]
}
return nil
}
// takeCompleteBuffer returns the complete existing buffer.
// This can be used if the necessary buffer size is unknown.
// Only one buffer (total) can be used at a time.
func (b *buffer) takeCompleteBuffer() []byte {
if b.length == 0 {
return b.buf
}
return nil
}

250
Godeps/_workspace/src/github.com/go-sql-driver/mysql/collations.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,250 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2014 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
const defaultCollation byte = 33 // utf8_general_ci
// A list of available collations mapped to the internal ID.
// To update this map use the following MySQL query:
// SELECT COLLATION_NAME, ID FROM information_schema.COLLATIONS
var collations = map[string]byte{
"big5_chinese_ci": 1,
"latin2_czech_cs": 2,
"dec8_swedish_ci": 3,
"cp850_general_ci": 4,
"latin1_german1_ci": 5,
"hp8_english_ci": 6,
"koi8r_general_ci": 7,
"latin1_swedish_ci": 8,
"latin2_general_ci": 9,
"swe7_swedish_ci": 10,
"ascii_general_ci": 11,
"ujis_japanese_ci": 12,
"sjis_japanese_ci": 13,
"cp1251_bulgarian_ci": 14,
"latin1_danish_ci": 15,
"hebrew_general_ci": 16,
"tis620_thai_ci": 18,
"euckr_korean_ci": 19,
"latin7_estonian_cs": 20,
"latin2_hungarian_ci": 21,
"koi8u_general_ci": 22,
"cp1251_ukrainian_ci": 23,
"gb2312_chinese_ci": 24,
"greek_general_ci": 25,
"cp1250_general_ci": 26,
"latin2_croatian_ci": 27,
"gbk_chinese_ci": 28,
"cp1257_lithuanian_ci": 29,
"latin5_turkish_ci": 30,
"latin1_german2_ci": 31,
"armscii8_general_ci": 32,
"utf8_general_ci": 33,
"cp1250_czech_cs": 34,
"ucs2_general_ci": 35,
"cp866_general_ci": 36,
"keybcs2_general_ci": 37,
"macce_general_ci": 38,
"macroman_general_ci": 39,
"cp852_general_ci": 40,
"latin7_general_ci": 41,
"latin7_general_cs": 42,
"macce_bin": 43,
"cp1250_croatian_ci": 44,
"utf8mb4_general_ci": 45,
"utf8mb4_bin": 46,
"latin1_bin": 47,
"latin1_general_ci": 48,
"latin1_general_cs": 49,
"cp1251_bin": 50,
"cp1251_general_ci": 51,
"cp1251_general_cs": 52,
"macroman_bin": 53,
"utf16_general_ci": 54,
"utf16_bin": 55,
"utf16le_general_ci": 56,
"cp1256_general_ci": 57,
"cp1257_bin": 58,
"cp1257_general_ci": 59,
"utf32_general_ci": 60,
"utf32_bin": 61,
"utf16le_bin": 62,
"binary": 63,
"armscii8_bin": 64,
"ascii_bin": 65,
"cp1250_bin": 66,
"cp1256_bin": 67,
"cp866_bin": 68,
"dec8_bin": 69,
"greek_bin": 70,
"hebrew_bin": 71,
"hp8_bin": 72,
"keybcs2_bin": 73,
"koi8r_bin": 74,
"koi8u_bin": 75,
"latin2_bin": 77,
"latin5_bin": 78,
"latin7_bin": 79,
"cp850_bin": 80,
"cp852_bin": 81,
"swe7_bin": 82,
"utf8_bin": 83,
"big5_bin": 84,
"euckr_bin": 85,
"gb2312_bin": 86,
"gbk_bin": 87,
"sjis_bin": 88,
"tis620_bin": 89,
"ucs2_bin": 90,
"ujis_bin": 91,
"geostd8_general_ci": 92,
"geostd8_bin": 93,
"latin1_spanish_ci": 94,
"cp932_japanese_ci": 95,
"cp932_bin": 96,
"eucjpms_japanese_ci": 97,
"eucjpms_bin": 98,
"cp1250_polish_ci": 99,
"utf16_unicode_ci": 101,
"utf16_icelandic_ci": 102,
"utf16_latvian_ci": 103,
"utf16_romanian_ci": 104,
"utf16_slovenian_ci": 105,
"utf16_polish_ci": 106,
"utf16_estonian_ci": 107,
"utf16_spanish_ci": 108,
"utf16_swedish_ci": 109,
"utf16_turkish_ci": 110,
"utf16_czech_ci": 111,
"utf16_danish_ci": 112,
"utf16_lithuanian_ci": 113,
"utf16_slovak_ci": 114,
"utf16_spanish2_ci": 115,
"utf16_roman_ci": 116,
"utf16_persian_ci": 117,
"utf16_esperanto_ci": 118,
"utf16_hungarian_ci": 119,
"utf16_sinhala_ci": 120,
"utf16_german2_ci": 121,
"utf16_croatian_ci": 122,
"utf16_unicode_520_ci": 123,
"utf16_vietnamese_ci": 124,
"ucs2_unicode_ci": 128,
"ucs2_icelandic_ci": 129,
"ucs2_latvian_ci": 130,
"ucs2_romanian_ci": 131,
"ucs2_slovenian_ci": 132,
"ucs2_polish_ci": 133,
"ucs2_estonian_ci": 134,
"ucs2_spanish_ci": 135,
"ucs2_swedish_ci": 136,
"ucs2_turkish_ci": 137,
"ucs2_czech_ci": 138,
"ucs2_danish_ci": 139,
"ucs2_lithuanian_ci": 140,
"ucs2_slovak_ci": 141,
"ucs2_spanish2_ci": 142,
"ucs2_roman_ci": 143,
"ucs2_persian_ci": 144,
"ucs2_esperanto_ci": 145,
"ucs2_hungarian_ci": 146,
"ucs2_sinhala_ci": 147,
"ucs2_german2_ci": 148,
"ucs2_croatian_ci": 149,
"ucs2_unicode_520_ci": 150,
"ucs2_vietnamese_ci": 151,
"ucs2_general_mysql500_ci": 159,
"utf32_unicode_ci": 160,
"utf32_icelandic_ci": 161,
"utf32_latvian_ci": 162,
"utf32_romanian_ci": 163,
"utf32_slovenian_ci": 164,
"utf32_polish_ci": 165,
"utf32_estonian_ci": 166,
"utf32_spanish_ci": 167,
"utf32_swedish_ci": 168,
"utf32_turkish_ci": 169,
"utf32_czech_ci": 170,
"utf32_danish_ci": 171,
"utf32_lithuanian_ci": 172,
"utf32_slovak_ci": 173,
"utf32_spanish2_ci": 174,
"utf32_roman_ci": 175,
"utf32_persian_ci": 176,
"utf32_esperanto_ci": 177,
"utf32_hungarian_ci": 178,
"utf32_sinhala_ci": 179,
"utf32_german2_ci": 180,
"utf32_croatian_ci": 181,
"utf32_unicode_520_ci": 182,
"utf32_vietnamese_ci": 183,
"utf8_unicode_ci": 192,
"utf8_icelandic_ci": 193,
"utf8_latvian_ci": 194,
"utf8_romanian_ci": 195,
"utf8_slovenian_ci": 196,
"utf8_polish_ci": 197,
"utf8_estonian_ci": 198,
"utf8_spanish_ci": 199,
"utf8_swedish_ci": 200,
"utf8_turkish_ci": 201,
"utf8_czech_ci": 202,
"utf8_danish_ci": 203,
"utf8_lithuanian_ci": 204,
"utf8_slovak_ci": 205,
"utf8_spanish2_ci": 206,
"utf8_roman_ci": 207,
"utf8_persian_ci": 208,
"utf8_esperanto_ci": 209,
"utf8_hungarian_ci": 210,
"utf8_sinhala_ci": 211,
"utf8_german2_ci": 212,
"utf8_croatian_ci": 213,
"utf8_unicode_520_ci": 214,
"utf8_vietnamese_ci": 215,
"utf8_general_mysql500_ci": 223,
"utf8mb4_unicode_ci": 224,
"utf8mb4_icelandic_ci": 225,
"utf8mb4_latvian_ci": 226,
"utf8mb4_romanian_ci": 227,
"utf8mb4_slovenian_ci": 228,
"utf8mb4_polish_ci": 229,
"utf8mb4_estonian_ci": 230,
"utf8mb4_spanish_ci": 231,
"utf8mb4_swedish_ci": 232,
"utf8mb4_turkish_ci": 233,
"utf8mb4_czech_ci": 234,
"utf8mb4_danish_ci": 235,
"utf8mb4_lithuanian_ci": 236,
"utf8mb4_slovak_ci": 237,
"utf8mb4_spanish2_ci": 238,
"utf8mb4_roman_ci": 239,
"utf8mb4_persian_ci": 240,
"utf8mb4_esperanto_ci": 241,
"utf8mb4_hungarian_ci": 242,
"utf8mb4_sinhala_ci": 243,
"utf8mb4_german2_ci": 244,
"utf8mb4_croatian_ci": 245,
"utf8mb4_unicode_520_ci": 246,
"utf8mb4_vietnamese_ci": 247,
}
// A blacklist of collations which is unsafe to interpolate parameters.
// These multibyte encodings may contains 0x5c (`\`) in their trailing bytes.
var unsafeCollations = map[byte]bool{
1: true, // big5_chinese_ci
13: true, // sjis_japanese_ci
28: true, // gbk_chinese_ci
84: true, // big5_bin
86: true, // gb2312_bin
87: true, // gbk_bin
88: true, // sjis_bin
95: true, // cp932_japanese_ci
96: true, // cp932_bin
}

402
Godeps/_workspace/src/github.com/go-sql-driver/mysql/connection.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,402 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"crypto/tls"
"database/sql/driver"
"errors"
"net"
"strconv"
"strings"
"time"
)
type mysqlConn struct {
buf buffer
netConn net.Conn
affectedRows uint64
insertId uint64
cfg *config
maxPacketAllowed int
maxWriteSize int
flags clientFlag
status statusFlag
sequence uint8
parseTime bool
strict bool
}
type config struct {
user string
passwd string
net string
addr string
dbname string
params map[string]string
loc *time.Location
tls *tls.Config
timeout time.Duration
collation uint8
allowAllFiles bool
allowOldPasswords bool
clientFoundRows bool
columnsWithAlias bool
interpolateParams bool
}
// Handles parameters set in DSN after the connection is established
func (mc *mysqlConn) handleParams() (err error) {
for param, val := range mc.cfg.params {
switch param {
// Charset
case "charset":
charsets := strings.Split(val, ",")
for i := range charsets {
// ignore errors here - a charset may not exist
err = mc.exec("SET NAMES " + charsets[i])
if err == nil {
break
}
}
if err != nil {
return
}
// time.Time parsing
case "parseTime":
var isBool bool
mc.parseTime, isBool = readBool(val)
if !isBool {
return errors.New("Invalid Bool value: " + val)
}
// Strict mode
case "strict":
var isBool bool
mc.strict, isBool = readBool(val)
if !isBool {
return errors.New("Invalid Bool value: " + val)
}
// Compression
case "compress":
err = errors.New("Compression not implemented yet")
return
// System Vars
default:
err = mc.exec("SET " + param + "=" + val + "")
if err != nil {
return
}
}
}
return
}
func (mc *mysqlConn) Begin() (driver.Tx, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
err := mc.exec("START TRANSACTION")
if err == nil {
return &mysqlTx{mc}, err
}
return nil, err
}
func (mc *mysqlConn) Close() (err error) {
// Makes Close idempotent
if mc.netConn != nil {
err = mc.writeCommandPacket(comQuit)
if err == nil {
err = mc.netConn.Close()
} else {
mc.netConn.Close()
}
mc.netConn = nil
}
mc.cfg = nil
mc.buf.rd = nil
return
}
func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
// Send command
err := mc.writeCommandPacketStr(comStmtPrepare, query)
if err != nil {
return nil, err
}
stmt := &mysqlStmt{
mc: mc,
}
// Read Result
columnCount, err := stmt.readPrepareResultPacket()
if err == nil {
if stmt.paramCount > 0 {
if err = mc.readUntilEOF(); err != nil {
return nil, err
}
}
if columnCount > 0 {
err = mc.readUntilEOF()
}
}
return stmt, err
}
func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (string, error) {
buf := mc.buf.takeCompleteBuffer()
if buf == nil {
// can not take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer)
return "", driver.ErrBadConn
}
buf = buf[:0]
argPos := 0
for i := 0; i < len(query); i++ {
q := strings.IndexByte(query[i:], '?')
if q == -1 {
buf = append(buf, query[i:]...)
break
}
buf = append(buf, query[i:i+q]...)
i += q
arg := args[argPos]
argPos++
if arg == nil {
buf = append(buf, "NULL"...)
continue
}
switch v := arg.(type) {
case int64:
buf = strconv.AppendInt(buf, v, 10)
case float64:
buf = strconv.AppendFloat(buf, v, 'g', -1, 64)
case bool:
if v {
buf = append(buf, '1')
} else {
buf = append(buf, '0')
}
case time.Time:
if v.IsZero() {
buf = append(buf, "'0000-00-00'"...)
} else {
v := v.In(mc.cfg.loc)
v = v.Add(time.Nanosecond * 500) // To round under microsecond
year := v.Year()
year100 := year / 100
year1 := year % 100
month := v.Month()
day := v.Day()
hour := v.Hour()
minute := v.Minute()
second := v.Second()
micro := v.Nanosecond() / 1000
buf = append(buf, []byte{
'\'',
digits10[year100], digits01[year100],
digits10[year1], digits01[year1],
'-',
digits10[month], digits01[month],
'-',
digits10[day], digits01[day],
' ',
digits10[hour], digits01[hour],
':',
digits10[minute], digits01[minute],
':',
digits10[second], digits01[second],
}...)
if micro != 0 {
micro10000 := micro / 10000
micro100 := micro / 100 % 100
micro1 := micro % 100
buf = append(buf, []byte{
'.',
digits10[micro10000], digits01[micro10000],
digits10[micro100], digits01[micro100],
digits10[micro1], digits01[micro1],
}...)
}
buf = append(buf, '\'')
}
case []byte:
if v == nil {
buf = append(buf, "NULL"...)
} else {
buf = append(buf, '\'')
if mc.status&statusNoBackslashEscapes == 0 {
buf = escapeBytesBackslash(buf, v)
} else {
buf = escapeBytesQuotes(buf, v)
}
buf = append(buf, '\'')
}
case string:
buf = append(buf, '\'')
if mc.status&statusNoBackslashEscapes == 0 {
buf = escapeStringBackslash(buf, v)
} else {
buf = escapeStringQuotes(buf, v)
}
buf = append(buf, '\'')
default:
return "", driver.ErrSkip
}
if len(buf)+4 > mc.maxPacketAllowed {
return "", driver.ErrSkip
}
}
if argPos != len(args) {
return "", driver.ErrSkip
}
return string(buf), nil
}
func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
if len(args) != 0 {
if !mc.cfg.interpolateParams {
return nil, driver.ErrSkip
}
// try to interpolate the parameters to save extra roundtrips for preparing and closing a statement
prepared, err := mc.interpolateParams(query, args)
if err != nil {
return nil, err
}
query = prepared
args = nil
}
mc.affectedRows = 0
mc.insertId = 0
err := mc.exec(query)
if err == nil {
return &mysqlResult{
affectedRows: int64(mc.affectedRows),
insertId: int64(mc.insertId),
}, err
}
return nil, err
}
// Internal function to execute commands
func (mc *mysqlConn) exec(query string) error {
// Send command
err := mc.writeCommandPacketStr(comQuery, query)
if err != nil {
return err
}
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err == nil && resLen > 0 {
if err = mc.readUntilEOF(); err != nil {
return err
}
err = mc.readUntilEOF()
}
return err
}
func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) {
if mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
if len(args) != 0 {
if !mc.cfg.interpolateParams {
return nil, driver.ErrSkip
}
// try client-side prepare to reduce roundtrip
prepared, err := mc.interpolateParams(query, args)
if err != nil {
return nil, err
}
query = prepared
args = nil
}
// Send command
err := mc.writeCommandPacketStr(comQuery, query)
if err == nil {
// Read Result
var resLen int
resLen, err = mc.readResultSetHeaderPacket()
if err == nil {
rows := new(textRows)
rows.mc = mc
if resLen == 0 {
// no columns, no more data
return emptyRows{}, nil
}
// Columns
rows.columns, err = mc.readColumns(resLen)
return rows, err
}
}
return nil, err
}
// Gets the value of the given MySQL System Variable
// The returned byte slice is only valid until the next read
func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) {
// Send command
if err := mc.writeCommandPacketStr(comQuery, "SELECT @@"+name); err != nil {
return nil, err
}
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err == nil {
rows := new(textRows)
rows.mc = mc
if resLen > 0 {
// Columns
if err := mc.readUntilEOF(); err != nil {
return nil, err
}
}
dest := make([]driver.Value, resLen)
if err = rows.readRow(dest); err == nil {
return dest[0].([]byte), mc.readUntilEOF()
}
}
return nil, err
}

162
Godeps/_workspace/src/github.com/go-sql-driver/mysql/const.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,162 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
const (
minProtocolVersion byte = 10
maxPacketSize = 1<<24 - 1
timeFormat = "2006-01-02 15:04:05.999999"
)
// MySQL constants documentation:
// http://dev.mysql.com/doc/internals/en/client-server-protocol.html
const (
iOK byte = 0x00
iLocalInFile byte = 0xfb
iEOF byte = 0xfe
iERR byte = 0xff
)
// https://dev.mysql.com/doc/internals/en/capability-flags.html#packet-Protocol::CapabilityFlags
type clientFlag uint32
const (
clientLongPassword clientFlag = 1 << iota
clientFoundRows
clientLongFlag
clientConnectWithDB
clientNoSchema
clientCompress
clientODBC
clientLocalFiles
clientIgnoreSpace
clientProtocol41
clientInteractive
clientSSL
clientIgnoreSIGPIPE
clientTransactions
clientReserved
clientSecureConn
clientMultiStatements
clientMultiResults
clientPSMultiResults
clientPluginAuth
clientConnectAttrs
clientPluginAuthLenEncClientData
clientCanHandleExpiredPasswords
clientSessionTrack
clientDeprecateEOF
)
const (
comQuit byte = iota + 1
comInitDB
comQuery
comFieldList
comCreateDB
comDropDB
comRefresh
comShutdown
comStatistics
comProcessInfo
comConnect
comProcessKill
comDebug
comPing
comTime
comDelayedInsert
comChangeUser
comBinlogDump
comTableDump
comConnectOut
comRegisterSlave
comStmtPrepare
comStmtExecute
comStmtSendLongData
comStmtClose
comStmtReset
comSetOption
comStmtFetch
)
// https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnType
const (
fieldTypeDecimal byte = iota
fieldTypeTiny
fieldTypeShort
fieldTypeLong
fieldTypeFloat
fieldTypeDouble
fieldTypeNULL
fieldTypeTimestamp
fieldTypeLongLong
fieldTypeInt24
fieldTypeDate
fieldTypeTime
fieldTypeDateTime
fieldTypeYear
fieldTypeNewDate
fieldTypeVarChar
fieldTypeBit
)
const (
fieldTypeNewDecimal byte = iota + 0xf6
fieldTypeEnum
fieldTypeSet
fieldTypeTinyBLOB
fieldTypeMediumBLOB
fieldTypeLongBLOB
fieldTypeBLOB
fieldTypeVarString
fieldTypeString
fieldTypeGeometry
)
type fieldFlag uint16
const (
flagNotNULL fieldFlag = 1 << iota
flagPriKey
flagUniqueKey
flagMultipleKey
flagBLOB
flagUnsigned
flagZeroFill
flagBinary
flagEnum
flagAutoIncrement
flagTimestamp
flagSet
flagUnknown1
flagUnknown2
flagUnknown3
flagUnknown4
)
// http://dev.mysql.com/doc/internals/en/status-flags.html
type statusFlag uint16
const (
statusInTrans statusFlag = 1 << iota
statusInAutocommit
statusReserved // Not in documentation
statusMoreResultsExists
statusNoGoodIndexUsed
statusNoIndexUsed
statusCursorExists
statusLastRowSent
statusDbDropped
statusNoBackslashEscapes
statusMetadataChanged
statusQueryWasSlow
statusPsOutParams
statusInTransReadonly
statusSessionStateChanged
)

140
Godeps/_workspace/src/github.com/go-sql-driver/mysql/driver.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,140 @@
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// The driver should be used via the database/sql package:
//
// import "database/sql"
// import _ "github.com/go-sql-driver/mysql"
//
// db, err := sql.Open("mysql", "user:password@/dbname")
//
// See https://github.com/go-sql-driver/mysql#usage for details
package mysql
import (
"database/sql"
"database/sql/driver"
"net"
)
// This struct is exported to make the driver directly accessible.
// In general the driver is used via the database/sql package.
type MySQLDriver struct{}
// DialFunc is a function which can be used to establish the network connection.
// Custom dial functions must be registered with RegisterDial
type DialFunc func(addr string) (net.Conn, error)
var dials map[string]DialFunc
// RegisterDial registers a custom dial function. It can then be used by the
// network address mynet(addr), where mynet is the registered new network.
// addr is passed as a parameter to the dial function.
func RegisterDial(net string, dial DialFunc) {
if dials == nil {
dials = make(map[string]DialFunc)
}
dials[net] = dial
}
// Open new Connection.
// See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how
// the DSN string is formated
func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
var err error
// New mysqlConn
mc := &mysqlConn{
maxPacketAllowed: maxPacketSize,
maxWriteSize: maxPacketSize - 1,
}
mc.cfg, err = parseDSN(dsn)
if err != nil {
return nil, err
}
// Connect to Server
if dial, ok := dials[mc.cfg.net]; ok {
mc.netConn, err = dial(mc.cfg.addr)
} else {
nd := net.Dialer{Timeout: mc.cfg.timeout}
mc.netConn, err = nd.Dial(mc.cfg.net, mc.cfg.addr)
}
if err != nil {
return nil, err
}
// Enable TCP Keepalives on TCP connections
if tc, ok := mc.netConn.(*net.TCPConn); ok {
if err := tc.SetKeepAlive(true); err != nil {
// Don't send COM_QUIT before handshake.
mc.netConn.Close()
mc.netConn = nil
return nil, err
}
}
mc.buf = newBuffer(mc.netConn)
// Reading Handshake Initialization Packet
cipher, err := mc.readInitPacket()
if err != nil {
mc.Close()
return nil, err
}
// Send Client Authentication Packet
if err = mc.writeAuthPacket(cipher); err != nil {
mc.Close()
return nil, err
}
// Read Result Packet
err = mc.readResultOK()
if err != nil {
// Retry with old authentication method, if allowed
if mc.cfg != nil && mc.cfg.allowOldPasswords && err == ErrOldPassword {
if err = mc.writeOldAuthPacket(cipher); err != nil {
mc.Close()
return nil, err
}
if err = mc.readResultOK(); err != nil {
mc.Close()
return nil, err
}
} else {
mc.Close()
return nil, err
}
}
// Get max allowed packet size
maxap, err := mc.getSystemVar("max_allowed_packet")
if err != nil {
mc.Close()
return nil, err
}
mc.maxPacketAllowed = stringToInt(maxap) - 1
if mc.maxPacketAllowed < maxPacketSize {
mc.maxWriteSize = mc.maxPacketAllowed
}
// Handle DSN Params
err = mc.handleParams()
if err != nil {
mc.Close()
return nil, err
}
return mc, nil
}
func init() {
sql.Register("mysql", &MySQLDriver{})
}

1657
Godeps/_workspace/src/github.com/go-sql-driver/mysql/driver_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

129
Godeps/_workspace/src/github.com/go-sql-driver/mysql/errors.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,129 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"database/sql/driver"
"errors"
"fmt"
"io"
"log"
"os"
)
// Various errors the driver might return. Can change between driver versions.
var (
ErrInvalidConn = errors.New("Invalid Connection")
ErrMalformPkt = errors.New("Malformed Packet")
ErrNoTLS = errors.New("TLS encryption requested but server does not support TLS")
ErrOldPassword = errors.New("This server only supports the insecure old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords")
ErrOldProtocol = errors.New("MySQL-Server does not support required Protocol 41+")
ErrPktSync = errors.New("Commands out of sync. You can't run this command now")
ErrPktSyncMul = errors.New("Commands out of sync. Did you run multiple statements at once?")
ErrPktTooLarge = errors.New("Packet for query is too large. You can change this value on the server by adjusting the 'max_allowed_packet' variable.")
ErrBusyBuffer = errors.New("Busy buffer")
)
var errLog Logger = log.New(os.Stderr, "[MySQL] ", log.Ldate|log.Ltime|log.Lshortfile)
// Logger is used to log critical error messages.
type Logger interface {
Print(v ...interface{})
}
// SetLogger is used to set the logger for critical errors.
// The initial logger is os.Stderr.
func SetLogger(logger Logger) error {
if logger == nil {
return errors.New("logger is nil")
}
errLog = logger
return nil
}
// MySQLError is an error type which represents a single MySQL error
type MySQLError struct {
Number uint16
Message string
}
func (me *MySQLError) Error() string {
return fmt.Sprintf("Error %d: %s", me.Number, me.Message)
}
// MySQLWarnings is an error type which represents a group of one or more MySQL
// warnings
type MySQLWarnings []MySQLWarning
func (mws MySQLWarnings) Error() string {
var msg string
for i, warning := range mws {
if i > 0 {
msg += "\r\n"
}
msg += fmt.Sprintf(
"%s %s: %s",
warning.Level,
warning.Code,
warning.Message,
)
}
return msg
}
// MySQLWarning is an error type which represents a single MySQL warning.
// Warnings are returned in groups only. See MySQLWarnings
type MySQLWarning struct {
Level string
Code string
Message string
}
func (mc *mysqlConn) getWarnings() (err error) {
rows, err := mc.Query("SHOW WARNINGS", nil)
if err != nil {
return
}
var warnings = MySQLWarnings{}
var values = make([]driver.Value, 3)
for {
err = rows.Next(values)
switch err {
case nil:
warning := MySQLWarning{}
if raw, ok := values[0].([]byte); ok {
warning.Level = string(raw)
} else {
warning.Level = fmt.Sprintf("%s", values[0])
}
if raw, ok := values[1].([]byte); ok {
warning.Code = string(raw)
} else {
warning.Code = fmt.Sprintf("%s", values[1])
}
if raw, ok := values[2].([]byte); ok {
warning.Message = string(raw)
} else {
warning.Message = fmt.Sprintf("%s", values[0])
}
warnings = append(warnings, warning)
case io.EOF:
return warnings
default:
rows.Close()
return
}
}
}

42
Godeps/_workspace/src/github.com/go-sql-driver/mysql/errors_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"bytes"
"log"
"testing"
)
func TestErrorsSetLogger(t *testing.T) {
previous := errLog
defer func() {
errLog = previous
}()
// set up logger
const expected = "prefix: test\n"
buffer := bytes.NewBuffer(make([]byte, 0, 64))
logger := log.New(buffer, "prefix: ", 0)
// print
SetLogger(logger)
errLog.Print("test")
// check result
if actual := buffer.String(); actual != expected {
t.Errorf("expected %q, got %q", expected, actual)
}
}
func TestErrorsStrictIgnoreNotes(t *testing.T) {
runTests(t, dsn+"&sql_notes=false", func(dbt *DBTest) {
dbt.mustExec("DROP TABLE IF EXISTS does_not_exist")
})
}

162
Godeps/_workspace/src/github.com/go-sql-driver/mysql/infile.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,162 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"fmt"
"io"
"os"
"strings"
)
var (
fileRegister map[string]bool
readerRegister map[string]func() io.Reader
)
// RegisterLocalFile adds the given file to the file whitelist,
// so that it can be used by "LOAD DATA LOCAL INFILE <filepath>".
// Alternatively you can allow the use of all local files with
// the DSN parameter 'allowAllFiles=true'
//
// filePath := "/home/gopher/data.csv"
// mysql.RegisterLocalFile(filePath)
// err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo")
// if err != nil {
// ...
//
func RegisterLocalFile(filePath string) {
// lazy map init
if fileRegister == nil {
fileRegister = make(map[string]bool)
}
fileRegister[strings.Trim(filePath, `"`)] = true
}
// DeregisterLocalFile removes the given filepath from the whitelist.
func DeregisterLocalFile(filePath string) {
delete(fileRegister, strings.Trim(filePath, `"`))
}
// RegisterReaderHandler registers a handler function which is used
// to receive a io.Reader.
// The Reader can be used by "LOAD DATA LOCAL INFILE Reader::<name>".
// If the handler returns a io.ReadCloser Close() is called when the
// request is finished.
//
// mysql.RegisterReaderHandler("data", func() io.Reader {
// var csvReader io.Reader // Some Reader that returns CSV data
// ... // Open Reader here
// return csvReader
// })
// err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo")
// if err != nil {
// ...
//
func RegisterReaderHandler(name string, handler func() io.Reader) {
// lazy map init
if readerRegister == nil {
readerRegister = make(map[string]func() io.Reader)
}
readerRegister[name] = handler
}
// DeregisterReaderHandler removes the ReaderHandler function with
// the given name from the registry.
func DeregisterReaderHandler(name string) {
delete(readerRegister, name)
}
func deferredClose(err *error, closer io.Closer) {
closeErr := closer.Close()
if *err == nil {
*err = closeErr
}
}
func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
var rdr io.Reader
var data []byte
if strings.HasPrefix(name, "Reader::") { // io.Reader
name = name[8:]
if handler, inMap := readerRegister[name]; inMap {
rdr = handler()
if rdr != nil {
data = make([]byte, 4+mc.maxWriteSize)
if cl, ok := rdr.(io.Closer); ok {
defer deferredClose(&err, cl)
}
} else {
err = fmt.Errorf("Reader '%s' is <nil>", name)
}
} else {
err = fmt.Errorf("Reader '%s' is not registered", name)
}
} else { // File
name = strings.Trim(name, `"`)
if mc.cfg.allowAllFiles || fileRegister[name] {
var file *os.File
var fi os.FileInfo
if file, err = os.Open(name); err == nil {
defer deferredClose(&err, file)
// get file size
if fi, err = file.Stat(); err == nil {
rdr = file
if fileSize := int(fi.Size()); fileSize <= mc.maxWriteSize {
data = make([]byte, 4+fileSize)
} else if fileSize <= mc.maxPacketAllowed {
data = make([]byte, 4+mc.maxWriteSize)
} else {
err = fmt.Errorf("Local File '%s' too large: Size: %d, Max: %d", name, fileSize, mc.maxPacketAllowed)
}
}
}
} else {
err = fmt.Errorf("Local File '%s' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files", name)
}
}
// send content packets
if err == nil {
var n int
for err == nil {
n, err = rdr.Read(data[4:])
if n > 0 {
if ioErr := mc.writePacket(data[:4+n]); ioErr != nil {
return ioErr
}
}
}
if err == io.EOF {
err = nil
}
}
// send empty packet (termination)
if data == nil {
data = make([]byte, 4)
}
if ioErr := mc.writePacket(data[:4]); ioErr != nil {
return ioErr
}
// read OK packet
if err == nil {
return mc.readResultOK()
} else {
mc.readPacket()
}
return err
}

1138
Godeps/_workspace/src/github.com/go-sql-driver/mysql/packets.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

22
Godeps/_workspace/src/github.com/go-sql-driver/mysql/result.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,22 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
type mysqlResult struct {
affectedRows int64
insertId int64
}
func (res *mysqlResult) LastInsertId() (int64, error) {
return res.insertId, nil
}
func (res *mysqlResult) RowsAffected() (int64, error) {
return res.affectedRows, nil
}

102
Godeps/_workspace/src/github.com/go-sql-driver/mysql/rows.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,102 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"database/sql/driver"
"io"
)
type mysqlField struct {
tableName string
name string
flags fieldFlag
fieldType byte
decimals byte
}
type mysqlRows struct {
mc *mysqlConn
columns []mysqlField
}
type binaryRows struct {
mysqlRows
}
type textRows struct {
mysqlRows
}
type emptyRows struct{}
func (rows *mysqlRows) Columns() []string {
columns := make([]string, len(rows.columns))
if rows.mc.cfg.columnsWithAlias {
for i := range columns {
columns[i] = rows.columns[i].tableName + "." + rows.columns[i].name
}
} else {
for i := range columns {
columns[i] = rows.columns[i].name
}
}
return columns
}
func (rows *mysqlRows) Close() error {
mc := rows.mc
if mc == nil {
return nil
}
if mc.netConn == nil {
return ErrInvalidConn
}
// Remove unread packets from stream
err := mc.readUntilEOF()
rows.mc = nil
return err
}
func (rows *binaryRows) Next(dest []driver.Value) error {
if mc := rows.mc; mc != nil {
if mc.netConn == nil {
return ErrInvalidConn
}
// Fetch next row from stream
return rows.readRow(dest)
}
return io.EOF
}
func (rows *textRows) Next(dest []driver.Value) error {
if mc := rows.mc; mc != nil {
if mc.netConn == nil {
return ErrInvalidConn
}
// Fetch next row from stream
return rows.readRow(dest)
}
return io.EOF
}
func (rows emptyRows) Columns() []string {
return nil
}
func (rows emptyRows) Close() error {
return nil
}
func (rows emptyRows) Next(dest []driver.Value) error {
return io.EOF
}

149
Godeps/_workspace/src/github.com/go-sql-driver/mysql/statement.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,149 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"database/sql/driver"
"fmt"
"reflect"
)
type mysqlStmt struct {
mc *mysqlConn
id uint32
paramCount int
columns []mysqlField // cached from the first query
}
func (stmt *mysqlStmt) Close() error {
if stmt.mc == nil || stmt.mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return driver.ErrBadConn
}
err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id)
stmt.mc = nil
return err
}
func (stmt *mysqlStmt) NumInput() int {
return stmt.paramCount
}
func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {
return converter{}
}
func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
if stmt.mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
// Send command
err := stmt.writeExecutePacket(args)
if err != nil {
return nil, err
}
mc := stmt.mc
mc.affectedRows = 0
mc.insertId = 0
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err == nil {
if resLen > 0 {
// Columns
err = mc.readUntilEOF()
if err != nil {
return nil, err
}
// Rows
err = mc.readUntilEOF()
}
if err == nil {
return &mysqlResult{
affectedRows: int64(mc.affectedRows),
insertId: int64(mc.insertId),
}, nil
}
}
return nil, err
}
func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
if stmt.mc.netConn == nil {
errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn
}
// Send command
err := stmt.writeExecutePacket(args)
if err != nil {
return nil, err
}
mc := stmt.mc
// Read Result
resLen, err := mc.readResultSetHeaderPacket()
if err != nil {
return nil, err
}
rows := new(binaryRows)
rows.mc = mc
if resLen > 0 {
// Columns
// If not cached, read them and cache them
if stmt.columns == nil {
rows.columns, err = mc.readColumns(resLen)
stmt.columns = rows.columns
} else {
rows.columns = stmt.columns
err = mc.readUntilEOF()
}
}
return rows, err
}
type converter struct{}
func (converter) ConvertValue(v interface{}) (driver.Value, error) {
if driver.IsValue(v) {
return v, nil
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
}
return driver.DefaultParameterConverter.ConvertValue(rv.Elem().Interface())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
return int64(rv.Uint()), nil
case reflect.Uint64:
u64 := rv.Uint()
if u64 >= 1<<63 {
return fmt.Sprintf("%d", u64), nil
}
return int64(u64), nil
case reflect.Float32, reflect.Float64:
return rv.Float(), nil
}
return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
}

31
Godeps/_workspace/src/github.com/go-sql-driver/mysql/transaction.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,31 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
type mysqlTx struct {
mc *mysqlConn
}
func (tx *mysqlTx) Commit() (err error) {
if tx.mc == nil || tx.mc.netConn == nil {
return ErrInvalidConn
}
err = tx.mc.exec("COMMIT")
tx.mc = nil
return
}
func (tx *mysqlTx) Rollback() (err error) {
if tx.mc == nil || tx.mc.netConn == nil {
return ErrInvalidConn
}
err = tx.mc.exec("ROLLBACK")
tx.mc = nil
return
}

963
Godeps/_workspace/src/github.com/go-sql-driver/mysql/utils.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,963 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"crypto/sha1"
"crypto/tls"
"database/sql/driver"
"encoding/binary"
"errors"
"fmt"
"io"
"net"
"net/url"
"strings"
"time"
)
var (
tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs
errInvalidDSNUnescaped = errors.New("Invalid DSN: Did you forget to escape a param value?")
errInvalidDSNAddr = errors.New("Invalid DSN: Network Address not terminated (missing closing brace)")
errInvalidDSNNoSlash = errors.New("Invalid DSN: Missing the slash separating the database name")
errInvalidDSNUnsafeCollation = errors.New("Invalid DSN: interpolateParams can be used with ascii, latin1, utf8 and utf8mb4 charset")
)
func init() {
tlsConfigRegister = make(map[string]*tls.Config)
}
// RegisterTLSConfig registers a custom tls.Config to be used with sql.Open.
// Use the key as a value in the DSN where tls=value.
//
// rootCertPool := x509.NewCertPool()
// pem, err := ioutil.ReadFile("/path/ca-cert.pem")
// if err != nil {
// log.Fatal(err)
// }
// if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
// log.Fatal("Failed to append PEM.")
// }
// clientCert := make([]tls.Certificate, 0, 1)
// certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem")
// if err != nil {
// log.Fatal(err)
// }
// clientCert = append(clientCert, certs)
// mysql.RegisterTLSConfig("custom", &tls.Config{
// RootCAs: rootCertPool,
// Certificates: clientCert,
// })
// db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom")
//
func RegisterTLSConfig(key string, config *tls.Config) error {
if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" {
return fmt.Errorf("Key '%s' is reserved", key)
}
tlsConfigRegister[key] = config
return nil
}
// DeregisterTLSConfig removes the tls.Config associated with key.
func DeregisterTLSConfig(key string) {
delete(tlsConfigRegister, key)
}
// parseDSN parses the DSN string to a config
func parseDSN(dsn string) (cfg *config, err error) {
// New config with some default values
cfg = &config{
loc: time.UTC,
collation: defaultCollation,
}
// TODO: use strings.IndexByte when we can depend on Go 1.2
// [user[:password]@][net[(addr)]]/dbname[?param1=value1&paramN=valueN]
// Find the last '/' (since the password or the net addr might contain a '/')
foundSlash := false
for i := len(dsn) - 1; i >= 0; i-- {
if dsn[i] == '/' {
foundSlash = true
var j, k int
// left part is empty if i <= 0
if i > 0 {
// [username[:password]@][protocol[(address)]]
// Find the last '@' in dsn[:i]
for j = i; j >= 0; j-- {
if dsn[j] == '@' {
// username[:password]
// Find the first ':' in dsn[:j]
for k = 0; k < j; k++ {
if dsn[k] == ':' {
cfg.passwd = dsn[k+1 : j]
break
}
}
cfg.user = dsn[:k]
break
}
}
// [protocol[(address)]]
// Find the first '(' in dsn[j+1:i]
for k = j + 1; k < i; k++ {
if dsn[k] == '(' {
// dsn[i-1] must be == ')' if an address is specified
if dsn[i-1] != ')' {
if strings.ContainsRune(dsn[k+1:i], ')') {
return nil, errInvalidDSNUnescaped
}
return nil, errInvalidDSNAddr
}
cfg.addr = dsn[k+1 : i-1]
break
}
}
cfg.net = dsn[j+1 : k]
}
// dbname[?param1=value1&...&paramN=valueN]
// Find the first '?' in dsn[i+1:]
for j = i + 1; j < len(dsn); j++ {
if dsn[j] == '?' {
if err = parseDSNParams(cfg, dsn[j+1:]); err != nil {
return
}
break
}
}
cfg.dbname = dsn[i+1 : j]
break
}
}
if !foundSlash && len(dsn) > 0 {
return nil, errInvalidDSNNoSlash
}
if cfg.interpolateParams && unsafeCollations[cfg.collation] {
return nil, errInvalidDSNUnsafeCollation
}
// Set default network if empty
if cfg.net == "" {
cfg.net = "tcp"
}
// Set default address if empty
if cfg.addr == "" {
switch cfg.net {
case "tcp":
cfg.addr = "127.0.0.1:3306"
case "unix":
cfg.addr = "/tmp/mysql.sock"
default:
return nil, errors.New("Default addr for network '" + cfg.net + "' unknown")
}
}
return
}
// parseDSNParams parses the DSN "query string"
// Values must be url.QueryEscape'ed
func parseDSNParams(cfg *config, params string) (err error) {
for _, v := range strings.Split(params, "&") {
param := strings.SplitN(v, "=", 2)
if len(param) != 2 {
continue
}
// cfg params
switch value := param[1]; param[0] {
// Enable client side placeholder substitution
case "interpolateParams":
var isBool bool
cfg.interpolateParams, isBool = readBool(value)
if !isBool {
return fmt.Errorf("Invalid Bool value: %s", value)
}
// Disable INFILE whitelist / enable all files
case "allowAllFiles":
var isBool bool
cfg.allowAllFiles, isBool = readBool(value)
if !isBool {
return fmt.Errorf("Invalid Bool value: %s", value)
}
// Use old authentication mode (pre MySQL 4.1)
case "allowOldPasswords":
var isBool bool
cfg.allowOldPasswords, isBool = readBool(value)
if !isBool {
return fmt.Errorf("Invalid Bool value: %s", value)
}
// Switch "rowsAffected" mode
case "clientFoundRows":
var isBool bool
cfg.clientFoundRows, isBool = readBool(value)
if !isBool {
return fmt.Errorf("Invalid Bool value: %s", value)
}
// Collation
case "collation":
collation, ok := collations[value]
if !ok {
// Note possibility for false negatives:
// could be triggered although the collation is valid if the
// collations map does not contain entries the server supports.
err = errors.New("unknown collation")
return
}
cfg.collation = collation
break
case "columnsWithAlias":
var isBool bool
cfg.columnsWithAlias, isBool = readBool(value)
if !isBool {
return fmt.Errorf("Invalid Bool value: %s", value)
}
// Time Location
case "loc":
if value, err = url.QueryUnescape(value); err != nil {
return
}
cfg.loc, err = time.LoadLocation(value)
if err != nil {
return
}
// Dial Timeout
case "timeout":
cfg.timeout, err = time.ParseDuration(value)
if err != nil {
return
}
// TLS-Encryption
case "tls":
boolValue, isBool := readBool(value)
if isBool {
if boolValue {
cfg.tls = &tls.Config{}
}
} else {
if strings.ToLower(value) == "skip-verify" {
cfg.tls = &tls.Config{InsecureSkipVerify: true}
} else if tlsConfig, ok := tlsConfigRegister[value]; ok {
if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify {
host, _, err := net.SplitHostPort(cfg.addr)
if err == nil {
tlsConfig.ServerName = host
}
}
cfg.tls = tlsConfig
} else {
return fmt.Errorf("Invalid value / unknown config name: %s", value)
}
}
default:
// lazy init
if cfg.params == nil {
cfg.params = make(map[string]string)
}
if cfg.params[param[0]], err = url.QueryUnescape(value); err != nil {
return
}
}
}
return
}
// Returns the bool value of the input.
// The 2nd return value indicates if the input was a valid bool value
func readBool(input string) (value bool, valid bool) {
switch input {
case "1", "true", "TRUE", "True":
return true, true
case "0", "false", "FALSE", "False":
return false, true
}
// Not a valid bool value
return
}
/******************************************************************************
* Authentication *
******************************************************************************/
// Encrypt password using 4.1+ method
func scramblePassword(scramble, password []byte) []byte {
if len(password) == 0 {
return nil
}
// stage1Hash = SHA1(password)
crypt := sha1.New()
crypt.Write(password)
stage1 := crypt.Sum(nil)
// scrambleHash = SHA1(scramble + SHA1(stage1Hash))
// inner Hash
crypt.Reset()
crypt.Write(stage1)
hash := crypt.Sum(nil)
// outer Hash
crypt.Reset()
crypt.Write(scramble)
crypt.Write(hash)
scramble = crypt.Sum(nil)
// token = scrambleHash XOR stage1Hash
for i := range scramble {
scramble[i] ^= stage1[i]
}
return scramble
}
// Encrypt password using pre 4.1 (old password) method
// https://github.com/atcurtis/mariadb/blob/master/mysys/my_rnd.c
type myRnd struct {
seed1, seed2 uint32
}
const myRndMaxVal = 0x3FFFFFFF
// Pseudo random number generator
func newMyRnd(seed1, seed2 uint32) *myRnd {
return &myRnd{
seed1: seed1 % myRndMaxVal,
seed2: seed2 % myRndMaxVal,
}
}
// Tested to be equivalent to MariaDB's floating point variant
// http://play.golang.org/p/QHvhd4qved
// http://play.golang.org/p/RG0q4ElWDx
func (r *myRnd) NextByte() byte {
r.seed1 = (r.seed1*3 + r.seed2) % myRndMaxVal
r.seed2 = (r.seed1 + r.seed2 + 33) % myRndMaxVal
return byte(uint64(r.seed1) * 31 / myRndMaxVal)
}
// Generate binary hash from byte string using insecure pre 4.1 method
func pwHash(password []byte) (result [2]uint32) {
var add uint32 = 7
var tmp uint32
result[0] = 1345345333
result[1] = 0x12345671
for _, c := range password {
// skip spaces and tabs in password
if c == ' ' || c == '\t' {
continue
}
tmp = uint32(c)
result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
result[1] += (result[1] << 8) ^ result[0]
add += tmp
}
// Remove sign bit (1<<31)-1)
result[0] &= 0x7FFFFFFF
result[1] &= 0x7FFFFFFF
return
}
// Encrypt password using insecure pre 4.1 method
func scrambleOldPassword(scramble, password []byte) []byte {
if len(password) == 0 {
return nil
}
scramble = scramble[:8]
hashPw := pwHash(password)
hashSc := pwHash(scramble)
r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
var out [8]byte
for i := range out {
out[i] = r.NextByte() + 64
}
mask := r.NextByte()
for i := range out {
out[i] ^= mask
}
return out[:]
}
/******************************************************************************
* Time related utils *
******************************************************************************/
// NullTime represents a time.Time that may be NULL.
// NullTime implements the Scanner interface so
// it can be used as a scan destination:
//
// var nt NullTime
// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt)
// ...
// if nt.Valid {
// // use nt.Time
// } else {
// // NULL value
// }
//
// This NullTime implementation is not driver-specific
type NullTime struct {
Time time.Time
Valid bool // Valid is true if Time is not NULL
}
// Scan implements the Scanner interface.
// The value type must be time.Time or string / []byte (formatted time-string),
// otherwise Scan fails.
func (nt *NullTime) Scan(value interface{}) (err error) {
if value == nil {
nt.Time, nt.Valid = time.Time{}, false
return
}
switch v := value.(type) {
case time.Time:
nt.Time, nt.Valid = v, true
return
case []byte:
nt.Time, err = parseDateTime(string(v), time.UTC)
nt.Valid = (err == nil)
return
case string:
nt.Time, err = parseDateTime(v, time.UTC)
nt.Valid = (err == nil)
return
}
nt.Valid = false
return fmt.Errorf("Can't convert %T to time.Time", value)
}
// Value implements the driver Valuer interface.
func (nt NullTime) Value() (driver.Value, error) {
if !nt.Valid {
return nil, nil
}
return nt.Time, nil
}
func parseDateTime(str string, loc *time.Location) (t time.Time, err error) {
base := "0000-00-00 00:00:00.0000000"
switch len(str) {
case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM"
if str == base[:len(str)] {
return
}
t, err = time.Parse(timeFormat[:len(str)], str)
default:
err = fmt.Errorf("Invalid Time-String: %s", str)
return
}
// Adjust location
if err == nil && loc != time.UTC {
y, mo, d := t.Date()
h, mi, s := t.Clock()
t, err = time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil
}
return
}
func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Value, error) {
switch num {
case 0:
return time.Time{}, nil
case 4:
return time.Date(
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
0, 0, 0, 0,
loc,
), nil
case 7:
return time.Date(
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
int(data[4]), // hour
int(data[5]), // minutes
int(data[6]), // seconds
0,
loc,
), nil
case 11:
return time.Date(
int(binary.LittleEndian.Uint16(data[:2])), // year
time.Month(data[2]), // month
int(data[3]), // day
int(data[4]), // hour
int(data[5]), // minutes
int(data[6]), // seconds
int(binary.LittleEndian.Uint32(data[7:11]))*1000, // nanoseconds
loc,
), nil
}
return nil, fmt.Errorf("Invalid DATETIME-packet length %d", num)
}
// zeroDateTime is used in formatBinaryDateTime to avoid an allocation
// if the DATE or DATETIME has the zero value.
// It must never be changed.
// The current behavior depends on database/sql copying the result.
var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value, error) {
// length expects the deterministic length of the zero value,
// negative time and 100+ hours are automatically added if needed
if len(src) == 0 {
if justTime {
return zeroDateTime[11 : 11+length], nil
}
return zeroDateTime[:length], nil
}
var dst []byte // return value
var pt, p1, p2, p3 byte // current digit pair
var zOffs byte // offset of value in zeroDateTime
if justTime {
switch length {
case
8, // time (can be up to 10 when negative and 100+ hours)
10, 11, 12, 13, 14, 15: // time with fractional seconds
default:
return nil, fmt.Errorf("illegal TIME length %d", length)
}
switch len(src) {
case 8, 12:
default:
return nil, fmt.Errorf("Invalid TIME-packet length %d", len(src))
}
// +2 to enable negative time and 100+ hours
dst = make([]byte, 0, length+2)
if src[0] == 1 {
dst = append(dst, '-')
}
if src[1] != 0 {
hour := uint16(src[1])*24 + uint16(src[5])
pt = byte(hour / 100)
p1 = byte(hour - 100*uint16(pt))
dst = append(dst, digits01[pt])
} else {
p1 = src[5]
}
zOffs = 11
src = src[6:]
} else {
switch length {
case 10, 19, 21, 22, 23, 24, 25, 26:
default:
t := "DATE"
if length > 10 {
t += "TIME"
}
return nil, fmt.Errorf("illegal %s length %d", t, length)
}
switch len(src) {
case 4, 7, 11:
default:
t := "DATE"
if length > 10 {
t += "TIME"
}
return nil, fmt.Errorf("illegal %s-packet length %d", t, len(src))
}
dst = make([]byte, 0, length)
// start with the date
year := binary.LittleEndian.Uint16(src[:2])
pt = byte(year / 100)
p1 = byte(year - 100*uint16(pt))
p2, p3 = src[2], src[3]
dst = append(dst,
digits10[pt], digits01[pt],
digits10[p1], digits01[p1], '-',
digits10[p2], digits01[p2], '-',
digits10[p3], digits01[p3],
)
if length == 10 {
return dst, nil
}
if len(src) == 4 {
return append(dst, zeroDateTime[10:length]...), nil
}
dst = append(dst, ' ')
p1 = src[4] // hour
src = src[5:]
}
// p1 is 2-digit hour, src is after hour
p2, p3 = src[0], src[1]
dst = append(dst,
digits10[p1], digits01[p1], ':',
digits10[p2], digits01[p2], ':',
digits10[p3], digits01[p3],
)
if length <= byte(len(dst)) {
return dst, nil
}
src = src[2:]
if len(src) == 0 {
return append(dst, zeroDateTime[19:zOffs+length]...), nil
}
microsecs := binary.LittleEndian.Uint32(src[:4])
p1 = byte(microsecs / 10000)
microsecs -= 10000 * uint32(p1)
p2 = byte(microsecs / 100)
microsecs -= 100 * uint32(p2)
p3 = byte(microsecs)
switch decimals := zOffs + length - 20; decimals {
default:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3], digits01[p3],
), nil
case 1:
return append(dst, '.',
digits10[p1],
), nil
case 2:
return append(dst, '.',
digits10[p1], digits01[p1],
), nil
case 3:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2],
), nil
case 4:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
), nil
case 5:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3],
), nil
}
}
/******************************************************************************
* Convert from and to bytes *
******************************************************************************/
func uint64ToBytes(n uint64) []byte {
return []byte{
byte(n),
byte(n >> 8),
byte(n >> 16),
byte(n >> 24),
byte(n >> 32),
byte(n >> 40),
byte(n >> 48),
byte(n >> 56),
}
}
func uint64ToString(n uint64) []byte {
var a [20]byte
i := 20
// U+0030 = 0
// ...
// U+0039 = 9
var q uint64
for n >= 10 {
i--
q = n / 10
a[i] = uint8(n-q*10) + 0x30
n = q
}
i--
a[i] = uint8(n) + 0x30
return a[i:]
}
// treats string value as unsigned integer representation
func stringToInt(b []byte) int {
val := 0
for i := range b {
val *= 10
val += int(b[i] - 0x30)
}
return val
}
// returns the string read as a bytes slice, wheter the value is NULL,
// the number of bytes read and an error, in case the string is longer than
// the input slice
func readLengthEncodedString(b []byte) ([]byte, bool, int, error) {
// Get length
num, isNull, n := readLengthEncodedInteger(b)
if num < 1 {
return b[n:n], isNull, n, nil
}
n += int(num)
// Check data length
if len(b) >= n {
return b[n-int(num) : n], false, n, nil
}
return nil, false, n, io.EOF
}
// returns the number of bytes skipped and an error, in case the string is
// longer than the input slice
func skipLengthEncodedString(b []byte) (int, error) {
// Get length
num, _, n := readLengthEncodedInteger(b)
if num < 1 {
return n, nil
}
n += int(num)
// Check data length
if len(b) >= n {
return n, nil
}
return n, io.EOF
}
// returns the number read, whether the value is NULL and the number of bytes read
func readLengthEncodedInteger(b []byte) (uint64, bool, int) {
switch b[0] {
// 251: NULL
case 0xfb:
return 0, true, 1
// 252: value of following 2
case 0xfc:
return uint64(b[1]) | uint64(b[2])<<8, false, 3
// 253: value of following 3
case 0xfd:
return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16, false, 4
// 254: value of following 8
case 0xfe:
return uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16 |
uint64(b[4])<<24 | uint64(b[5])<<32 | uint64(b[6])<<40 |
uint64(b[7])<<48 | uint64(b[8])<<56,
false, 9
}
// 0-250: value of first byte
return uint64(b[0]), false, 1
}
// encodes a uint64 value and appends it to the given bytes slice
func appendLengthEncodedInteger(b []byte, n uint64) []byte {
switch {
case n <= 250:
return append(b, byte(n))
case n <= 0xffff:
return append(b, 0xfc, byte(n), byte(n>>8))
case n <= 0xffffff:
return append(b, 0xfd, byte(n), byte(n>>8), byte(n>>16))
}
return append(b, 0xfe, byte(n), byte(n>>8), byte(n>>16), byte(n>>24),
byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56))
}
// reserveBuffer checks cap(buf) and expand buffer to len(buf) + appendSize.
// If cap(buf) is not enough, reallocate new buffer.
func reserveBuffer(buf []byte, appendSize int) []byte {
newSize := len(buf) + appendSize
if cap(buf) < newSize {
// Grow buffer exponentially
newBuf := make([]byte, len(buf)*2+appendSize)
copy(newBuf, buf)
buf = newBuf
}
return buf[:newSize]
}
// escapeBytesBackslash escapes []byte with backslashes (\)
// This escapes the contents of a string (provided as []byte) by adding backslashes before special
// characters, and turning others into specific escape sequences, such as
// turning newlines into \n and null bytes into \0.
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L823-L932
func escapeBytesBackslash(buf, v []byte) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for _, c := range v {
switch c {
case '\x00':
buf[pos] = '\\'
buf[pos+1] = '0'
pos += 2
case '\n':
buf[pos] = '\\'
buf[pos+1] = 'n'
pos += 2
case '\r':
buf[pos] = '\\'
buf[pos+1] = 'r'
pos += 2
case '\x1a':
buf[pos] = '\\'
buf[pos+1] = 'Z'
pos += 2
case '\'':
buf[pos] = '\\'
buf[pos+1] = '\''
pos += 2
case '"':
buf[pos] = '\\'
buf[pos+1] = '"'
pos += 2
case '\\':
buf[pos] = '\\'
buf[pos+1] = '\\'
pos += 2
default:
buf[pos] = c
pos += 1
}
}
return buf[:pos]
}
// escapeStringBackslash is similar to escapeBytesBackslash but for string.
func escapeStringBackslash(buf []byte, v string) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for i := 0; i < len(v); i++ {
c := v[i]
switch c {
case '\x00':
buf[pos] = '\\'
buf[pos+1] = '0'
pos += 2
case '\n':
buf[pos] = '\\'
buf[pos+1] = 'n'
pos += 2
case '\r':
buf[pos] = '\\'
buf[pos+1] = 'r'
pos += 2
case '\x1a':
buf[pos] = '\\'
buf[pos+1] = 'Z'
pos += 2
case '\'':
buf[pos] = '\\'
buf[pos+1] = '\''
pos += 2
case '"':
buf[pos] = '\\'
buf[pos+1] = '"'
pos += 2
case '\\':
buf[pos] = '\\'
buf[pos+1] = '\\'
pos += 2
default:
buf[pos] = c
pos += 1
}
}
return buf[:pos]
}
// escapeBytesQuotes escapes apostrophes in []byte by doubling them up.
// This escapes the contents of a string by doubling up any apostrophes that
// it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
// effect on the server.
// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/mysys/charset.c#L963-L1038
func escapeBytesQuotes(buf, v []byte) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for _, c := range v {
if c == '\'' {
buf[pos] = '\''
buf[pos+1] = '\''
pos += 2
} else {
buf[pos] = c
pos++
}
}
return buf[:pos]
}
// escapeStringQuotes is similar to escapeBytesQuotes but for string.
func escapeStringQuotes(buf []byte, v string) []byte {
pos := len(buf)
buf = reserveBuffer(buf, len(v)*2)
for i := 0; i < len(v); i++ {
c := v[i]
if c == '\'' {
buf[pos] = '\''
buf[pos+1] = '\''
pos += 2
} else {
buf[pos] = c
pos++
}
}
return buf[:pos]
}

346
Godeps/_workspace/src/github.com/go-sql-driver/mysql/utils_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,346 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"bytes"
"crypto/tls"
"encoding/binary"
"fmt"
"testing"
"time"
)
var testDSNs = []struct {
in string
out string
loc *time.Location
}{
{"username:password@protocol(address)/dbname?param=value", "&{user:username passwd:password net:protocol addr:address dbname:dbname params:map[param:value] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"username:password@protocol(address)/dbname?param=value&columnsWithAlias=true", "&{user:username passwd:password net:protocol addr:address dbname:dbname params:map[param:value] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:true interpolateParams:false}", time.UTC},
{"user@unix(/path/to/socket)/dbname?charset=utf8", "&{user:user passwd: net:unix addr:/path/to/socket dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8mb4,utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"user:password@/dbname?loc=UTC&timeout=30s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci", "&{user:user passwd:password net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:30000000000 collation:224 allowAllFiles:true allowOldPasswords:true clientFoundRows:true columnsWithAlias:false interpolateParams:false}", time.UTC},
{"user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local", "&{user:user passwd:p@ss(word) net:tcp addr:[de:ad:be:ef::ca:fe]:80 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.Local},
{"/dbname", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"@/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"user:p@/ssword@/", "&{user:user passwd:p@/ssword net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
{"unix/?arg=%2Fsome%2Fpath.ext", "&{user: passwd: net:unix addr:/tmp/mysql.sock dbname: params:map[arg:/some/path.ext] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
}
func TestDSNParser(t *testing.T) {
var cfg *config
var err error
var res string
for i, tst := range testDSNs {
cfg, err = parseDSN(tst.in)
if err != nil {
t.Error(err.Error())
}
// pointer not static
cfg.tls = nil
res = fmt.Sprintf("%+v", cfg)
if res != fmt.Sprintf(tst.out, tst.loc) {
t.Errorf("%d. parseDSN(%q) => %q, want %q", i, tst.in, res, fmt.Sprintf(tst.out, tst.loc))
}
}
}
func TestDSNParserInvalid(t *testing.T) {
var invalidDSNs = []string{
"@net(addr/", // no closing brace
"@tcp(/", // no closing brace
"tcp(/", // no closing brace
"(/", // no closing brace
"net(addr)//", // unescaped
"user:pass@tcp(1.2.3.4:3306)", // no trailing slash
//"/dbname?arg=/some/unescaped/path",
}
for i, tst := range invalidDSNs {
if _, err := parseDSN(tst); err == nil {
t.Errorf("invalid DSN #%d. (%s) didn't error!", i, tst)
}
}
}
func TestDSNWithCustomTLS(t *testing.T) {
baseDSN := "user:password@tcp(localhost:5555)/dbname?tls="
tlsCfg := tls.Config{}
RegisterTLSConfig("utils_test", &tlsCfg)
// Custom TLS is missing
tst := baseDSN + "invalid_tls"
cfg, err := parseDSN(tst)
if err == nil {
t.Errorf("Invalid custom TLS in DSN (%s) but did not error. Got config: %#v", tst, cfg)
}
tst = baseDSN + "utils_test"
// Custom TLS with a server name
name := "foohost"
tlsCfg.ServerName = name
cfg, err = parseDSN(tst)
if err != nil {
t.Error(err.Error())
} else if cfg.tls.ServerName != name {
t.Errorf("Did not get the correct TLS ServerName (%s) parsing DSN (%s).", name, tst)
}
// Custom TLS without a server name
name = "localhost"
tlsCfg.ServerName = ""
cfg, err = parseDSN(tst)
if err != nil {
t.Error(err.Error())
} else if cfg.tls.ServerName != name {
t.Errorf("Did not get the correct ServerName (%s) parsing DSN (%s).", name, tst)
}
DeregisterTLSConfig("utils_test")
}
func TestDSNUnsafeCollation(t *testing.T) {
_, err := parseDSN("/dbname?collation=gbk_chinese_ci&interpolateParams=true")
if err != errInvalidDSNUnsafeCollation {
t.Error("Expected %v, Got %v", errInvalidDSNUnsafeCollation, err)
}
_, err = parseDSN("/dbname?collation=gbk_chinese_ci&interpolateParams=false")
if err != nil {
t.Error("Expected %v, Got %v", nil, err)
}
_, err = parseDSN("/dbname?collation=gbk_chinese_ci")
if err != nil {
t.Error("Expected %v, Got %v", nil, err)
}
_, err = parseDSN("/dbname?collation=ascii_bin&interpolateParams=true")
if err != nil {
t.Error("Expected %v, Got %v", nil, err)
}
_, err = parseDSN("/dbname?collation=latin1_german1_ci&interpolateParams=true")
if err != nil {
t.Error("Expected %v, Got %v", nil, err)
}
_, err = parseDSN("/dbname?collation=utf8_general_ci&interpolateParams=true")
if err != nil {
t.Error("Expected %v, Got %v", nil, err)
}
_, err = parseDSN("/dbname?collation=utf8mb4_general_ci&interpolateParams=true")
if err != nil {
t.Error("Expected %v, Got %v", nil, err)
}
}
func BenchmarkParseDSN(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, tst := range testDSNs {
if _, err := parseDSN(tst.in); err != nil {
b.Error(err.Error())
}
}
}
}
func TestScanNullTime(t *testing.T) {
var scanTests = []struct {
in interface{}
error bool
valid bool
time time.Time
}{
{tDate, false, true, tDate},
{sDate, false, true, tDate},
{[]byte(sDate), false, true, tDate},
{tDateTime, false, true, tDateTime},
{sDateTime, false, true, tDateTime},
{[]byte(sDateTime), false, true, tDateTime},
{tDate0, false, true, tDate0},
{sDate0, false, true, tDate0},
{[]byte(sDate0), false, true, tDate0},
{sDateTime0, false, true, tDate0},
{[]byte(sDateTime0), false, true, tDate0},
{"", true, false, tDate0},
{"1234", true, false, tDate0},
{0, true, false, tDate0},
}
var nt = NullTime{}
var err error
for _, tst := range scanTests {
err = nt.Scan(tst.in)
if (err != nil) != tst.error {
t.Errorf("%v: expected error status %t, got %t", tst.in, tst.error, (err != nil))
}
if nt.Valid != tst.valid {
t.Errorf("%v: expected valid status %t, got %t", tst.in, tst.valid, nt.Valid)
}
if nt.Time != tst.time {
t.Errorf("%v: expected time %v, got %v", tst.in, tst.time, nt.Time)
}
}
}
func TestLengthEncodedInteger(t *testing.T) {
var integerTests = []struct {
num uint64
encoded []byte
}{
{0x0000000000000000, []byte{0x00}},
{0x0000000000000012, []byte{0x12}},
{0x00000000000000fa, []byte{0xfa}},
{0x0000000000000100, []byte{0xfc, 0x00, 0x01}},
{0x0000000000001234, []byte{0xfc, 0x34, 0x12}},
{0x000000000000ffff, []byte{0xfc, 0xff, 0xff}},
{0x0000000000010000, []byte{0xfd, 0x00, 0x00, 0x01}},
{0x0000000000123456, []byte{0xfd, 0x56, 0x34, 0x12}},
{0x0000000000ffffff, []byte{0xfd, 0xff, 0xff, 0xff}},
{0x0000000001000000, []byte{0xfe, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}},
{0x123456789abcdef0, []byte{0xfe, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12}},
{0xffffffffffffffff, []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
}
for _, tst := range integerTests {
num, isNull, numLen := readLengthEncodedInteger(tst.encoded)
if isNull {
t.Errorf("%x: expected %d, got NULL", tst.encoded, tst.num)
}
if num != tst.num {
t.Errorf("%x: expected %d, got %d", tst.encoded, tst.num, num)
}
if numLen != len(tst.encoded) {
t.Errorf("%x: expected size %d, got %d", tst.encoded, len(tst.encoded), numLen)
}
encoded := appendLengthEncodedInteger(nil, num)
if !bytes.Equal(encoded, tst.encoded) {
t.Errorf("%v: expected %x, got %x", num, tst.encoded, encoded)
}
}
}
func TestOldPass(t *testing.T) {
scramble := []byte{9, 8, 7, 6, 5, 4, 3, 2}
vectors := []struct {
pass string
out string
}{
{" pass", "47575c5a435b4251"},
{"pass ", "47575c5a435b4251"},
{"123\t456", "575c47505b5b5559"},
{"C0mpl!ca ted#PASS123", "5d5d554849584a45"},
}
for _, tuple := range vectors {
ours := scrambleOldPassword(scramble, []byte(tuple.pass))
if tuple.out != fmt.Sprintf("%x", ours) {
t.Errorf("Failed old password %q", tuple.pass)
}
}
}
func TestFormatBinaryDateTime(t *testing.T) {
rawDate := [11]byte{}
binary.LittleEndian.PutUint16(rawDate[:2], 1978) // years
rawDate[2] = 12 // months
rawDate[3] = 30 // days
rawDate[4] = 15 // hours
rawDate[5] = 46 // minutes
rawDate[6] = 23 // seconds
binary.LittleEndian.PutUint32(rawDate[7:], 987654) // microseconds
expect := func(expected string, inlen, outlen uint8) {
actual, _ := formatBinaryDateTime(rawDate[:inlen], outlen, false)
bytes, ok := actual.([]byte)
if !ok {
t.Errorf("formatBinaryDateTime must return []byte, was %T", actual)
}
if string(bytes) != expected {
t.Errorf(
"expected %q, got %q for length in %d, out %d",
bytes, actual, inlen, outlen,
)
}
}
expect("0000-00-00", 0, 10)
expect("0000-00-00 00:00:00", 0, 19)
expect("1978-12-30", 4, 10)
expect("1978-12-30 15:46:23", 7, 19)
expect("1978-12-30 15:46:23.987654", 11, 26)
}
func TestEscapeBackslash(t *testing.T) {
expect := func(expected, value string) {
actual := string(escapeBytesBackslash([]byte{}, []byte(value)))
if actual != expected {
t.Errorf(
"expected %s, got %s",
expected, actual,
)
}
actual = string(escapeStringBackslash([]byte{}, value))
if actual != expected {
t.Errorf(
"expected %s, got %s",
expected, actual,
)
}
}
expect("foo\\0bar", "foo\x00bar")
expect("foo\\nbar", "foo\nbar")
expect("foo\\rbar", "foo\rbar")
expect("foo\\Zbar", "foo\x1abar")
expect("foo\\\"bar", "foo\"bar")
expect("foo\\\\bar", "foo\\bar")
expect("foo\\'bar", "foo'bar")
}
func TestEscapeQuotes(t *testing.T) {
expect := func(expected, value string) {
actual := string(escapeBytesQuotes([]byte{}, []byte(value)))
if actual != expected {
t.Errorf(
"expected %s, got %s",
expected, actual,
)
}
actual = string(escapeStringQuotes([]byte{}, value))
if actual != expected {
t.Errorf(
"expected %s, got %s",
expected, actual,
)
}
}
expect("foo\x00bar", "foo\x00bar") // not affected
expect("foo\nbar", "foo\nbar") // not affected
expect("foo\rbar", "foo\rbar") // not affected
expect("foo\x1abar", "foo\x1abar") // not affected
expect("foo''bar", "foo'bar") // affected
expect("foo\"bar", "foo\"bar") // not affected
}

74
Godeps/_workspace/src/github.com/goamz/goamz/aws/attempt.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,74 @@
package aws
import (
"time"
)
// 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.
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
}
type Attempt struct {
strategy AttemptStrategy
last time.Time
end time.Time
force bool
count int
}
// Start begins a new sequence of attempts for the given strategy.
func (s AttemptStrategy) Start() *Attempt {
now := time.Now()
return &Attempt{
strategy: s,
last: now,
end: now.Add(s.Total),
force: true,
}
}
// Next waits until it is time to perform the next attempt or returns
// false if it is time to stop trying.
func (a *Attempt) Next() bool {
now := time.Now()
sleep := a.nextSleep(now)
if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count {
return false
}
a.force = false
if sleep > 0 && a.count > 0 {
time.Sleep(sleep)
now = time.Now()
}
a.count++
a.last = now
return true
}
func (a *Attempt) nextSleep(now time.Time) time.Duration {
sleep := a.strategy.Delay - now.Sub(a.last)
if sleep < 0 {
return 0
}
return sleep
}
// 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 (a *Attempt) HasNext() bool {
if a.force || a.strategy.Min > a.count {
return true
}
now := time.Now()
if now.Add(a.nextSleep(now)).Before(a.end) {
a.force = true
return true
}
return false
}

58
Godeps/_workspace/src/github.com/goamz/goamz/aws/attempt_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,58 @@
package aws_test
import (
"time"
"github.com/goamz/goamz/aws"
. "gopkg.in/check.v1"
)
func (S) TestAttemptTiming(c *C) {
testAttempt := aws.AttemptStrategy{
Total: 0.25e9,
Delay: 0.1e9,
}
want := []time.Duration{0, 0.1e9, 0.2e9, 0.2e9}
got := make([]time.Duration, 0, len(want)) // avoid allocation when testing timing
t0 := time.Now()
for a := testAttempt.Start(); a.Next(); {
got = append(got, time.Now().Sub(t0))
}
got = append(got, time.Now().Sub(t0))
c.Assert(got, HasLen, len(want))
const margin = 0.01e9
for i, got := range want {
lo := want[i] - margin
hi := want[i] + margin
if got < lo || got > hi {
c.Errorf("attempt %d want %g got %g", i, want[i].Seconds(), got.Seconds())
}
}
}
func (S) TestAttemptNextHasNext(c *C) {
a := aws.AttemptStrategy{}.Start()
c.Assert(a.Next(), Equals, true)
c.Assert(a.Next(), Equals, false)
a = aws.AttemptStrategy{}.Start()
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, false)
c.Assert(a.Next(), Equals, false)
a = aws.AttemptStrategy{Total: 2e8}.Start()
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, true)
time.Sleep(2e8)
c.Assert(a.HasNext(), Equals, true)
c.Assert(a.Next(), Equals, true)
c.Assert(a.Next(), Equals, false)
a = aws.AttemptStrategy{Total: 1e8, Min: 2}.Start()
time.Sleep(1e8)
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, true)
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, false)
c.Assert(a.Next(), Equals, false)
}

431
Godeps/_workspace/src/github.com/goamz/goamz/aws/aws.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,431 @@
//
// 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>
//
package aws
import (
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"time"
"github.com/vaughan0/go-ini"
)
// Defines the valid signers
const (
V2Signature = iota
V4Signature = iota
Route53Signature = iota
)
// Defines the service endpoint and correct Signer implementation to use
// to sign requests for this endpoint
type ServiceInfo struct {
Endpoint string
Signer uint
}
// Region defines the URLs where AWS services may be accessed.
//
// See http://goo.gl/d8BP1 for more details.
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
}
var Regions = map[string]Region{
APNortheast.Name: APNortheast,
APSoutheast.Name: APSoutheast,
APSoutheast2.Name: APSoutheast2,
EUCentral.Name: EUCentral,
EUWest.Name: EUWest,
USEast.Name: USEast,
USWest.Name: USWest,
USWest2.Name: USWest2,
USGovWest.Name: USGovWest,
SAEast.Name: SAEast,
CNNorth.Name: CNNorth,
}
// 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 Signer interface {
Sign(method, path string, params map[string]string)
}
// 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 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
}
// Implements a Server Query/Post API to easily query AWS services and build
// errors when desired
type Service struct {
service ServiceInfo
signer Signer
}
// Create a base set of params for an action
func MakeParams(action string) map[string]string {
params := make(map[string]string)
params["Action"] = action
return params
}
// Create a new AWS server to handle making requests
func NewService(auth Auth, service ServiceInfo) (s *Service, err error) {
var signer Signer
switch service.Signer {
case V2Signature:
signer, err = NewV2Signer(auth, service)
// case V4Signature:
// signer, err = NewV4Signer(auth, service, Regions["eu-west-1"])
default:
err = fmt.Errorf("Unsupported signer for service")
}
if err != nil {
return
}
s = &Service{service: service, signer: signer}
return
}
func (s *Service) Query(method, path string, params map[string]string) (resp *http.Response, err error) {
params["Timestamp"] = time.Now().UTC().Format(time.RFC3339)
u, err := url.Parse(s.service.Endpoint)
if err != nil {
return nil, err
}
u.Path = path
s.signer.Sign(method, path, params)
if method == "GET" {
u.RawQuery = multimap(params).Encode()
resp, err = http.Get(u.String())
} else if method == "POST" {
resp, err = http.PostForm(u.String(), multimap(params))
}
return
}
func (s *Service) BuildError(r *http.Response) error {
errors := ErrorResponse{}
xml.NewDecoder(r.Body).Decode(&errors)
var err Error
err = errors.Errors
err.RequestId = errors.RequestId
err.StatusCode = r.StatusCode
if err.Message == "" {
err.Message = r.Status
}
return &err
}
type ErrorResponse struct {
Errors Error `xml:"Error"`
RequestId string // A unique ID for tracking the request
}
type Error struct {
StatusCode int
Type string
Code string
Message string
RequestId string
}
func (err *Error) Error() string {
return fmt.Sprintf("Type: %s, Code: %s, Message: %s",
err.Type, err.Code, err.Message,
)
}
type Auth struct {
AccessKey, SecretKey string
token string
expiration time.Time
}
func (a *Auth) Token() string {
if a.token == "" {
return ""
}
if time.Since(a.expiration) >= -30*time.Second { //in an ideal world this should be zero assuming the instance is synching it's clock
*a, _ = GetAuth("", "", "", time.Time{})
}
return a.token
}
func (a *Auth) Expiration() time.Time {
return a.expiration
}
// To be used with other APIs that return auth credentials such as STS
func NewAuth(accessKey, secretKey, token string, expiration time.Time) *Auth {
return &Auth{
AccessKey: accessKey,
SecretKey: secretKey,
token: token,
expiration: expiration,
}
}
// ResponseMetadata
type ResponseMetadata struct {
RequestId string // A unique ID for tracking the request
}
type BaseResponse struct {
ResponseMetadata ResponseMetadata
}
var unreserved = make([]bool, 128)
var hex = "0123456789ABCDEF"
func init() {
// RFC3986
u := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_.~"
for _, c := range u {
unreserved[c] = true
}
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
type credentials struct {
Code string
LastUpdated string
Type string
AccessKeyId string
SecretAccessKey string
Token string
Expiration string
}
// 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 GetMetaData(path string) (contents []byte, err error) {
url := "http://169.254.169.254/latest/meta-data/" + path
resp, err := RetryingClient.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return []byte(body), err
}
func getInstanceCredentials() (cred credentials, err error) {
credentialPath := "iam/security-credentials/"
// Get the instance role
role, err := GetMetaData(credentialPath)
if err != nil {
return
}
// Get the instance role credentials
credentialJSON, err := GetMetaData(credentialPath + string(role))
if err != nil {
return
}
err = json.Unmarshal([]byte(credentialJSON), &cred)
return
}
// GetAuth creates an Auth based on either passed in credentials,
// environment information or instance based role credentials.
func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error) {
// First try passed in credentials
if accessKey != "" && secretKey != "" {
return Auth{accessKey, secretKey, token, expiration}, nil
}
// Next try to get auth from the shared credentials file
auth, err = SharedAuth()
if err == nil {
// Found auth, return
return
}
// Next try to get auth from the environment
auth, err = EnvAuth()
if err == nil {
// Found auth, return
return
}
// Next try getting auth from the instance role
cred, err := getInstanceCredentials()
if err == nil {
// Found auth, return
auth.AccessKey = cred.AccessKeyId
auth.SecretKey = cred.SecretAccessKey
auth.token = cred.Token
exptdate, err := time.Parse("2006-01-02T15:04:05Z", cred.Expiration)
if err != nil {
err = fmt.Errorf("Error Parseing expiration date: cred.Expiration :%s , error: %s \n", cred.Expiration, err)
}
auth.expiration = exptdate
return auth, err
}
err = errors.New("No valid AWS authentication found")
return auth, err
}
// 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 EnvAuth() (auth Auth, err error) {
auth.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
if auth.AccessKey == "" {
auth.AccessKey = os.Getenv("AWS_ACCESS_KEY")
}
auth.SecretKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
if auth.SecretKey == "" {
auth.SecretKey = os.Getenv("AWS_SECRET_KEY")
}
if auth.AccessKey == "" {
err = errors.New("AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
}
if auth.SecretKey == "" {
err = errors.New("AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
}
auth.token = os.Getenv("AWS_SESSION_TOKEN")
return
}
// 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 SharedAuth() (auth Auth, err error) {
var profileName = os.Getenv("AWS_PROFILE")
if profileName == "" {
profileName = "default"
}
var credentialsFile = os.Getenv("AWS_CREDENTIAL_FILE")
if credentialsFile == "" {
var homeDir = os.Getenv("HOME")
if homeDir == "" {
err = errors.New("Could not get HOME")
return
}
credentialsFile = homeDir + "/.aws/credentials"
}
file, err := ini.LoadFile(credentialsFile)
if err != nil {
err = errors.New("Couldn't parse AWS credentials file")
return
}
var profile = file[profileName]
if profile == nil {
err = errors.New("Couldn't find profile in AWS credentials file")
return
}
auth.AccessKey = profile["aws_access_key_id"]
auth.SecretKey = profile["aws_secret_access_key"]
if auth.AccessKey == "" {
err = errors.New("AWS_ACCESS_KEY_ID not found in environment in credentials file")
}
if auth.SecretKey == "" {
err = errors.New("AWS_SECRET_ACCESS_KEY not found in credentials file")
}
return
}
// Encode takes a string and URI-encodes it in a way suitable
// to be used in AWS signatures.
func Encode(s string) string {
encode := false
for i := 0; i != len(s); i++ {
c := s[i]
if c > 127 || !unreserved[c] {
encode = true
break
}
}
if !encode {
return s
}
e := make([]byte, len(s)*3)
ei := 0
for i := 0; i != len(s); i++ {
c := s[i]
if c > 127 || !unreserved[c] {
e[ei] = '%'
e[ei+1] = hex[c>>4]
e[ei+2] = hex[c&0xF]
ei += 3
} else {
e[ei] = c
ei += 1
}
}
return string(e[:ei])
}

211
Godeps/_workspace/src/github.com/goamz/goamz/aws/aws_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,211 @@
package aws_test
import (
"io/ioutil"
"os"
"strings"
"testing"
"time"
"github.com/goamz/goamz/aws"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) {
TestingT(t)
}
var _ = Suite(&S{})
type S struct {
environ []string
}
func (s *S) SetUpSuite(c *C) {
s.environ = os.Environ()
}
func (s *S) TearDownTest(c *C) {
os.Clearenv()
for _, kv := range s.environ {
l := strings.SplitN(kv, "=", 2)
os.Setenv(l[0], l[1])
}
}
func (s *S) TestSharedAuthNoHome(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "foo")
_, err := aws.SharedAuth()
c.Assert(err, ErrorMatches, "Could not get HOME")
}
func (s *S) TestSharedAuthNoCredentialsFile(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "foo")
os.Setenv("HOME", "/tmp")
_, err := aws.SharedAuth()
c.Assert(err, ErrorMatches, "Couldn't parse AWS credentials file")
}
func (s *S) TestSharedAuthNoProfileInFile(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "foo")
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\n"), 0644)
os.Setenv("HOME", d)
_, err = aws.SharedAuth()
c.Assert(err, ErrorMatches, "Couldn't find profile in AWS credentials file")
}
func (s *S) TestSharedAuthNoKeysInProfile(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "bar")
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\nawsaccesskeyid = AK.."), 0644)
os.Setenv("HOME", d)
_, err = aws.SharedAuth()
c.Assert(err, ErrorMatches, "AWS_SECRET_ACCESS_KEY not found in credentials file")
}
func (s *S) TestSharedAuthDefaultCredentials(c *C) {
os.Clearenv()
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[default]\naws_access_key_id = access\naws_secret_access_key = secret\n"), 0644)
os.Setenv("HOME", d)
auth, err := aws.SharedAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestSharedAuth(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "bar")
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\naws_access_key_id = access\naws_secret_access_key = secret\n"), 0644)
os.Setenv("HOME", d)
auth, err := aws.SharedAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEnvAuthNoSecret(c *C) {
os.Clearenv()
_, err := aws.EnvAuth()
c.Assert(err, ErrorMatches, "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
}
func (s *S) TestEnvAuthNoAccess(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_ACCESS_KEY", "foo")
_, err := aws.EnvAuth()
c.Assert(err, ErrorMatches, "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
}
func (s *S) TestEnvAuth(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY_ID", "access")
auth, err := aws.EnvAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEnvAuthAlt(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY", "access")
auth, err := aws.EnvAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEnvAuthToken(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY", "access")
os.Setenv("AWS_SESSION_TOKEN", "token")
auth, err := aws.EnvAuth()
c.Assert(err, IsNil)
c.Assert(auth.SecretKey, Equals, "secret")
c.Assert(auth.AccessKey, Equals, "access")
c.Assert(auth.Token(), Equals, "token")
}
func (s *S) TestGetAuthStatic(c *C) {
exptdate := time.Now().Add(time.Hour)
auth, err := aws.GetAuth("access", "secret", "token", exptdate)
c.Assert(err, IsNil)
c.Assert(auth.AccessKey, Equals, "access")
c.Assert(auth.SecretKey, Equals, "secret")
c.Assert(auth.Token(), Equals, "token")
c.Assert(auth.Expiration(), Equals, exptdate)
}
func (s *S) TestGetAuthEnv(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY_ID", "access")
auth, err := aws.GetAuth("", "", "", time.Time{})
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEncode(c *C) {
c.Assert(aws.Encode("foo"), Equals, "foo")
c.Assert(aws.Encode("/"), Equals, "%2F")
}
func (s *S) TestRegionsAreNamed(c *C) {
for n, r := range aws.Regions {
c.Assert(n, Equals, r.Name)
}
}

124
Godeps/_workspace/src/github.com/goamz/goamz/aws/client.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,124 @@
package aws
import (
"math"
"net"
"net/http"
"time"
)
type RetryableFunc func(*http.Request, *http.Response, error) bool
type WaitFunc func(try int)
type DeadlineFunc func() time.Time
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
transport *http.Transport
}
// Convenience method for creating an http client
func NewClient(rt *ResilientTransport) *http.Client {
rt.transport = &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, rt.DialTimeout)
if err != nil {
return nil, err
}
c.SetDeadline(rt.Deadline())
return c, nil
},
Proxy: http.ProxyFromEnvironment,
}
// TODO: Would be nice is ResilientTransport allowed clients to initialize
// with http.Transport attributes.
return &http.Client{
Transport: rt,
}
}
var retryingTransport = &ResilientTransport{
Deadline: func() time.Time {
return time.Now().Add(5 * time.Second)
},
DialTimeout: 10 * time.Second,
MaxTries: 3,
ShouldRetry: awsRetry,
Wait: ExpBackoff,
}
// Exported default client
var RetryingClient = NewClient(retryingTransport)
func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return t.tries(req)
}
// Retry a request a maximum of t.MaxTries times.
// We'll only retry if the proper criteria are met.
// If a wait function is specified, wait that amount of time
// In between requests.
func (t *ResilientTransport) tries(req *http.Request) (res *http.Response, err error) {
for try := 0; try < t.MaxTries; try += 1 {
res, err = t.transport.RoundTrip(req)
if !t.ShouldRetry(req, res, err) {
break
}
if res != nil {
res.Body.Close()
}
if t.Wait != nil {
t.Wait(try)
}
}
return
}
func ExpBackoff(try int) {
time.Sleep(100 * time.Millisecond *
time.Duration(math.Exp2(float64(try))))
}
func LinearBackoff(try int) {
time.Sleep(time.Duration(try*100) * time.Millisecond)
}
// Decide if we should retry a request.
// In general, the criteria for retrying a request is described here
// http://docs.aws.amazon.com/general/latest/gr/api-retries.html
func awsRetry(req *http.Request, res *http.Response, err error) bool {
retry := false
// Retry if there's a temporary network error.
if neterr, ok := err.(net.Error); ok {
if neterr.Temporary() {
retry = true
}
}
// Retry if we get a 5xx series error.
if res != nil {
if res.StatusCode >= 500 && res.StatusCode < 600 {
retry = true
}
}
return retry
}

121
Godeps/_workspace/src/github.com/goamz/goamz/aws/client_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,121 @@
package aws_test
import (
"fmt"
"github.com/goamz/goamz/aws"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
// Retrieve the response from handler using aws.RetryingClient
func serveAndGet(handler http.HandlerFunc) (body string, err error) {
ts := httptest.NewServer(handler)
defer ts.Close()
resp, err := aws.RetryingClient.Get(ts.URL)
if err != nil {
return
}
if resp.StatusCode != 200 {
return "", fmt.Errorf("Bad status code: %d", resp.StatusCode)
}
greeting, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}
return strings.TrimSpace(string(greeting)), nil
}
func TestClient_expected(t *testing.T) {
body := "foo bar"
resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, body)
})
if err != nil {
t.Fatal(err)
}
if resp != body {
t.Fatal("Body not as expected.")
}
}
func TestClient_delay(t *testing.T) {
body := "baz"
wait := 4
resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
if wait < 0 {
// If we dipped to zero delay and still failed.
t.Fatal("Never succeeded.")
}
wait -= 1
time.Sleep(time.Second * time.Duration(wait))
fmt.Fprintln(w, body)
})
if err != nil {
t.Fatal(err)
}
if resp != body {
t.Fatal("Body not as expected.", resp)
}
}
func TestClient_no4xxRetry(t *testing.T) {
tries := 0
// Fail once before succeeding.
_, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
tries += 1
http.Error(w, "error", 404)
})
if err == nil {
t.Fatal("should have error")
}
if tries != 1 {
t.Fatalf("should only try once: %d", tries)
}
}
func TestClient_retries(t *testing.T) {
body := "biz"
failed := false
// Fail once before succeeding.
resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
if !failed {
http.Error(w, "error", 500)
failed = true
} else {
fmt.Fprintln(w, body)
}
})
if failed != true {
t.Error("We didn't retry!")
}
if err != nil {
t.Fatal(err)
}
if resp != body {
t.Fatal("Body not as expected.")
}
}
func TestClient_fails(t *testing.T) {
tries := 0
// Fail 3 times and return the last error.
_, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
tries += 1
http.Error(w, "error", 500)
})
if err == nil {
t.Fatal(err)
}
if tries != 3 {
t.Fatal("Didn't retry enough")
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше