From 922e8ca0eb056a02f9919c80d012362b6b1756ed Mon Sep 17 00:00:00 2001 From: Ids van der Molen Date: Thu, 27 Jun 2019 19:11:16 +0200 Subject: [PATCH 01/63] Separate build and runtime to reduce image footprint --- Dockerfile | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 07363a4..7832a96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,14 @@ -FROM golang:alpine +FROM golang:alpine AS build -RUN apk add --no-cache --virtual git openssl ca-certificates && \ - go get github.com/messagebird/sachet/cmd/... && \ - rm -rf src pkg && \ - apk del git +RUN apk update && \ + apk add --no-cache git openssl ca-certificates && \ + go get github.com/messagebird/sachet/cmd/... +FROM alpine +COPY --from=build /go/bin/sachet /usr/local/bin COPY examples/config.yaml /etc/sachet/config.yaml +RUN apk update && \ + apk add --no-cache ca-certificates EXPOSE 9876 ENTRYPOINT ["sachet"] From 12fcf4795fdb9043fff79b77b1cd81d559060eb7 Mon Sep 17 00:00:00 2001 From: Ids van der Molen Date: Fri, 28 Jun 2019 09:35:17 +0200 Subject: [PATCH 02/63] Run as user nobody --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7832a96..ed5ddde 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,10 +6,11 @@ RUN apk update && \ FROM alpine COPY --from=build /go/bin/sachet /usr/local/bin -COPY examples/config.yaml /etc/sachet/config.yaml +COPY --chown=nobody examples/config.yaml /etc/sachet/config.yaml RUN apk update && \ apk add --no-cache ca-certificates +USER nobody EXPOSE 9876 ENTRYPOINT ["sachet"] CMD ["-config", "/etc/sachet/config.yaml"] From edace8fd8be371d537aa970cda125b8642e226aa Mon Sep 17 00:00:00 2001 From: Luke Addison Date: Sat, 10 Aug 2019 19:17:33 +0100 Subject: [PATCH 03/63] Update vendor --- Gopkg.lock | 63 ++- .../xconstruct/go-pushbullet/.travis.yml | 7 + .../xconstruct/go-pushbullet/LICENSE | 21 + .../xconstruct/go-pushbullet/README.md | 79 ++++ .../xconstruct/go-pushbullet/pushbullet.go | 423 ++++++++++++++++++ 5 files changed, 588 insertions(+), 5 deletions(-) create mode 100644 vendor/github.com/xconstruct/go-pushbullet/.travis.yml create mode 100644 vendor/github.com/xconstruct/go-pushbullet/LICENSE create mode 100644 vendor/github.com/xconstruct/go-pushbullet/README.md create mode 100644 vendor/github.com/xconstruct/go-pushbullet/pushbullet.go diff --git a/Gopkg.lock b/Gopkg.lock index 3120de8..a8effd2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,131 +3,184 @@ [[projects]] branch = "master" + digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" name = "github.com/beorn7/perks" packages = ["quantile"] + pruneopts = "UT" revision = "3a771d992973f24aa725d07868b467d1ddfceafb" [[projects]] + digest = "1:004d308dffe0ab15d83f7dc98ec8c42c843666df1a50537a4ff38ed4cf187f2c" name = "github.com/carlosdp/twiliogo" packages = ["."] + pruneopts = "UT" revision = "f61c8230fa91b87ca5c16a21a661861208749dfe" version = "v0.1" [[projects]] + digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "UT" revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" [[projects]] + digest = "1:15042ad3498153684d09f393bbaec6b216c8eec6d61f63dff711de7d64ed8861" name = "github.com/golang/protobuf" packages = ["proto"] + pruneopts = "UT" revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" version = "v1.1.0" [[projects]] + digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6" name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] + pruneopts = "UT" revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" version = "v1.0.0" [[projects]] branch = "master" + digest = "1:98dc904e7724bf8f5b26809d39fb706d37b45fa30a838240b334dfbadc7befbb" name = "github.com/messagebird/go-rest-api" packages = ["."] + pruneopts = "UT" revision = "a9514230491e7db6adaa58162cce34a5df987fd4" [[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" name = "github.com/pmezard/go-difflib" packages = ["difflib"] + pruneopts = "UT" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] + digest = "1:4b0a77e3bb3c0ddf54cff8dca385a744edc3625be3b9b55492ed6a14de4c13e6" name = "github.com/prometheus/alertmanager" packages = [ "template", "template/internal/deftmpl", - "types" + "types", ] + pruneopts = "UT" revision = "30af4d051b37ce817ea7e35b56c57a0e2ec9dbb0" version = "v0.14.0" [[projects]] + digest = "1:b6221ec0f8903b556e127c449e7106b63e6867170c2d10a7c058623d086f2081" name = "github.com/prometheus/client_golang" packages = ["prometheus"] + pruneopts = "UT" revision = "c5b7fccd204277076155f10851dad72b76a49317" version = "v0.8.0" [[projects]] branch = "master" + digest = "1:32d10bdfa8f09ecf13598324dba86ab891f11db3c538b6a34d1c3b5b99d7c36b" name = "github.com/prometheus/client_model" packages = ["go"] + pruneopts = "UT" revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" [[projects]] branch = "master" + digest = "1:e469cd65badf7694aeb44874518606d93c1d59e7735d3754ad442782437d3cc3" name = "github.com/prometheus/common" packages = [ "expfmt", "internal/bitbucket.org/ww/goautoneg", - "model" + "model", ] + pruneopts = "UT" revision = "d811d2e9bf898806ecfb6ef6296774b13ffc314c" [[projects]] branch = "master" + digest = "1:570784e0ddbf67f14087c6d8cfb7b999b9c55e75518a755e88cb202566ea8a17" name = "github.com/prometheus/procfs" packages = [ ".", "internal/util", "nfs", - "xfs" + "xfs", ] + pruneopts = "UT" revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e" [[projects]] + digest = "1:1bc4a5bd879ce6b44fdaa2e8e1144921c145604764e92220009b951c1f2439f5" name = "github.com/stretchr/objx" packages = ["."] + pruneopts = "UT" revision = "facf9a85c22f48d2f52f2380e4efce1768749a89" version = "v0.1" [[projects]] + digest = "1:eca8319bce847b7208ed5ae89ef2efb28586a7095657217241641e1da78a3c13" name = "github.com/stretchr/testify" packages = [ "assert", - "mock" + "mock", ] + pruneopts = "UT" revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" version = "v1.2.1" [[projects]] + digest = "1:420817f94b6c172dabb8a054d0b2d257d7437a87c7c8c7ee432bc008a577fc46" name = "github.com/technoweenie/multipartstreamer" packages = ["."] + pruneopts = "UT" revision = "a90a01d73ae432e2611d178c18367fbaa13e0154" version = "v1.0.1" [[projects]] + branch = "master" + digest = "1:ff865c5772fd1d5dfc30dfd225f9faf545661c35aa774c972411a2ec4af7cd2a" + name = "github.com/xconstruct/go-pushbullet" + packages = ["."] + pruneopts = "UT" + revision = "67759df45fbbd23cbe3d5cdc6df7891c5b663cb8" + +[[projects]] + digest = "1:81ccd59248f60553288016a6b5cb7d988fb9c11e21b713a951790647332528bd" name = "gopkg.in/njern/gonexmo.v1" packages = ["."] + pruneopts = "UT" revision = "c83191e580d14eb435e39f0317a89c6912b094a4" version = "v1.0.1" [[projects]] + digest = "1:6999e4e34bb73184674e844d6d1e6f48f75a30a9c86ef7663dbc7b2509962812" name = "gopkg.in/telegram-bot-api.v4" packages = ["."] + pruneopts = "UT" revision = "0e0af0c480ea98e982d5f4d45fb39577c6ab1e3e" version = "v4.6.2" [[projects]] + digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "UT" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "5f8fe62dbc923ac817a9bbbb22dad207fce7420d6a8d36a73c5f4e6c83232d47" + input-imports = [ + "github.com/carlosdp/twiliogo", + "github.com/messagebird/go-rest-api", + "github.com/prometheus/alertmanager/template", + "github.com/prometheus/client_golang/prometheus", + "github.com/xconstruct/go-pushbullet", + "gopkg.in/njern/gonexmo.v1", + "gopkg.in/telegram-bot-api.v4", + "gopkg.in/yaml.v2", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/xconstruct/go-pushbullet/.travis.yml b/vendor/github.com/xconstruct/go-pushbullet/.travis.yml new file mode 100644 index 0000000..64ec0d6 --- /dev/null +++ b/vendor/github.com/xconstruct/go-pushbullet/.travis.yml @@ -0,0 +1,7 @@ +language: go +go: + - tip +before_install: + - go get github.com/mattn/goveralls +script: + - goveralls --service=travis-ci --repotoken erZSOzTiDwnegx7UEkCTqGXCtK9940t52 -package . diff --git a/vendor/github.com/xconstruct/go-pushbullet/LICENSE b/vendor/github.com/xconstruct/go-pushbullet/LICENSE new file mode 100644 index 0000000..d5afe25 --- /dev/null +++ b/vendor/github.com/xconstruct/go-pushbullet/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Constantin Schomburg + +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. diff --git a/vendor/github.com/xconstruct/go-pushbullet/README.md b/vendor/github.com/xconstruct/go-pushbullet/README.md new file mode 100644 index 0000000..12982aa --- /dev/null +++ b/vendor/github.com/xconstruct/go-pushbullet/README.md @@ -0,0 +1,79 @@ +go-pushbullet +============= + +[![Build](https://img.shields.io/travis/xconstruct/go-pushbullet.svg?style=flat-square)](https://travis-ci.org/xconstruct/go-pushbullet) +[![Coverage](https://img.shields.io/coveralls/xconstruct/go-pushbullet.svg?style=flat-square)](https://coveralls.io/github/xconstruct/go-pushbullet) +[![API Documentation](https://img.shields.io/badge/api-GoDoc-blue.svg?style=flat-square)](https://godoc.org/github.com/xconstruct/go-pushbullet) +[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](http://opensource.org/licenses/MIT) + +Simple Go client for [Pushbullet](http://pushbullet.com), a webservice to push +links, notes and more to your Android devices. + +Documentation available under: http://godoc.org/github.com/xconstruct/go-pushbullet + +### Install ### + + go get "github.com/xconstruct/go-pushbullet" + +### Example ### + +```go +pb := pushbullet.New("YOUR_API_KEY") +devs, err := pb.Devices() +if err != nil { + panic(err) +} + +err = pb.PushNote(devs[0].Iden, "Hello!", "Hi from go-pushbullet!") +if err != nil { + panic(err) +} + + +user, err := pb.Me() +if err != nil { + panic(err) +} + +err = pb.PushSMS(user.Iden, devs[0].Iden, "", "Sms text") +if err != nil { + panic(err) +} +``` + +You can also retrieve a pushbullet device by nickname, and call the same methods as you would with the pushbullet client +```go +dev, err := pb.Device("My Phone") +if err != nil { + panic(err) +} + +err = dev.PushNote("Hello!", "Straight to device with just a title and body") +if err != nil { + panic(err) +} +``` + +Channels are also supported in a similar manner +```go +subs, err := pb.Subscriptions() +if err != nil { + panic(err) +} + +err = pb.PushNoteToChannel(subs[0].Channel.Tag, "Hello!", "Hi from go-pushbullet!") +if err != nil { + panic(err) +} + +sub, err := pb.Subscription("MyChannelTag") +if err != nil { + panic(err) +} + +err = sub.PushNote("Hello!", "Straight to Channel with just a title and body") +if err != nil { + panic(err) +} + +``` diff --git a/vendor/github.com/xconstruct/go-pushbullet/pushbullet.go b/vendor/github.com/xconstruct/go-pushbullet/pushbullet.go new file mode 100644 index 0000000..bcc8fb8 --- /dev/null +++ b/vendor/github.com/xconstruct/go-pushbullet/pushbullet.go @@ -0,0 +1,423 @@ +// Package pushbullet provides simple access to the v2 API of http://pushbullet.com. +/* + +Example client: + pb := pushbullet.New("YOUR_API_KEY") + devices, err := pb.Devices() + ... + err = pb.PushNote(devices[0].Iden, "Hello!", "Hi from go-pushbullet!") + +The API is document at https://docs.pushbullet.com/http/ . At the moment, it only supports querying devices and sending notifications. + +*/ +package pushbullet + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "errors" + "io/ioutil" + "net/http" + "net/url" +) + +// ErrDeviceNotFound is raised when device nickname is not found on pusbullet server +var ErrDeviceNotFound = errors.New("Device not found") + +// EndpointURL sets the default URL for the Pushbullet API +var EndpointURL = "https://api.pushbullet.com/v2" + +// Endpoint allows manipulation of pushbullet API endpoint for testing +type Endpoint struct { + URL string +} + +// A Client connects to PushBullet with an API Key. +type Client struct { + Key string + Client *http.Client + Endpoint +} + +// New creates a new client with your personal API key. +func New(apikey string) *Client { + endpoint := Endpoint{URL: EndpointURL} + return &Client{apikey, http.DefaultClient, endpoint} +} + +// NewWithClient creates a new client with your personal API key and the given http Client +func NewWithClient(apikey string, client *http.Client) *Client { + endpoint := Endpoint{URL: EndpointURL} + return &Client{apikey, client, endpoint} +} + +// A Device is a PushBullet device +type Device struct { + Iden string `json:"iden"` + Active bool `json:"active"` + Created float32 `json:"created"` + Modified float32 `json:"modified"` + Icon string `json:"icon"` + Nickname string `json:"nickname"` + GeneratedNickname bool `json:"generated_nickname"` + Manufacturer string `json:"manufacturer"` + Model string `json:"model"` + AppVersion int `json:"app_version"` + Fingerprint string `json:"fingerprint"` + KeyFingerprint string `json:"key_fingerprint"` + PushToken string `json:"push_token"` + HasSms bool `json:"has_sms"` + Client *Client `json:"-"` +} + +// ErrResponse is an error returned by the PushBullet API +type ErrResponse struct { + Type string `json:"type"` + Message string `json:"message"` + Cat string `json:"cat"` +} + +func (e *ErrResponse) Error() string { + return e.Message +} + +type errorResponse struct { + ErrResponse `json:"error"` +} + +type deviceResponse struct { + Devices []*Device + SharedDevices []*Device `json:"shared_devices"` +} + +type subscriptionResponse struct { + Subscriptions []*Subscription +} + +func (c *Client) buildRequest(object string, data interface{}) *http.Request { + r, err := http.NewRequest("GET", c.Endpoint.URL+object, nil) + if err != nil { + panic(err) + } + + // appengine sdk requires us to set the auth header by hand + u := url.UserPassword(c.Key, "") + r.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(u.String()))) + + if data != nil { + r.Method = "POST" + r.Header.Set("Content-Type", "application/json") + var b bytes.Buffer + enc := json.NewEncoder(&b) + enc.Encode(data) + r.Body = ioutil.NopCloser(&b) + } + + return r +} + +// Devices fetches a list of devices from PushBullet. +func (c *Client) Devices() ([]*Device, error) { + req := c.buildRequest("/devices", nil) + resp, err := c.Client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + var errjson errorResponse + dec := json.NewDecoder(resp.Body) + err = dec.Decode(&errjson) + if err == nil { + return nil, &errjson.ErrResponse + } + + return nil, errors.New(resp.Status) + } + + var devResp deviceResponse + dec := json.NewDecoder(resp.Body) + err = dec.Decode(&devResp) + if err != nil { + return nil, err + } + + for i := range devResp.Devices { + devResp.Devices[i].Client = c + } + devices := append(devResp.Devices, devResp.SharedDevices...) + return devices, nil +} + +// Device fetches an device with a given nickname from PushBullet. +func (c *Client) Device(nickname string) (*Device, error) { + devices, err := c.Devices() + if err != nil { + return nil, err + } + + for i := range devices { + if devices[i].Nickname == nickname { + devices[i].Client = c + return devices[i], nil + } + } + return nil, ErrDeviceNotFound +} + +// PushNote sends a note to the specific device with the given title and body +func (d *Device) PushNote(title, body string) error { + return d.Client.PushNote(d.Iden, title, body) +} + +// PushLink sends a link to the specific device with the given title and url +func (d *Device) PushLink(title, u, body string) error { + return d.Client.PushLink(d.Iden, title, u, body) +} + +// PushSMS sends an SMS to the specific user from the device with the given title and url +func (d *Device) PushSMS(deviceIden, phoneNumber, message string) error { + return d.Client.PushSMS(d.Iden, deviceIden, phoneNumber, message) +} + +// User represents the User object for pushbullet +type User struct { + Iden string `json:"iden"` + Email string `json:"email"` + EmailNormalized string `json:"email_normalized"` + Created float64 `json:"created"` + Modified float64 `json:"modified"` + Name string `json:"name"` + ImageUrl string `json:"image_url"` + Preferences interface{} `json:"preferences"` +} + +// Me returns the user object for the pushbullet user +func (c *Client) Me() (*User, error) { + req := c.buildRequest("/users/me", nil) + resp, err := c.Client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + var errjson errorResponse + dec := json.NewDecoder(resp.Body) + err = dec.Decode(&errjson) + if err == nil { + return nil, &errjson.ErrResponse + } + + return nil, errors.New(resp.Status) + } + + var userResponse User + dec := json.NewDecoder(resp.Body) + err = dec.Decode(&userResponse) + if err != nil { + return nil, err + } + return &userResponse, nil +} + +// Push pushes the data to a specific device registered with PushBullet. The +// 'data' parameter is marshaled to JSON and sent as the request body. Most +// users should call one of PusNote, PushLink, PushAddress, or PushList. +func (c *Client) Push(endPoint string, data interface{}) error { + req := c.buildRequest(endPoint, data) + resp, err := c.Client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + var errResponse errorResponse + dec := json.NewDecoder(resp.Body) + err = dec.Decode(&errResponse) + if err == nil { + return &errResponse.ErrResponse + } + + return errors.New(resp.Status) + } + + return nil +} + +// Note exposes the required and optional fields of the Pushbullet push type=note +type Note struct { + Iden string `json:"device_iden,omitempty"` + Tag string `json:"channel_tag,omitempty"` + Type string `json:"type"` + Title string `json:"title"` + Body string `json:"body"` +} + +// PushNote pushes a note with title and body to a specific PushBullet device. +func (c *Client) PushNote(iden string, title, body string) error { + data := Note{ + Iden: iden, + Type: "note", + Title: title, + Body: body, + } + return c.Push("/pushes", data) +} + +// PushNoteToChannel pushes a note with title and body to a specific PushBullet channel. +func (c *Client) PushNoteToChannel(tag string, title, body string) error { + data := Note{ + Tag: tag, + Type: "note", + Title: title, + Body: body, + } + return c.Push("/pushes", data) +} + +// Link exposes the required and optional fields of the Pushbullet push type=link +type Link struct { + Iden string `json:"device_iden,omitempty"` + Tag string `json:"channel_tag,omitempty"` + Type string `json:"type"` + Title string `json:"title"` + URL string `json:"url"` + Body string `json:"body,omitempty"` +} + +// PushLink pushes a link with a title and url to a specific PushBullet device. +func (c *Client) PushLink(iden, title, u, body string) error { + data := Link{ + Iden: iden, + Type: "link", + Title: title, + URL: u, + Body: body, + } + return c.Push("/pushes", data) +} + +// PushLinkToChannel pushes a link with a title and url to a specific PushBullet device. +func (c *Client) PushLinkToChannel(tag, title, u, body string) error { + data := Link{ + Tag: tag, + Type: "link", + Title: title, + URL: u, + Body: body, + } + return c.Push("/pushes", data) +} + +// EphemeralPush exposes the required fields of the Pushbullet ephemeral object +type EphemeralPush struct { + Type string `json:"type"` + PackageName string `json:"package_name"` + SourceUserIden string `json:"source_user_iden"` + TargetDeviceIden string `json:"target_device_iden"` + ConversationIden string `json:"conversation_iden"` + Message string `json:"message"` +} + +// Ephemeral constructs the Ephemeral object for pushing which requires the EphemeralPush object +type Ephemeral struct { + Type string `json:"type"` + Push EphemeralPush `json:"push"` +} + +// PushSMS sends an SMS message with pushbullet +func (c *Client) PushSMS(userIden, deviceIden, phoneNumber, message string) error { + data := Ephemeral{ + Type: "push", + Push: EphemeralPush{ + Type: "messaging_extension_reply", + PackageName: "com.pushbullet.android", + SourceUserIden: userIden, + TargetDeviceIden: deviceIden, + ConversationIden: phoneNumber, + Message: message, + }, + } + return c.Push("/ephemerals", data) +} + +// Subscription object allows interaction with pushbullet channels +type Subscription struct { + Iden string `json:"iden"` + Active bool `json:"active"` + Created float32 `json:"created"` + Modified float32 `json:"modified"` + Muted string `json:"muted"` + Channel *Channel `json:"channel"` + Client *Client `json:"-"` +} + +// Channel object contains specific information about the pushbullet Channel +type Channel struct { + Iden string `json:"iden"` + Tag string `json:"tag"` + Name string `json:"name"` + Description string `json:"description"` + ImageUrl string `json:"image_url"` + WebsiteUrl string `json:"website_url"` +} + +func (c *Client) Subscriptions() ([]*Subscription, error) { + req := c.buildRequest("/subscriptions", nil) + resp, err := c.Client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + var errjson errorResponse + dec := json.NewDecoder(resp.Body) + err = dec.Decode(&errjson) + if err == nil { + return nil, &errjson.ErrResponse + } + + return nil, errors.New(resp.Status) + } + + var subResp subscriptionResponse + dec := json.NewDecoder(resp.Body) + err = dec.Decode(&subResp) + if err != nil { + return nil, err + } + + for i := range subResp.Subscriptions { + subResp.Subscriptions[i].Client = c + } + subscriptions := append(subResp.Subscriptions) + return subscriptions, nil +} + +// Subscription fetches an subscription with a given channel tag from PushBullet. +func (c *Client) Subscription(tag string) (*Subscription, error) { + subs, err := c.Subscriptions() + if err != nil { + return nil, err + } + + for i := range subs { + if subs[i].Channel.Tag == tag { + subs[i].Client = c + return subs[i], nil + } + } + return nil, ErrDeviceNotFound +} + +// PushNote sends a note to the specific Channel with the given title and body +func (s *Subscription) PushNote(title, body string) error { + return s.Client.PushNoteToChannel(s.Channel.Tag, title, body) +} + +// PushNote sends a link to the specific Channel with the given title, url and body +func (s *Subscription) PushLink(title, u, body string) error { + return s.Client.PushLinkToChannel(s.Channel.Tag, title, u, body) +} From 9cb69ec6b8ff1700b5e15398c0aba69dd8f5b5d2 Mon Sep 17 00:00:00 2001 From: Luke Addison Date: Sat, 10 Aug 2019 19:17:53 +0100 Subject: [PATCH 04/63] Add Pushbullet provider --- cmd/sachet/config.go | 2 + cmd/sachet/main.go | 3 ++ examples/config.yaml | 8 ++- provider/pushbullet/README.md | 20 +++++++ provider/pushbullet/pushbullet.go | 88 +++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 provider/pushbullet/README.md create mode 100644 provider/pushbullet/pushbullet.go diff --git a/cmd/sachet/config.go b/cmd/sachet/config.go index 3c5fef9..7c034d9 100644 --- a/cmd/sachet/config.go +++ b/cmd/sachet/config.go @@ -12,6 +12,7 @@ import ( "github.com/messagebird/sachet/provider/messagebird" "github.com/messagebird/sachet/provider/nexmo" "github.com/messagebird/sachet/provider/otc" + "github.com/messagebird/sachet/provider/pushbullet" "github.com/messagebird/sachet/provider/sipgate" "github.com/messagebird/sachet/provider/telegram" "github.com/messagebird/sachet/provider/turbosms" @@ -44,6 +45,7 @@ var config struct { FreeMobile freemobile.Config AspSms aspsms.Config Sipgate sipgate.Config + Pushbullet pushbullet.Config } Receivers []ReceiverConf diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index 840489e..8a3ee82 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -20,6 +20,7 @@ import ( "github.com/messagebird/sachet/provider/messagebird" "github.com/messagebird/sachet/provider/nexmo" "github.com/messagebird/sachet/provider/otc" + "github.com/messagebird/sachet/provider/pushbullet" "github.com/messagebird/sachet/provider/sipgate" "github.com/messagebird/sachet/provider/telegram" "github.com/messagebird/sachet/provider/turbosms" @@ -174,6 +175,8 @@ func providerByName(name string) (sachet.Provider, error) { return aspsms.NewAspSms(config.Providers.AspSms), nil case "sipgate": return sipgate.NewSipgate(config.Providers.Sipgate), nil + case "pushbullet": + return pushbullet.NewPushbullet(config.Providers.Pushbullet), nil } return nil, fmt.Errorf("%s: Unknown provider", name) diff --git a/examples/config.yaml b/examples/config.yaml index 711454c..3ac3ebb 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -40,6 +40,8 @@ providers: sipgate: username: 'username' password: 'password' + pushbullet: + access_token: 'o.AbCdEfGhIjKlMnOpQrStUvWxYz012345' templates: - telegram.tmpl @@ -55,4 +57,8 @@ receivers: to: - '164451814' # the chat id of a user. Get yours at https://telegram.me/userinfobot text: '{{ .GroupLabels.alertname }} @ {{ .Labels.instance }}: {{ .Status | toUpper }}' - + - name: 'pushbullet' + provider: 'pushbullet' + to: + - device:My Nickname + - channel:mytag diff --git a/provider/pushbullet/README.md b/provider/pushbullet/README.md new file mode 100644 index 0000000..c91accf --- /dev/null +++ b/provider/pushbullet/README.md @@ -0,0 +1,20 @@ +# Pushbullet + +To configure the Pushbullet provider, you need to specify an access token, which can be generated in your [account settings](https://www.pushbullet.com/#settings/account). + +``` +providers: + pushbullet: + access_token: 'o.AbCdEfGhIjKlMnOpQrStUvWxYz012345' +``` + +To configure a pushbullet receiver you must specify a list of targets in the form `targetType:targetName` where the format of the name depends on the type. Currently pushing to a device or to subscribers of a channel are supported. + +``` +receivers: +- name: 'pushbullet' + provider: 'pushbullet' + to: + - device:My Nickname + - channel:mytag +``` \ No newline at end of file diff --git a/provider/pushbullet/pushbullet.go b/provider/pushbullet/pushbullet.go new file mode 100644 index 0000000..5deb10f --- /dev/null +++ b/provider/pushbullet/pushbullet.go @@ -0,0 +1,88 @@ +package pushbullet + +import ( + "fmt" + "strings" + + "github.com/messagebird/sachet" + "github.com/xconstruct/go-pushbullet" +) + +const ( + deviceTargetType = "device" + channelTargetType = "channel" +) + +// Config is the configuration struct for the Pushbullet provider +type Config struct { + AccessToken string `yaml:"access_token"` +} + +// Pushbullet contains the necessary values for the Pushbullet provider +type Pushbullet struct { + Config +} + +// NewPushbullet creates and returns a new Pushbullet struct +func NewPushbullet(config Config) *Pushbullet { + return &Pushbullet{config} +} + +// Send pushes a note to devices registered in configuration +func (c *Pushbullet) Send(message sachet.Message) error { + + for _, recipient := range message.To { + + // create pushbullet client + pb := pushbullet.New(c.AccessToken) + + // parse recipient + targetTypeName := strings.Split(recipient, ":") + if len(targetTypeName) != 2 { + return fmt.Errorf("cannot parse recipient %s: expecting targetType:targetName", recipient) + } + targetType := targetTypeName[0] + targetName := targetTypeName[1] + + switch targetType { + case deviceTargetType: + // retrieve device + dev, err := pb.Device(targetName) + if err != nil { + return err + } + + // push note + err = pb.PushNote(dev.Iden, message.From, message.Text) + if err != nil { + return err + } + case channelTargetType: + // retrieve subscription + sub, err := pb.Subscription(targetName) + if err != nil { + return err + } + + // push note + err = sub.PushNote(message.From, message.Text) + if err != nil { + return err + } + default: + return fmt.Errorf("unrecognised target type: %s", targetType) + } + + } + + return nil +} + +func contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} From 11fdfd9ca09033d4877b74477a310ab5a4e616f8 Mon Sep 17 00:00:00 2001 From: Luke Addison Date: Mon, 12 Aug 2019 13:39:01 +0100 Subject: [PATCH 05/63] Fix split logic --- provider/pushbullet/pushbullet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/pushbullet/pushbullet.go b/provider/pushbullet/pushbullet.go index 5deb10f..b28b790 100644 --- a/provider/pushbullet/pushbullet.go +++ b/provider/pushbullet/pushbullet.go @@ -37,7 +37,7 @@ func (c *Pushbullet) Send(message sachet.Message) error { pb := pushbullet.New(c.AccessToken) // parse recipient - targetTypeName := strings.Split(recipient, ":") + targetTypeName := strings.SplitN(recipient, ":", 2) if len(targetTypeName) != 2 { return fmt.Errorf("cannot parse recipient %s: expecting targetType:targetName", recipient) } From d4cc159d1d97018cc65a245de06fcaa04685506d Mon Sep 17 00:00:00 2001 From: Luke Addison Date: Mon, 12 Aug 2019 14:30:35 +0100 Subject: [PATCH 06/63] Remove unused contains function --- provider/pushbullet/pushbullet.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/provider/pushbullet/pushbullet.go b/provider/pushbullet/pushbullet.go index b28b790..0851eaf 100644 --- a/provider/pushbullet/pushbullet.go +++ b/provider/pushbullet/pushbullet.go @@ -77,12 +77,3 @@ func (c *Pushbullet) Send(message sachet.Message) error { return nil } - -func contains(s []string, e string) bool { - for _, a := range s { - if a == e { - return true - } - } - return false -} From ce8050b6608b077e502a4808b4c0017519968aac Mon Sep 17 00:00:00 2001 From: Kevin Hellemun Date: Fri, 30 Aug 2019 14:04:21 +0200 Subject: [PATCH 07/63] Auto push images to docker hub on tag. Fixed docker image to build the current code instead of pulling it. Added script to push image to docker hub repo. Moved from dep to go mod. --- .gitignore | 1 + .travis.yml | 16 +- Dockerfile | 14 +- Gopkg.lock | 186 ---------------- Gopkg.toml | 58 ----- build_push_image.sh | 17 ++ cmd/sachet/main.go | 2 + go.mod | 27 +++ go.sum | 44 ++++ .../prometheus/client_model/ruby/LICENSE | 201 ------------------ vendor/github.com/prometheus/procfs/ttar | 0 vendor/modules.txt | 46 ++++ 12 files changed, 158 insertions(+), 454 deletions(-) delete mode 100644 Gopkg.lock delete mode 100644 Gopkg.toml create mode 100755 build_push_image.sh create mode 100644 go.mod create mode 100644 go.sum delete mode 100644 vendor/github.com/prometheus/client_model/ruby/LICENSE mode change 100755 => 100644 vendor/github.com/prometheus/procfs/ttar create mode 100644 vendor/modules.txt diff --git a/.gitignore b/.gitignore index 359a86d..5cc3fec 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ _testmain.go gin-bin bin config.yaml +.idea diff --git a/.travis.yml b/.travis.yml index db2d81e..326cd08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,16 @@ language: go go: - - "1.10" - - 1.9 - - tip +- "1.11" +- "1.10" +- "1.9" +- tip -script: go test ./... +script: +- go test ./... + +deploy: +- provider: script + script: bash build_push_image.sh + on: + tags: true diff --git a/Dockerfile b/Dockerfile index ed5ddde..5c41848 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,15 @@ -FROM golang:alpine AS build +FROM golang:1.12 AS builder -RUN apk update && \ - apk add --no-cache git openssl ca-certificates && \ - go get github.com/messagebird/sachet/cmd/... +WORKDIR /build + +COPY . . + +RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -mod vendor -o sachet github.com/messagebird/sachet/cmd/sachet \ +&& chmod 777 sachet FROM alpine -COPY --from=build /go/bin/sachet /usr/local/bin + +COPY --from=builder /build/sachet /usr/local/bin COPY --chown=nobody examples/config.yaml /etc/sachet/config.yaml RUN apk update && \ apk add --no-cache ca-certificates diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index a8effd2..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,186 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" - name = "github.com/beorn7/perks" - packages = ["quantile"] - pruneopts = "UT" - revision = "3a771d992973f24aa725d07868b467d1ddfceafb" - -[[projects]] - digest = "1:004d308dffe0ab15d83f7dc98ec8c42c843666df1a50537a4ff38ed4cf187f2c" - name = "github.com/carlosdp/twiliogo" - packages = ["."] - pruneopts = "UT" - revision = "f61c8230fa91b87ca5c16a21a661861208749dfe" - version = "v0.1" - -[[projects]] - digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" - name = "github.com/davecgh/go-spew" - packages = ["spew"] - pruneopts = "UT" - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" - -[[projects]] - digest = "1:15042ad3498153684d09f393bbaec6b216c8eec6d61f63dff711de7d64ed8861" - name = "github.com/golang/protobuf" - packages = ["proto"] - pruneopts = "UT" - revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" - version = "v1.1.0" - -[[projects]] - digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6" - name = "github.com/matttproud/golang_protobuf_extensions" - packages = ["pbutil"] - pruneopts = "UT" - revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" - version = "v1.0.0" - -[[projects]] - branch = "master" - digest = "1:98dc904e7724bf8f5b26809d39fb706d37b45fa30a838240b334dfbadc7befbb" - name = "github.com/messagebird/go-rest-api" - packages = ["."] - pruneopts = "UT" - revision = "a9514230491e7db6adaa58162cce34a5df987fd4" - -[[projects]] - digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" - name = "github.com/pmezard/go-difflib" - packages = ["difflib"] - pruneopts = "UT" - revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.0.0" - -[[projects]] - digest = "1:4b0a77e3bb3c0ddf54cff8dca385a744edc3625be3b9b55492ed6a14de4c13e6" - name = "github.com/prometheus/alertmanager" - packages = [ - "template", - "template/internal/deftmpl", - "types", - ] - pruneopts = "UT" - revision = "30af4d051b37ce817ea7e35b56c57a0e2ec9dbb0" - version = "v0.14.0" - -[[projects]] - digest = "1:b6221ec0f8903b556e127c449e7106b63e6867170c2d10a7c058623d086f2081" - name = "github.com/prometheus/client_golang" - packages = ["prometheus"] - pruneopts = "UT" - revision = "c5b7fccd204277076155f10851dad72b76a49317" - version = "v0.8.0" - -[[projects]] - branch = "master" - digest = "1:32d10bdfa8f09ecf13598324dba86ab891f11db3c538b6a34d1c3b5b99d7c36b" - name = "github.com/prometheus/client_model" - packages = ["go"] - pruneopts = "UT" - revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" - -[[projects]] - branch = "master" - digest = "1:e469cd65badf7694aeb44874518606d93c1d59e7735d3754ad442782437d3cc3" - name = "github.com/prometheus/common" - packages = [ - "expfmt", - "internal/bitbucket.org/ww/goautoneg", - "model", - ] - pruneopts = "UT" - revision = "d811d2e9bf898806ecfb6ef6296774b13ffc314c" - -[[projects]] - branch = "master" - digest = "1:570784e0ddbf67f14087c6d8cfb7b999b9c55e75518a755e88cb202566ea8a17" - name = "github.com/prometheus/procfs" - packages = [ - ".", - "internal/util", - "nfs", - "xfs", - ] - pruneopts = "UT" - revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e" - -[[projects]] - digest = "1:1bc4a5bd879ce6b44fdaa2e8e1144921c145604764e92220009b951c1f2439f5" - name = "github.com/stretchr/objx" - packages = ["."] - pruneopts = "UT" - revision = "facf9a85c22f48d2f52f2380e4efce1768749a89" - version = "v0.1" - -[[projects]] - digest = "1:eca8319bce847b7208ed5ae89ef2efb28586a7095657217241641e1da78a3c13" - name = "github.com/stretchr/testify" - packages = [ - "assert", - "mock", - ] - pruneopts = "UT" - revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" - version = "v1.2.1" - -[[projects]] - digest = "1:420817f94b6c172dabb8a054d0b2d257d7437a87c7c8c7ee432bc008a577fc46" - name = "github.com/technoweenie/multipartstreamer" - packages = ["."] - pruneopts = "UT" - revision = "a90a01d73ae432e2611d178c18367fbaa13e0154" - version = "v1.0.1" - -[[projects]] - branch = "master" - digest = "1:ff865c5772fd1d5dfc30dfd225f9faf545661c35aa774c972411a2ec4af7cd2a" - name = "github.com/xconstruct/go-pushbullet" - packages = ["."] - pruneopts = "UT" - revision = "67759df45fbbd23cbe3d5cdc6df7891c5b663cb8" - -[[projects]] - digest = "1:81ccd59248f60553288016a6b5cb7d988fb9c11e21b713a951790647332528bd" - name = "gopkg.in/njern/gonexmo.v1" - packages = ["."] - pruneopts = "UT" - revision = "c83191e580d14eb435e39f0317a89c6912b094a4" - version = "v1.0.1" - -[[projects]] - digest = "1:6999e4e34bb73184674e844d6d1e6f48f75a30a9c86ef7663dbc7b2509962812" - name = "gopkg.in/telegram-bot-api.v4" - packages = ["."] - pruneopts = "UT" - revision = "0e0af0c480ea98e982d5f4d45fb39577c6ab1e3e" - version = "v4.6.2" - -[[projects]] - digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" - name = "gopkg.in/yaml.v2" - packages = ["."] - pruneopts = "UT" - revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" - version = "v2.2.1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/carlosdp/twiliogo", - "github.com/messagebird/go-rest-api", - "github.com/prometheus/alertmanager/template", - "github.com/prometheus/client_golang/prometheus", - "github.com/xconstruct/go-pushbullet", - "gopkg.in/njern/gonexmo.v1", - "gopkg.in/telegram-bot-api.v4", - "gopkg.in/yaml.v2", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index 2121758..0000000 --- a/Gopkg.toml +++ /dev/null @@ -1,58 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - - -[[constraint]] - name = "github.com/carlosdp/twiliogo" - version = "0.1.0" - -[[constraint]] - name = "github.com/messagebird/go-rest-api" - branch = "master" - -[[constraint]] - name = "github.com/prometheus/alertmanager" - version = "0.14.0" - -[[constraint]] - name = "github.com/prometheus/client_golang" - version = "0.8.0" - -[[constraint]] - name = "gopkg.in/njern/gonexmo.v1" - version = "1.0.1" - -[[constraint]] - name = "gopkg.in/telegram-bot-api.v4" - version = "4.6.2" - -[[constraint]] - name = "gopkg.in/yaml.v2" - version = "2.2.1" - -[prune] - go-tests = true - unused-packages = true diff --git a/build_push_image.sh b/build_push_image.sh new file mode 100755 index 0000000..1cdd3fd --- /dev/null +++ b/build_push_image.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -e + +if [[ ${TRAVIS_EVENT_TYPE} == "cron" ]]; then + exit 0 +fi + +IMAGE_NAME="messagebird/sachet" + +docker build --build-arg TAG="${TRAVIS_TAG}" -t ${IMAGE_NAME}:latest . + +docker tag ${IMAGE_NAME}:latest ${IMAGE_NAME}:"${TRAVIS_TAG}" + +echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin + +docker push ${IMAGE_NAME}:"${TRAVIS_TAG}" +docker push ${IMAGE_NAME}:latest diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index 8a3ee82..2b72c09 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -133,6 +133,8 @@ func main() { *listenAddress = ":" + os.Getenv("PORT") } + log.Printf("Listiting on %s", *listenAddress) + log.Fatal(http.ListenAndServe(*listenAddress, nil)) } diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..734f78a --- /dev/null +++ b/go.mod @@ -0,0 +1,27 @@ +module github.com/messagebird/sachet + +go 1.12 + +require ( + github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect + github.com/carlosdp/twiliogo v0.0.0-20140102225436-f61c8230fa91 + github.com/davecgh/go-spew v1.1.0 // indirect + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/golang/protobuf v1.1.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.0 // indirect + github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/alertmanager v0.14.0 + github.com/prometheus/client_golang v0.8.0 + github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 // indirect + github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89 // indirect + github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d // indirect + github.com/stretchr/objx v0.1.0 // indirect + github.com/stretchr/testify v1.2.1 // indirect + github.com/technoweenie/multipartstreamer v1.0.1 // indirect + github.com/xconstruct/go-pushbullet v0.0.0-20171206132031-67759df45fbb + golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect + gopkg.in/njern/gonexmo.v1 v1.0.1 + gopkg.in/telegram-bot-api.v4 v4.6.2 + gopkg.in/yaml.v2 v2.2.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bbcb933 --- /dev/null +++ b/go.sum @@ -0,0 +1,44 @@ +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/carlosdp/twiliogo v0.0.0-20140102225436-f61c8230fa91 h1:fIflfwVZsOHJD5nWJXEmdGrHnhVGVWtvVZAXMsHlCDU= +github.com/carlosdp/twiliogo v0.0.0-20140102225436-f61c8230fa91/go.mod h1:pAxCBpjl/0JxYZlWGP/Dyi8f/LQSCQD2WAsG/iNzqQ8= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/matttproud/golang_protobuf_extensions v1.0.0 h1:YNOwxxSJzSUARoD9KRZLzM9Y858MNGCOACTvCW9TSAc= +github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e h1:hsSmRHe7psyLMQ/Kn8xgr0koZKB4rfgO4dsKgP6S4Dc= +github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e/go.mod h1:+XI/mPytD/HkPfkOm6IDu6hWgIyePQYZ4Fb5Nlm2las= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/alertmanager v0.14.0 h1:pO6S2wb3PAX0LedGvfaFlJQZNSAB0HrsST5//thlBq0= +github.com/prometheus/alertmanager v0.14.0/go.mod h1:zdz6eCci7rHWB/8/1E/9JEfoKqCAIlxmt8EIKvHi0dI= +github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 h1:cLL6NowurKLMfCeQy4tIeph12XNQWgANCNvdyrOYKV4= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89 h1:7KBNF1zLlfEkG0K4axOT7B9GNzaIse6ELQL/w48P7KI= +github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d h1:RCcsxyRr6+/pLg6wr0cUjPovhEhSNOtPh0SOz6u3hGU= +github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= +github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= +github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= +github.com/xconstruct/go-pushbullet v0.0.0-20171206132031-67759df45fbb h1:m+CPNoRrlFVxLKZeodSyEc9cc1GBWYJutHO/eOByUo8= +github.com/xconstruct/go-pushbullet v0.0.0-20171206132031-67759df45fbb/go.mod h1:OdGNyFi3/K/Fl/3pZu3lAGKMBhTQDl9Lgjn08LSA95Q= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/njern/gonexmo.v1 v1.0.1 h1:fTAudpN4nmfmdyGU+W4FbU0Ifh+jUsQao/F5neKD2Hs= +gopkg.in/njern/gonexmo.v1 v1.0.1/go.mod h1:PwngK45ZxAYI4/2IVT5FELDeSohbM1e4kyjYTO2OkCg= +gopkg.in/telegram-bot-api.v4 v4.6.2 h1:oUu8dyT/KzUWusD3OiPWTLoFM6n9uskQlW1GLoxjQcE= +gopkg.in/telegram-bot-api.v4 v4.6.2/go.mod h1:5DpGO5dbumb40px+dXcwCpcjmeHNYLpk0bp3XRNvWDM= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/prometheus/client_model/ruby/LICENSE b/vendor/github.com/prometheus/client_model/ruby/LICENSE deleted file mode 100644 index 11069ed..0000000 --- a/vendor/github.com/prometheus/client_model/ruby/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/github.com/prometheus/procfs/ttar b/vendor/github.com/prometheus/procfs/ttar old mode 100755 new mode 100644 diff --git a/vendor/modules.txt b/vendor/modules.txt new file mode 100644 index 0000000..1fe76ef --- /dev/null +++ b/vendor/modules.txt @@ -0,0 +1,46 @@ +# github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 +github.com/beorn7/perks/quantile +# github.com/carlosdp/twiliogo v0.0.0-20140102225436-f61c8230fa91 +github.com/carlosdp/twiliogo +# github.com/davecgh/go-spew v1.1.0 +github.com/davecgh/go-spew/spew +# github.com/golang/protobuf v1.1.0 +github.com/golang/protobuf/proto +# github.com/matttproud/golang_protobuf_extensions v1.0.0 +github.com/matttproud/golang_protobuf_extensions/pbutil +# github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e +github.com/messagebird/go-rest-api +# github.com/pmezard/go-difflib v1.0.0 +github.com/pmezard/go-difflib/difflib +# github.com/prometheus/alertmanager v0.14.0 +github.com/prometheus/alertmanager/template +github.com/prometheus/alertmanager/template/internal/deftmpl +github.com/prometheus/alertmanager/types +# github.com/prometheus/client_golang v0.8.0 +github.com/prometheus/client_golang/prometheus +# github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 +github.com/prometheus/client_model/go +# github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89 +github.com/prometheus/common/model +github.com/prometheus/common/expfmt +github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg +# github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d +github.com/prometheus/procfs +github.com/prometheus/procfs/nfs +github.com/prometheus/procfs/xfs +github.com/prometheus/procfs/internal/util +# github.com/stretchr/objx v0.1.0 +github.com/stretchr/objx +# github.com/stretchr/testify v1.2.1 +github.com/stretchr/testify/mock +github.com/stretchr/testify/assert +# github.com/technoweenie/multipartstreamer v1.0.1 +github.com/technoweenie/multipartstreamer +# github.com/xconstruct/go-pushbullet v0.0.0-20171206132031-67759df45fbb +github.com/xconstruct/go-pushbullet +# gopkg.in/njern/gonexmo.v1 v1.0.1 +gopkg.in/njern/gonexmo.v1 +# gopkg.in/telegram-bot-api.v4 v4.6.2 +gopkg.in/telegram-bot-api.v4 +# gopkg.in/yaml.v2 v2.2.1 +gopkg.in/yaml.v2 From 0540ca97c91ce781562075019534680e6b030685 Mon Sep 17 00:00:00 2001 From: Kevin Hellemun <17928966+OGKevin@users.noreply.github.com> Date: Fri, 30 Aug 2019 14:10:43 +0200 Subject: [PATCH 08/63] No need for chmod --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5c41848..2314963 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,7 @@ WORKDIR /build COPY . . -RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -mod vendor -o sachet github.com/messagebird/sachet/cmd/sachet \ -&& chmod 777 sachet +RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -mod vendor -o sachet github.com/messagebird/sachet/cmd/sachet FROM alpine From 92c7cf57d5c261f60ac121ec75cbefb8a4474f82 Mon Sep 17 00:00:00 2001 From: marcel corso Date: Sun, 1 Sep 2019 21:52:45 +0200 Subject: [PATCH 09/63] small typo --- cmd/sachet/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index 2b72c09..ee46607 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -133,7 +133,7 @@ func main() { *listenAddress = ":" + os.Getenv("PORT") } - log.Printf("Listiting on %s", *listenAddress) + log.Printf("Listening on %s", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) } From d1eaa778f148fd77ee5b5d1c530bd12e0eaed08e Mon Sep 17 00:00:00 2001 From: Kevin Hellemun <17928966+OGKevin@users.noreply.github.com> Date: Fri, 6 Sep 2019 12:39:22 +0200 Subject: [PATCH 10/63] Add live and ready endpoint for probes. --- cmd/sachet/main.go | 7 + go.mod | 1 + go.sum | 2 + .../heptiolabs/healthcheck/.gitignore | 1 + .../heptiolabs/healthcheck/.travis.yml | 13 ++ .../heptiolabs/healthcheck/CODE_OF_CONDUCT.md | 37 ++++ .../heptiolabs/healthcheck/CONTRIBUTING.md | 57 +++++ .../heptiolabs/healthcheck/Gopkg.lock | 87 ++++++++ .../heptiolabs/healthcheck/Gopkg.toml | 10 + .../github.com/heptiolabs/healthcheck/LICENSE | 201 ++++++++++++++++++ .../heptiolabs/healthcheck/README.md | 92 ++++++++ .../heptiolabs/healthcheck/async.go | 85 ++++++++ .../heptiolabs/healthcheck/checks.go | 104 +++++++++ .../github.com/heptiolabs/healthcheck/doc.go | 24 +++ .../heptiolabs/healthcheck/handler.go | 103 +++++++++ .../heptiolabs/healthcheck/metrics_handler.go | 76 +++++++ .../heptiolabs/healthcheck/timeout.go | 52 +++++ .../heptiolabs/healthcheck/types.go | 52 +++++ vendor/modules.txt | 2 + 19 files changed, 1006 insertions(+) create mode 100644 vendor/github.com/heptiolabs/healthcheck/.gitignore create mode 100644 vendor/github.com/heptiolabs/healthcheck/.travis.yml create mode 100644 vendor/github.com/heptiolabs/healthcheck/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/heptiolabs/healthcheck/CONTRIBUTING.md create mode 100644 vendor/github.com/heptiolabs/healthcheck/Gopkg.lock create mode 100644 vendor/github.com/heptiolabs/healthcheck/Gopkg.toml create mode 100644 vendor/github.com/heptiolabs/healthcheck/LICENSE create mode 100644 vendor/github.com/heptiolabs/healthcheck/README.md create mode 100644 vendor/github.com/heptiolabs/healthcheck/async.go create mode 100644 vendor/github.com/heptiolabs/healthcheck/checks.go create mode 100644 vendor/github.com/heptiolabs/healthcheck/doc.go create mode 100644 vendor/github.com/heptiolabs/healthcheck/handler.go create mode 100644 vendor/github.com/heptiolabs/healthcheck/metrics_handler.go create mode 100644 vendor/github.com/heptiolabs/healthcheck/timeout.go create mode 100644 vendor/github.com/heptiolabs/healthcheck/types.go diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index ee46607..83f710a 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -28,6 +28,8 @@ import ( "github.com/prometheus/alertmanager/template" "github.com/prometheus/client_golang/prometheus" + + "github.com/heptiolabs/healthcheck" ) var ( @@ -129,6 +131,11 @@ func main() { } }) + hc := healthcheck.NewMetricsHandler(prometheus.DefaultRegisterer, "sachet") + + http.Handle("/-/live", hc) + http.Handle("/-/ready", hc) + if os.Getenv("PORT") != "" { *listenAddress = ":" + os.Getenv("PORT") } diff --git a/go.mod b/go.mod index 734f78a..5b5b923 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/davecgh/go-spew v1.1.0 // indirect github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect github.com/golang/protobuf v1.1.0 // indirect + github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 github.com/matttproud/golang_protobuf_extensions v1.0.0 // indirect github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index bbcb933..e095086 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaEL github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 h1:GT4RsKmHh1uZyhmTkWJTDALRjSHYQp6FRKrotf0zhAs= +github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40/go.mod h1:NtmN9h8vrTveVQRLHcX2HQ5wIPBDCsZ351TGbZWgg38= github.com/matttproud/golang_protobuf_extensions v1.0.0 h1:YNOwxxSJzSUARoD9KRZLzM9Y858MNGCOACTvCW9TSAc= github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e h1:hsSmRHe7psyLMQ/Kn8xgr0koZKB4rfgO4dsKgP6S4Dc= diff --git a/vendor/github.com/heptiolabs/healthcheck/.gitignore b/vendor/github.com/heptiolabs/healthcheck/.gitignore new file mode 100644 index 0000000..61ead86 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/.gitignore @@ -0,0 +1 @@ +/vendor diff --git a/vendor/github.com/heptiolabs/healthcheck/.travis.yml b/vendor/github.com/heptiolabs/healthcheck/.travis.yml new file mode 100644 index 0000000..df44261 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/.travis.yml @@ -0,0 +1,13 @@ +language: go +go_import_path: github.com/heptiolabs/healthcheck +go: + - 1.9.x + +sudo: false + +install: + - go get -u github.com/golang/dep/cmd/dep + && dep ensure -vendor-only -v + +script: + - go test -v -cover . diff --git a/vendor/github.com/heptiolabs/healthcheck/CODE_OF_CONDUCT.md b/vendor/github.com/heptiolabs/healthcheck/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..560c400 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/CODE_OF_CONDUCT.md @@ -0,0 +1,37 @@ +# Community Code of Conduct + +## Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering +an open and welcoming community, we pledge to respect all people who contribute +through reporting issues, posting feature requests, updating documentation, +submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for +everyone, regardless of level of experience, gender, gender identity and expression, +sexual orientation, disability, personal appearance, body size, race, ethnicity, age, +religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, + without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are not +aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers +commit themselves to fairly and consistently applying these principles to every aspect +of managing this project. Project maintainers who do not follow or enforce the Code of +Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer(s). + +This Code of Conduct is adapted from the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md) and [Contributor Covenant](http://contributor-covenant.org/version/1/2/0/), version 1.2.0. diff --git a/vendor/github.com/heptiolabs/healthcheck/CONTRIBUTING.md b/vendor/github.com/heptiolabs/healthcheck/CONTRIBUTING.md new file mode 100644 index 0000000..2c0e880 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/CONTRIBUTING.md @@ -0,0 +1,57 @@ +## DCO Sign off + +All authors to the project retain copyright to their work. However, to ensure +that they are only submitting work that they have rights to, we are requiring +everyone to acknowldge this by signing their work. + +Any copyright notices in this repos should specify the authors as "the contributors". + +To sign your work, just add a line like this at the end of your commit message: + +``` +Signed-off-by: Joe Beda +``` + +This can easily be done with the `--signoff` option to `git commit`. + +By doing this you state that you can certify the following (from https://developercertificate.org/): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` \ No newline at end of file diff --git a/vendor/github.com/heptiolabs/healthcheck/Gopkg.lock b/vendor/github.com/heptiolabs/healthcheck/Gopkg.lock new file mode 100644 index 0000000..28121b7 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/Gopkg.lock @@ -0,0 +1,87 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" + +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" + version = "v1.0.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_golang" + packages = [ + "prometheus", + "prometheus/promhttp" + ] + revision = "c3324c1198cf3374996e9d3098edd46a6b55afc9" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" + +[[projects]] + branch = "master" + name = "github.com/prometheus/common" + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model" + ] + revision = "6fb6fce6f8b75884b92e1889c150403fc0872c5e" + +[[projects]] + branch = "master" + name = "github.com/prometheus/procfs" + packages = [ + ".", + "internal/util", + "nfs", + "xfs" + ] + revision = "7186fbf4eb22a031bcd4657c8adc3fc39acf6d8a" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert"] + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[[projects]] + name = "gopkg.in/DATA-DOG/go-sqlmock.v1" + packages = ["."] + revision = "d76b18b42f285b792bf985118980ce9eacea9d10" + version = "v1.3.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "739553432f1d3b8bc633e5e10f18d31e57b1f8af15c9e916398429bd4d7bd826" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/heptiolabs/healthcheck/Gopkg.toml b/vendor/github.com/heptiolabs/healthcheck/Gopkg.toml new file mode 100644 index 0000000..25c3355 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/Gopkg.toml @@ -0,0 +1,10 @@ +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. + +[[constraint]] + name = "github.com/prometheus/client_golang" + branch = "master" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.1.4" diff --git a/vendor/github.com/heptiolabs/healthcheck/LICENSE b/vendor/github.com/heptiolabs/healthcheck/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/heptiolabs/healthcheck/README.md b/vendor/github.com/heptiolabs/healthcheck/README.md new file mode 100644 index 0000000..1e916cf --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/README.md @@ -0,0 +1,92 @@ +# healthcheck +[![Build Status](https://travis-ci.org/heptiolabs/healthcheck.svg?branch=master)](https://travis-ci.org/heptiolabs/healthcheck) +[![Go Report Card](https://goreportcard.com/badge/github.com/heptiolabs/healthcheck)](https://goreportcard.com/report/github.com/heptiolabs/healthcheck) +[![GoDoc](https://godoc.org/github.com/heptiolabs/healthcheck?status.svg)](https://godoc.org/github.com/heptiolabs/healthcheck) + +Healthcheck is a library for implementing Kubernetes [liveness and readiness](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/) probe handlers in your Go application. + +## Features + + - Integrates easily with Kubernetes. This library explicitly separates liveness vs. readiness checks instead of lumping everything into a single category of check. + + - Optionally exposes each check as a [Prometheus gauge](https://prometheus.io/docs/concepts/metric_types/#gauge) metric. This allows for cluster-wide monitoring and alerting on individual checks. + + - Supports asynchronous checks, which run in a background goroutine at a fixed interval. These are useful for expensive checks that you don't want to add latency to the liveness and readiness endpoints. + + - Includes a small library of generically useful checks for validating upstream DNS, TCP, HTTP, and database dependencies as well as checking basic health of the Go runtime. + +## Usage + +See the [GoDoc examples](https://godoc.org/github.com/heptiolabs/healthcheck) for more detail. + + - Install with `go get` or your favorite Go dependency manager: `go get -u github.com/heptiolabs/healthcheck` + + - Import the package: `import "github.com/heptiolabs/healthcheck"` + + - Create a `healthcheck.Handler`: + ```go + health := healthcheck.NewHandler() + ``` + + - Configure some application-specific liveness checks (whether the app itself is unhealthy): + ```go + // Our app is not happy if we've got more than 100 goroutines running. + health.AddLivenessCheck("goroutine-threshold", healthcheck.GoroutineCountCheck(100)) + ``` + + - Configure some application-specific readiness checks (whether the app is ready to serve requests): + ```go + // Our app is not ready if we can't resolve our upstream dependency in DNS. + health.AddReadinessCheck( + "upstream-dep-dns", + healthcheck.DNSResolveCheck("upstream.example.com", 50*time.Millisecond)) + + // Our app is not ready if we can't connect to our database (`var db *sql.DB`) in <1s. + health.AddReadinessCheck("database", healthcheck.DatabasePingCheck(db, 1*time.Second)) + ``` + + - Expose the `/live` and `/ready` endpoints over HTTP (on port 8086): + ```go + go http.ListenAndServe("0.0.0.0:8086", health) + ``` + + - Configure your Kubernetes container with HTTP liveness and readiness probes see the ([Kubernetes documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/)) for more detail: + ```yaml + # this is a bare bones example + # copy and paste livenessProbe and readinessProbe as appropriate for your app + apiVersion: v1 + kind: Pod + metadata: + name: heptio-healthcheck-example + spec: + containers: + - name: liveness + image: your-registry/your-container + + # define a liveness probe that checks every 5 seconds, starting after 5 seconds + livenessProbe: + httpGet: + path: /live + port: 8086 + initialDelaySeconds: 5 + periodSeconds: 5 + + # define a readiness probe that checks every 5 seconds + readinessProbe: + httpGet: + path: /ready + port: 8086 + periodSeconds: 5 + ``` + + - If one of your readiness checks fails, Kubernetes will stop routing traffic to that pod within a few seconds (depending on `periodSeconds` and other factors). + + - If one of your liveness checks fails or your app becomes totally unresponsive, Kubernetes will restart your container. + + ## HTTP Endpoints + When you run `go http.ListenAndServe("0.0.0.0:8086", health)`, two HTTP endpoints are exposed: + + - **`/live`**: liveness endpoint (HTTP 200 if healthy, HTTP 503 if unhealthy) + - **`/ready`**: readiness endpoint (HTTP 200 if healthy, HTTP 503 if unhealthy) + +Pass the `?full=1` query parameter to see the full check results as JSON. These are omitted by default for performance. \ No newline at end of file diff --git a/vendor/github.com/heptiolabs/healthcheck/async.go b/vendor/github.com/heptiolabs/healthcheck/async.go new file mode 100644 index 0000000..2c6bb9f --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/async.go @@ -0,0 +1,85 @@ +// Copyright 2017 by the contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthcheck + +import ( + "context" + "errors" + "time" +) + +// ErrNoData is returned if the first call of an Async() wrapped Check has not +// yet returned. +var ErrNoData = errors.New("no data yet") + +// Async converts a Check into an asynchronous check that runs in a background +// goroutine at a fixed interval. The check is called at a fixed rate, not with +// a fixed delay between invocations. If your check takes longer than the +// interval to execute, the next execution will happen immediately. +// +// Note: if you need to clean up the background goroutine, use AsyncWithContext(). +func Async(check Check, interval time.Duration) Check { + return AsyncWithContext(context.Background(), check, interval) +} + +// AsyncWithContext converts a Check into an asynchronous check that runs in a +// background goroutine at a fixed interval. The check is called at a fixed +// rate, not with a fixed delay between invocations. If your check takes longer +// than the interval to execute, the next execution will happen immediately. +// +// Note: if you don't need to cancel execution (because this runs forever), use Async() +func AsyncWithContext(ctx context.Context, check Check, interval time.Duration) Check { + // create a chan that will buffer the most recent check result + result := make(chan error, 1) + + // fill it with ErrNoData so we'll start in an initially failing state + // (we don't want to be ready/live until we've actually executed the check + // once, but that might be slow). + result <- ErrNoData + + // make a wrapper that runs the check, and swaps out the current head of + // the channel with the latest result + update := func() { + err := check() + <-result + result <- err + } + + // spawn a background goroutine to run the check + go func() { + // call once right away (time.Tick() doesn't always tick immediately + // but we want an initial result as soon as possible) + update() + + // loop forever or until the context is canceled + ticker := time.Tick(interval) + for { + select { + case <-ticker: + update() + case <-ctx.Done(): + return + } + } + }() + + // return a Check function that closes over our result and mutex + return func() error { + // peek at the head of the channel, then put it back + err := <-result + result <- err + return err + } +} diff --git a/vendor/github.com/heptiolabs/healthcheck/checks.go b/vendor/github.com/heptiolabs/healthcheck/checks.go new file mode 100644 index 0000000..a41eb32 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/checks.go @@ -0,0 +1,104 @@ +// Copyright 2017 by the contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthcheck + +import ( + "context" + "database/sql" + "fmt" + "net" + "net/http" + "runtime" + "time" +) + +// TCPDialCheck returns a Check that checks TCP connectivity to the provided +// endpoint. +func TCPDialCheck(addr string, timeout time.Duration) Check { + return func() error { + conn, err := net.DialTimeout("tcp", addr, timeout) + if err != nil { + return err + } + return conn.Close() + } +} + +// HTTPGetCheck returns a Check that performs an HTTP GET request against the +// specified URL. The check fails if the response times out or returns a non-200 +// status code. +func HTTPGetCheck(url string, timeout time.Duration) Check { + client := http.Client{ + Timeout: timeout, + // never follow redirects + CheckRedirect: func(*http.Request, []*http.Request) error { + return http.ErrUseLastResponse + }, + } + return func() error { + resp, err := client.Get(url) + if err != nil { + return err + } + resp.Body.Close() + if resp.StatusCode != 200 { + return fmt.Errorf("returned status %d", resp.StatusCode) + } + return nil + } +} + +// DatabasePingCheck returns a Check that validates connectivity to a +// database/sql.DB using Ping(). +func DatabasePingCheck(database *sql.DB, timeout time.Duration) Check { + return func() error { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + if database == nil { + return fmt.Errorf("database is nil") + } + return database.PingContext(ctx) + } +} + +// DNSResolveCheck returns a Check that makes sure the provided host can resolve +// to at least one IP address within the specified timeout. +func DNSResolveCheck(host string, timeout time.Duration) Check { + resolver := net.Resolver{} + return func() error { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + addrs, err := resolver.LookupHost(ctx, host) + if err != nil { + return err + } + if len(addrs) < 1 { + return fmt.Errorf("could not resolve host") + } + return nil + } +} + +// GoroutineCountCheck returns a Check that fails if too many goroutines are +// running (which could indicate a resource leak). +func GoroutineCountCheck(threshold int) Check { + return func() error { + count := runtime.NumGoroutine() + if count > threshold { + return fmt.Errorf("too many goroutines (%d > %d)", count, threshold) + } + return nil + } +} diff --git a/vendor/github.com/heptiolabs/healthcheck/doc.go b/vendor/github.com/heptiolabs/healthcheck/doc.go new file mode 100644 index 0000000..1920098 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/doc.go @@ -0,0 +1,24 @@ +// Copyright 2017 by the contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +Package healthcheck helps you implement Kubernetes liveness and readiness checks +for your application. It supports synchronous and asynchronous (background) +checks. It can optionally report each check's status as a set of Prometheus +gauge metrics for cluster-wide monitoring and alerting. + +It also includes a small library of generic checks for DNS, TCP, and HTTP +reachability as well as Goroutine usage. +*/ +package healthcheck diff --git a/vendor/github.com/heptiolabs/healthcheck/handler.go b/vendor/github.com/heptiolabs/healthcheck/handler.go new file mode 100644 index 0000000..6ea9740 --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/handler.go @@ -0,0 +1,103 @@ +// Copyright 2017 by the contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthcheck + +import ( + "encoding/json" + "net/http" + "sync" +) + +// basicHandler is a basic Handler implementation. +type basicHandler struct { + http.ServeMux + checksMutex sync.RWMutex + livenessChecks map[string]Check + readinessChecks map[string]Check +} + +// NewHandler creates a new basic Handler +func NewHandler() Handler { + h := &basicHandler{ + livenessChecks: make(map[string]Check), + readinessChecks: make(map[string]Check), + } + h.Handle("/live", http.HandlerFunc(h.LiveEndpoint)) + h.Handle("/ready", http.HandlerFunc(h.ReadyEndpoint)) + return h +} + +func (s *basicHandler) LiveEndpoint(w http.ResponseWriter, r *http.Request) { + s.handle(w, r, s.livenessChecks) +} + +func (s *basicHandler) ReadyEndpoint(w http.ResponseWriter, r *http.Request) { + s.handle(w, r, s.readinessChecks, s.livenessChecks) +} + +func (s *basicHandler) AddLivenessCheck(name string, check Check) { + s.checksMutex.Lock() + defer s.checksMutex.Unlock() + s.livenessChecks[name] = check +} + +func (s *basicHandler) AddReadinessCheck(name string, check Check) { + s.checksMutex.Lock() + defer s.checksMutex.Unlock() + s.readinessChecks[name] = check +} + +func (s *basicHandler) collectChecks(checks map[string]Check, resultsOut map[string]string, statusOut *int) { + s.checksMutex.RLock() + defer s.checksMutex.RUnlock() + for name, check := range checks { + if err := check(); err != nil { + *statusOut = http.StatusServiceUnavailable + resultsOut[name] = err.Error() + } else { + resultsOut[name] = "OK" + } + } +} + +func (s *basicHandler) handle(w http.ResponseWriter, r *http.Request, checks ...map[string]Check) { + if r.Method != http.MethodGet { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + checkResults := make(map[string]string) + status := http.StatusOK + for _, checks := range checks { + s.collectChecks(checks, checkResults, &status) + } + + // write out the response code and content type header + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(status) + + // unless ?full=1, return an empty body. Kubernetes only cares about the + // HTTP status code, so we won't waste bytes on the full body. + if r.URL.Query().Get("full") != "1" { + w.Write([]byte("{}\n")) + return + } + + // otherwise, write the JSON body ignoring any encoding errors (which + // shouldn't really be possible since we're encoding a map[string]string). + encoder := json.NewEncoder(w) + encoder.SetIndent("", " ") + encoder.Encode(checkResults) +} diff --git a/vendor/github.com/heptiolabs/healthcheck/metrics_handler.go b/vendor/github.com/heptiolabs/healthcheck/metrics_handler.go new file mode 100644 index 0000000..e95be0f --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/metrics_handler.go @@ -0,0 +1,76 @@ +// Copyright 2017 by the contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthcheck + +import ( + "net/http" + + "github.com/prometheus/client_golang/prometheus" +) + +type metricsHandler struct { + handler Handler + registry prometheus.Registerer + namespace string +} + +// NewMetricsHandler returns a healthcheck Handler that also exposes metrics +// into the provided Prometheus registry. +func NewMetricsHandler(registry prometheus.Registerer, namespace string) Handler { + return &metricsHandler{ + handler: NewHandler(), + registry: registry, + namespace: namespace, + } +} + +func (h *metricsHandler) AddLivenessCheck(name string, check Check) { + h.handler.AddLivenessCheck(name, h.wrap(name, check)) +} + +func (h *metricsHandler) AddReadinessCheck(name string, check Check) { + h.handler.AddReadinessCheck(name, h.wrap(name, check)) +} + +func (h *metricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + h.handler.ServeHTTP(w, r) +} + +func (h *metricsHandler) LiveEndpoint(w http.ResponseWriter, r *http.Request) { + h.handler.LiveEndpoint(w, r) +} + +func (h *metricsHandler) ReadyEndpoint(w http.ResponseWriter, r *http.Request) { + h.handler.ReadyEndpoint(w, r) +} + +func (h *metricsHandler) wrap(name string, check Check) Check { + h.registry.MustRegister(prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: h.namespace, + Subsystem: "healthcheck", + Name: "status", + Help: "Current check status (0 indicates success, 1 indicates failure)", + ConstLabels: prometheus.Labels{"check": name}, + }, + func() float64 { + if check() == nil { + return 0 + } + return 1 + }, + )) + return check +} diff --git a/vendor/github.com/heptiolabs/healthcheck/timeout.go b/vendor/github.com/heptiolabs/healthcheck/timeout.go new file mode 100644 index 0000000..86bf21d --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/timeout.go @@ -0,0 +1,52 @@ +// Copyright 2017 by the contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthcheck + +import ( + "fmt" + "time" +) + +// TimeoutError is the error returned when a Timeout-wrapped Check takes too long +type timeoutError time.Duration + +func (e timeoutError) Error() string { + return fmt.Sprintf("timed out after %s", time.Duration(e).String()) +} + +// Timeout returns whether this error is a timeout (always true for timeoutError) +func (e timeoutError) Timeout() bool { + return true +} + +// Temporary returns whether this error is temporary (always true for timeoutError) +func (e timeoutError) Temporary() bool { + return true +} + +// Timeout adds a timeout to a Check. If the underlying check takes longer than +// the timeout, it returns an error. +func Timeout(check Check, timeout time.Duration) Check { + return func() error { + c := make(chan error, 1) + go func() { c <- check() }() + select { + case err := <-c: + return err + case <-time.After(timeout): + return timeoutError(timeout) + } + } +} diff --git a/vendor/github.com/heptiolabs/healthcheck/types.go b/vendor/github.com/heptiolabs/healthcheck/types.go new file mode 100644 index 0000000..714294b --- /dev/null +++ b/vendor/github.com/heptiolabs/healthcheck/types.go @@ -0,0 +1,52 @@ +// Copyright 2017 by the contributors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthcheck + +import ( + "net/http" +) + +// Check is a health/readiness check. +type Check func() error + +// Handler is an http.Handler with additional methods that register health and +// readiness checks. It handles handle "/live" and "/ready" HTTP +// endpoints. +type Handler interface { + // The Handler is an http.Handler, so it can be exposed directly and handle + // /live and /ready endpoints. + http.Handler + + // AddLivenessCheck adds a check that indicates that this instance of the + // application should be destroyed or restarted. A failed liveness check + // indicates that this instance is unhealthy, not some upstream dependency. + // Every liveness check is also included as a readiness check. + AddLivenessCheck(name string, check Check) + + // AddReadinessCheck adds a check that indicates that this instance of the + // application is currently unable to serve requests because of an upstream + // or some transient failure. If a readiness check fails, this instance + // should no longer receiver requests, but should not be restarted or + // destroyed. + AddReadinessCheck(name string, check Check) + + // LiveEndpoint is the HTTP handler for just the /live endpoint, which is + // useful if you need to attach it into your own HTTP handler tree. + LiveEndpoint(http.ResponseWriter, *http.Request) + + // ReadyEndpoint is the HTTP handler for just the /ready endpoint, which is + // useful if you need to attach it into your own HTTP handler tree. + ReadyEndpoint(http.ResponseWriter, *http.Request) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 1fe76ef..825312d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -6,6 +6,8 @@ github.com/carlosdp/twiliogo github.com/davecgh/go-spew/spew # github.com/golang/protobuf v1.1.0 github.com/golang/protobuf/proto +# github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 +github.com/heptiolabs/healthcheck # github.com/matttproud/golang_protobuf_extensions v1.0.0 github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e From b89cd5c6c79094c91b7b421b0083847c00c28b74 Mon Sep 17 00:00:00 2001 From: Kevin Hellemun <17928966+OGKevin@users.noreply.github.com> Date: Fri, 6 Sep 2019 14:27:19 +0200 Subject: [PATCH 11/63] Use handle func rather than handle --- cmd/sachet/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index 83f710a..6683f56 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -133,8 +133,8 @@ func main() { hc := healthcheck.NewMetricsHandler(prometheus.DefaultRegisterer, "sachet") - http.Handle("/-/live", hc) - http.Handle("/-/ready", hc) + http.HandleFunc("/-/live", hc.LiveEndpoint) + http.HandleFunc("/-/ready", hc.ReadyEndpoint) if os.Getenv("PORT") != "" { *listenAddress = ":" + os.Getenv("PORT") From e0e6edf4d019719ae58978adc31ddf13433520ec Mon Sep 17 00:00:00 2001 From: Ids van der Molen Date: Wed, 30 Oct 2019 15:00:35 +0100 Subject: [PATCH 12/63] Add Type field to Message and support VoiceMessages with messagebird provider --- cmd/sachet/config.go | 1 + cmd/sachet/main.go | 6 ++++ provider/messagebird/README.md | 43 +++++++++++++++++++++++++++++ provider/messagebird/messagebird.go | 24 ++++++++++++++-- sachet.go | 1 + 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 provider/messagebird/README.md diff --git a/cmd/sachet/config.go b/cmd/sachet/config.go index 7c034d9..02f3b62 100644 --- a/cmd/sachet/config.go +++ b/cmd/sachet/config.go @@ -28,6 +28,7 @@ type ReceiverConf struct { To []string From string Text string + Type string } var config struct { diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index 6683f56..356cca5 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -66,6 +66,11 @@ func main() { return } + // default is set to "text" messages + if receiverConf.Type == "" { + receiverConf.Type = "text" + } + var text string if receiverConf.Text != "" { text, err = tmpl.ExecuteTextString(receiverConf.Text, data) @@ -106,6 +111,7 @@ func main() { message := sachet.Message{ To: receiverConf.To, From: receiverConf.From, + Type: receiverConf.Type, Text: text, } diff --git a/provider/messagebird/README.md b/provider/messagebird/README.md new file mode 100644 index 0000000..87232cf --- /dev/null +++ b/provider/messagebird/README.md @@ -0,0 +1,43 @@ +# MessageBird +## Provider +To configure the MessageBird provider, you need to specify an access key. + +```yaml +providers: + messagebird: + access_key: 'live_qKwVZ02ULV70GqabBYxLU8d5r' + debug: true + gateway: 240 + language: en-us + voice: female + repeat: 2 +``` + +The MessageBird provider supports text and voice messages. +For text messages you can configure the following parameters (see https://developers.messagebird.com/api/sms-messaging): + * `gateway`: an integer specifying the SMS gateway + +For voice messages you can configure the following parameters (see https://developers.messagebird.com/api/voice-messaging/): + * `language`: specifies the language in which the message needs to be read to the recipient + * `voice`: specifies the voice in which the message needs to be read to the recipient + * `repeat`: specifies the number of times the message needs to be repeated + +## Receivers +To configure a MessageBird receiver you must specify a list of targets. By default text messages are send, but you can specify a voice message by setting `type: voice` for a receiver. The `type` defaults to `text`. The `from` field is not used for voice messages. + +```yaml +receivers: +- name: 'team1' + provider: messagebird + to: + - '+919742033616' + - '+919742033617' + type: voice +- name: 'team2' + provider: messagebird + to: + - '+919742033616' + - '+919742033617' + from: '08039591643' + type: text +``` diff --git a/provider/messagebird/messagebird.go b/provider/messagebird/messagebird.go index 87a1be2..ed8baba 100644 --- a/provider/messagebird/messagebird.go +++ b/provider/messagebird/messagebird.go @@ -3,6 +3,7 @@ package messagebird import ( "log" "os" + "fmt" "github.com/messagebird/go-rest-api" "github.com/messagebird/sachet" @@ -12,11 +13,15 @@ type MessageBirdConfig struct { AccessKey string `yaml:"access_key"` Gateway int `yaml:"gateway"` Debug bool `yaml:"debug"` + Language string `yaml:"language"` + Voice string `yaml:"voice"` + Repeat int `yaml:"repeat"` } type MessageBird struct { client *messagebird.Client - params messagebird.MessageParams + messageParams messagebird.MessageParams + voiceMessageParams messagebird.VoiceMessageParams } func NewMessageBird(config MessageBirdConfig) *MessageBird { @@ -26,13 +31,26 @@ func NewMessageBird(config MessageBirdConfig) *MessageBird { } return &MessageBird{ client: client, - params: messagebird.MessageParams{ + messageParams: messagebird.MessageParams{ Gateway: config.Gateway, }, + voiceMessageParams: messagebird.VoiceMessageParams{ + Language: config.Language, + Voice: config.Voice, + Repeat: config.Repeat, + }, } } func (mb *MessageBird) Send(message sachet.Message) error { - _, err := mb.client.NewMessage(message.From, message.To, message.Text, &mb.params) + var err error=nil + switch message.Type { + case "text": + _, err = mb.client.NewMessage(message.From, message.To, message.Text, &mb.messageParams) + case "voice": + _, err = mb.client.NewVoiceMessage(message.To, message.Text, &mb.voiceMessageParams) + default: + return fmt.Errorf("unknown message type %s", message.Type) + } return err } diff --git a/sachet.go b/sachet.go index 3ac55a2..336267c 100644 --- a/sachet.go +++ b/sachet.go @@ -8,4 +8,5 @@ type Message struct { To []string From string Text string + Type string } From e35c3d5383635563fa320caf098420c3b080e75c Mon Sep 17 00:00:00 2001 From: Ids van der Molen Date: Wed, 30 Oct 2019 16:10:18 +0100 Subject: [PATCH 13/63] Handle default for Message.Type in provider --- cmd/sachet/main.go | 5 ----- provider/messagebird/messagebird.go | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index 356cca5..f577687 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -66,11 +66,6 @@ func main() { return } - // default is set to "text" messages - if receiverConf.Type == "" { - receiverConf.Type = "text" - } - var text string if receiverConf.Text != "" { text, err = tmpl.ExecuteTextString(receiverConf.Text, data) diff --git a/provider/messagebird/messagebird.go b/provider/messagebird/messagebird.go index ed8baba..21bbde1 100644 --- a/provider/messagebird/messagebird.go +++ b/provider/messagebird/messagebird.go @@ -45,7 +45,7 @@ func NewMessageBird(config MessageBirdConfig) *MessageBird { func (mb *MessageBird) Send(message sachet.Message) error { var err error=nil switch message.Type { - case "text": + case "","text": _, err = mb.client.NewMessage(message.From, message.To, message.Text, &mb.messageParams) case "voice": _, err = mb.client.NewVoiceMessage(message.To, message.Text, &mb.voiceMessageParams) From 1af1bf12eee53db273eca71c84872b53cad3b747 Mon Sep 17 00:00:00 2001 From: marcel corso Date: Wed, 30 Oct 2019 17:10:48 +0100 Subject: [PATCH 14/63] add docker build, push to release --- release.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 7774d4b..2ed55f4 100755 --- a/release.sh +++ b/release.sh @@ -15,6 +15,8 @@ env GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o "bin/sachet-$VERSION.li cd bin tar -zcvf "$REPO-$VERSION.linux-amd64.tar.gz" "$REPO-$VERSION.linux-amd64" +docker build -t ${USER}/${REPO}:${VERSION} . + # go get -u github.com/aktau/github-release # dont forget to set your token like # export GITHUB_TOKEN=blabla @@ -34,4 +36,6 @@ github-release upload \ --name "$REPO-$VERSION.linux-amd64.tar.gz" \ --file "$REPO-$VERSION.linux-amd64.tar.gz" - +docker push ${USER}/${REPO}:${VERSION} +docker tag ${USER}/${REPO}:${VERSION} ${USER}/${REPO}:latest +docker push ${USER}/${REPO}:latest From c8e547a36010e833aa4c695e15016e5d52dce7b5 Mon Sep 17 00:00:00 2001 From: Khaled Karam Date: Sun, 3 Nov 2019 09:51:45 +0300 Subject: [PATCH 15/63] add nowsms as a provider Signed-off-by: Khaled Karam --- cmd/sachet/config.go | 2 + cmd/sachet/main.go | 3 ++ examples/config.yaml | 6 +++ provider/messagebird/messagebird.go | 2 +- provider/nowsms/nowsms.go | 68 +++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 provider/nowsms/nowsms.go diff --git a/cmd/sachet/config.go b/cmd/sachet/config.go index 02f3b62..2e8fd10 100644 --- a/cmd/sachet/config.go +++ b/cmd/sachet/config.go @@ -11,6 +11,7 @@ import ( "github.com/messagebird/sachet/provider/mediaburst" "github.com/messagebird/sachet/provider/messagebird" "github.com/messagebird/sachet/provider/nexmo" + "github.com/messagebird/sachet/provider/nowsms" "github.com/messagebird/sachet/provider/otc" "github.com/messagebird/sachet/provider/pushbullet" "github.com/messagebird/sachet/provider/sipgate" @@ -47,6 +48,7 @@ var config struct { AspSms aspsms.Config Sipgate sipgate.Config Pushbullet pushbullet.Config + NowSms nowsms.Config } Receivers []ReceiverConf diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index f577687..12103e3 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -19,6 +19,7 @@ import ( "github.com/messagebird/sachet/provider/mediaburst" "github.com/messagebird/sachet/provider/messagebird" "github.com/messagebird/sachet/provider/nexmo" + "github.com/messagebird/sachet/provider/nowsms" "github.com/messagebird/sachet/provider/otc" "github.com/messagebird/sachet/provider/pushbullet" "github.com/messagebird/sachet/provider/sipgate" @@ -187,6 +188,8 @@ func providerByName(name string) (sachet.Provider, error) { return sipgate.NewSipgate(config.Providers.Sipgate), nil case "pushbullet": return pushbullet.NewPushbullet(config.Providers.Pushbullet), nil + case "nowsms": + return nowsms.NewNowSms(config.Providers.NowSms), nil } return nil, fmt.Errorf("%s: Unknown provider", name) diff --git a/examples/config.yaml b/examples/config.yaml index 3ac3ebb..c9e50fc 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -42,6 +42,12 @@ providers: password: 'password' pushbullet: access_token: 'o.AbCdEfGhIjKlMnOpQrStUvWxYz012345' + nowsms: + username: 'username' + password: 'password' + phone_numbers: + - '332432432' + - '4242334534' templates: - telegram.tmpl diff --git a/provider/messagebird/messagebird.go b/provider/messagebird/messagebird.go index 21bbde1..ae0200b 100644 --- a/provider/messagebird/messagebird.go +++ b/provider/messagebird/messagebird.go @@ -5,7 +5,7 @@ import ( "os" "fmt" - "github.com/messagebird/go-rest-api" + messagebird "github.com/messagebird/go-rest-api" "github.com/messagebird/sachet" ) diff --git a/provider/nowsms/nowsms.go b/provider/nowsms/nowsms.go new file mode 100644 index 0000000..db7c297 --- /dev/null +++ b/provider/nowsms/nowsms.go @@ -0,0 +1,68 @@ +package nowsms + +import ( + "fmt" + "io/ioutil" + "net/http" + "strings" + "time" + + "github.com/messagebird/sachet" +) + +// Config is the configuration struct for NowSms provider +type Config struct { + User string `yaml:"username"` + Password string `yaml:"password"` + PhoneNumbers []string `yaml:"phone_numbers"` +} + +// NowSms contains the necessary values for the NowSms provider +type NowSms struct { + Config + HTTPClient *http.Client // The HTTP client to send requests on +} + +// NewNowSms creates and returns a new NowSms struct +func NewNowSms(config Config) *NowSms { + return &NowSms{ + config, + &http.Client{Timeout: time.Second * 20}, + } +} + +// Send sends SMS to user registered in configuration +func (ns *NowSms) Send(message sachet.Message) error { + const nowSmsURL = "http://sms-gateway:8800/send" + + request, err := http.NewRequest("POST", nowSmsURL, nil) + if err != nil { + return err + } + request.Header.Set("User-Agent", "Sachet") + + params := request.URL.Query() + params.Add("User", ns.User) + params.Add("Password", ns.Password) + params.Add("PhoneNumber", strings.Join(ns.PhoneNumbers, ",")) + params.Add("Text", message.Text) + request.URL.RawQuery = params.Encode() + + response, err := ns.HTTPClient.Do(request) + if err != nil { + return err + } + defer response.Body.Close() + + if response.StatusCode != http.StatusOK { + body, _ := ioutil.ReadAll(response.Body) + return fmt.Errorf( + "SMS sending failed. HTTP status code: %d, Response body: %s", + response.StatusCode, + body, + ) + } + fmt.Println("Message sent: ", message.Text) + + return nil +} From aa524b1ca19f28b254ef4d895d6603727bc8343e Mon Sep 17 00:00:00 2001 From: Khaled Karam Date: Sun, 3 Nov 2019 14:49:03 +0300 Subject: [PATCH 16/63] set phone numbers as attribute reciever instead of configuration Signed-off-by: Khaled Karam --- examples/config.yaml | 8 +++++--- provider/nowsms/nowsms.go | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/config.yaml b/examples/config.yaml index c9e50fc..f8f535f 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -45,9 +45,6 @@ providers: nowsms: username: 'username' password: 'password' - phone_numbers: - - '332432432' - - '4242334534' templates: - telegram.tmpl @@ -68,3 +65,8 @@ receivers: to: - device:My Nickname - channel:mytag + - name: 'nowsms' + provider: 'nowsms' + to: + - '332432432' + - '4242334534' diff --git a/provider/nowsms/nowsms.go b/provider/nowsms/nowsms.go index db7c297..840edf8 100644 --- a/provider/nowsms/nowsms.go +++ b/provider/nowsms/nowsms.go @@ -44,7 +44,7 @@ func (ns *NowSms) Send(message sachet.Message) error { params := request.URL.Query() params.Add("User", ns.User) params.Add("Password", ns.Password) - params.Add("PhoneNumber", strings.Join(ns.PhoneNumbers, ",")) + params.Add("PhoneNumber", strings.Join(message.To, ",")) params.Add("Text", message.Text) request.URL.RawQuery = params.Encode() From 4bb9d1cedcea496bcf986315efafb9cdf3314e19 Mon Sep 17 00:00:00 2001 From: Trung Nguyen Date: Fri, 22 Nov 2019 15:35:37 +0700 Subject: [PATCH 17/63] Add kannel provider --- cmd/sachet/config.go | 2 ++ cmd/sachet/main.go | 3 ++ examples/config.yaml | 5 +++ provider/kannel/kannel.go | 65 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 provider/kannel/kannel.go diff --git a/cmd/sachet/config.go b/cmd/sachet/config.go index 2e8fd10..d6ac922 100644 --- a/cmd/sachet/config.go +++ b/cmd/sachet/config.go @@ -8,6 +8,7 @@ import ( "github.com/messagebird/sachet/provider/exotel" "github.com/messagebird/sachet/provider/freemobile" "github.com/messagebird/sachet/provider/infobip" + "github.com/messagebird/sachet/provider/kannel" "github.com/messagebird/sachet/provider/mediaburst" "github.com/messagebird/sachet/provider/messagebird" "github.com/messagebird/sachet/provider/nexmo" @@ -38,6 +39,7 @@ var config struct { Nexmo nexmo.NexmoConfig Twilio twilio.TwilioConfig Infobip infobip.InfobipConfig + Kannel kannel.KannelConfig Exotel exotel.ExotelConfig CM cm.CMConfig Telegram telegram.TelegramConfig diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index 12103e3..f48d9c6 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -16,6 +16,7 @@ import ( "github.com/messagebird/sachet/provider/exotel" "github.com/messagebird/sachet/provider/freemobile" "github.com/messagebird/sachet/provider/infobip" + "github.com/messagebird/sachet/provider/kannel" "github.com/messagebird/sachet/provider/mediaburst" "github.com/messagebird/sachet/provider/messagebird" "github.com/messagebird/sachet/provider/nexmo" @@ -168,6 +169,8 @@ func providerByName(name string) (sachet.Provider, error) { return twilio.NewTwilio(config.Providers.Twilio), nil case "infobip": return infobip.NewInfobip(config.Providers.Infobip), nil + case "kannel": + return kannel.NewKannel(config.Providers.Kannel), nil case "turbosms": return turbosms.NewTurbosms(config.Providers.Turbosms), nil case "exotel": diff --git a/examples/config.yaml b/examples/config.yaml index f8f535f..4c79b01 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -8,6 +8,11 @@ providers: infobip: token: "sasasa" secret: "sasasa" + kannel: + # url: "http://localhost:13013/cgi-bin/sendsms" + url: "http://httpbin.org/get" + user: "tester" + password: "foobar" exotel: account_sid: 'sachet' auth_token: 'bbba3f4afc0b4ee76c93e43b7c1b2d4350d1a0e8' diff --git a/provider/kannel/kannel.go b/provider/kannel/kannel.go new file mode 100644 index 0000000..aabfa93 --- /dev/null +++ b/provider/kannel/kannel.go @@ -0,0 +1,65 @@ +package kannel + +import ( + "fmt" + "net/url" + "net/http" + "time" + + "github.com/messagebird/sachet" +) + +//KannelConfig configuration struct for Kannel Client +type KannelConfig struct { + URL string `yaml:"url"` + User string `yaml:"username"` + Pass string `yaml:"password"` +} + +//KannelRequestTimeout is the timeout for http request to Kannel +const KannelRequestTimeout = time.Second * 20 + +//Kannel is the exte Kannel +type Kannel struct { + KannelConfig +} + +//NewKannel creates a new +func NewKannel(config KannelConfig) *Kannel { + Kannel := &Kannel{config} + return Kannel +} + +//Send send sms to n number of people using bulk sms api +func (c *Kannel) Send(message sachet.Message) (err error) { + var request *http.Request + var resp *http.Response + + queryParams := url.Values{"from": {message.From}, "to": message.To, "text": {message.Text}, "user": {c.User}, "pass": {c.Pass}} + //preparing the request + request, err = http.NewRequest("GET", c.URL, nil) + if err != nil { + return + } + + // request.SetBasicAuth(c.User, c.Pass) + request.URL.RawQuery = queryParams.Encode() + request.Header.Set("Content-Type", "application/x-www-form-urlencoded") + request.Header.Set("User-Agent", "SachetV1.0") + //calling the endpoint + fmt.Println(request.URL.String()) + httpClient := &http.Client{} + httpClient.Timeout = KannelRequestTimeout + + resp, err = httpClient.Do(request) + if err != nil { + return + } + defer resp.Body.Close() + var body []byte + resp.Body.Read(body) + if resp.StatusCode == http.StatusOK && err == nil { + return + } + return fmt.Errorf("Failed sending sms:Reason: %s , StatusCode : %d", string(body), resp.StatusCode) +} From 83d49e6be6b65cbb8b0f62a809e5fecad10f0d36 Mon Sep 17 00:00:00 2001 From: Trung Nguyen Date: Thu, 28 Nov 2019 13:57:52 +0700 Subject: [PATCH 18/63] Using atom beautify --- provider/kannel/kannel.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/provider/kannel/kannel.go b/provider/kannel/kannel.go index aabfa93..8b99c33 100644 --- a/provider/kannel/kannel.go +++ b/provider/kannel/kannel.go @@ -2,8 +2,8 @@ package kannel import ( "fmt" - "net/url" "net/http" + "net/url" "time" "github.com/messagebird/sachet" @@ -11,9 +11,9 @@ import ( //KannelConfig configuration struct for Kannel Client type KannelConfig struct { - URL string `yaml:"url"` - User string `yaml:"username"` - Pass string `yaml:"password"` + URL string `yaml:"url"` + User string `yaml:"username"` + Pass string `yaml:"password"` } //KannelRequestTimeout is the timeout for http request to Kannel From 239945b30668ea24980cb533c6dad09355a2008f Mon Sep 17 00:00:00 2001 From: Trung Nguyen Date: Thu, 28 Nov 2019 14:23:30 +0700 Subject: [PATCH 19/63] Support list of receipient --- provider/kannel/kannel.go | 54 ++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/provider/kannel/kannel.go b/provider/kannel/kannel.go index 8b99c33..2623461 100644 --- a/provider/kannel/kannel.go +++ b/provider/kannel/kannel.go @@ -32,34 +32,30 @@ func NewKannel(config KannelConfig) *Kannel { //Send send sms to n number of people using bulk sms api func (c *Kannel) Send(message sachet.Message) (err error) { - var request *http.Request - var resp *http.Response - - queryParams := url.Values{"from": {message.From}, "to": message.To, "text": {message.Text}, "user": {c.User}, "pass": {c.Pass}} - //preparing the request - request, err = http.NewRequest("GET", c.URL, nil) - if err != nil { - return - } - - // request.SetBasicAuth(c.User, c.Pass) - request.URL.RawQuery = queryParams.Encode() - request.Header.Set("Content-Type", "application/x-www-form-urlencoded") - request.Header.Set("User-Agent", "SachetV1.0") - //calling the endpoint - fmt.Println(request.URL.String()) - httpClient := &http.Client{} - httpClient.Timeout = KannelRequestTimeout - - resp, err = httpClient.Do(request) - if err != nil { - return - } - defer resp.Body.Close() - var body []byte - resp.Body.Read(body) - if resp.StatusCode == http.StatusOK && err == nil { - return + for _, recipient := range message.To { + queryParams := url.Values{"from": {message.From}, "to": {recipient}, "text": {message.Text}, "user": {c.User}, "pass": {c.Pass}} + + request, err := http.NewRequest("GET", c.URL, nil) + if err != nil { + return err + } + + request.URL.RawQuery = queryParams.Encode() + request.Header.Set("Content-Type", "application/x-www-form-urlencoded") + request.Header.Set("User-Agent", "SachetV1.0") + // calling the endpoint - print out Kannel requested URL for debug purpose + // fmt.Println(request.URL.String()) + httpClient := &http.Client{} + httpClient.Timeout = KannelRequestTimeout + + response, err := httpClient.Do(request) + if err != nil { + return err + } + + if response.StatusCode >= 400 { + return fmt.Errorf("Failed sending sms. statusCode: %d", response.StatusCode) + } } - return fmt.Errorf("Failed sending sms:Reason: %s , StatusCode : %d", string(body), resp.StatusCode) + return } From 3cf03554ae085533a7eb8cf82e9c02016c0fe67a Mon Sep 17 00:00:00 2001 From: Herb Date: Fri, 10 Jan 2020 16:10:32 +0800 Subject: [PATCH 20/63] add provider aliyun --- cmd/sachet/config.go | 2 ++ cmd/sachet/main.go | 3 ++ go.mod | 5 +--- go.sum | 26 +++++++++++++++++ provider/aliyun/aliyun.go | 61 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 provider/aliyun/aliyun.go diff --git a/cmd/sachet/config.go b/cmd/sachet/config.go index d6ac922..d38e5ae 100644 --- a/cmd/sachet/config.go +++ b/cmd/sachet/config.go @@ -3,6 +3,7 @@ package main import ( "io/ioutil" + "github.com/messagebird/sachet/provider/aliyun" "github.com/messagebird/sachet/provider/aspsms" "github.com/messagebird/sachet/provider/cm" "github.com/messagebird/sachet/provider/exotel" @@ -51,6 +52,7 @@ var config struct { Sipgate sipgate.Config Pushbullet pushbullet.Config NowSms nowsms.Config + Aliyun aliyun.AliyunConfig } Receivers []ReceiverConf diff --git a/cmd/sachet/main.go b/cmd/sachet/main.go index f48d9c6..fb9c86d 100644 --- a/cmd/sachet/main.go +++ b/cmd/sachet/main.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/messagebird/sachet" + "github.com/messagebird/sachet/provider/aliyun" "github.com/messagebird/sachet/provider/aspsms" "github.com/messagebird/sachet/provider/cm" "github.com/messagebird/sachet/provider/exotel" @@ -193,6 +194,8 @@ func providerByName(name string) (sachet.Provider, error) { return pushbullet.NewPushbullet(config.Providers.Pushbullet), nil case "nowsms": return nowsms.NewNowSms(config.Providers.NowSms), nil + case "aliyun": + return aliyun.NewAliyun(config.Providers.Aliyun) } return nil, fmt.Errorf("%s: Unknown provider", name) diff --git a/go.mod b/go.mod index 5b5b923..1a7cddb 100644 --- a/go.mod +++ b/go.mod @@ -3,22 +3,19 @@ module github.com/messagebird/sachet go 1.12 require ( + github.com/aliyun/alibaba-cloud-sdk-go v1.60.327 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect github.com/carlosdp/twiliogo v0.0.0-20140102225436-f61c8230fa91 - github.com/davecgh/go-spew v1.1.0 // indirect github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect github.com/golang/protobuf v1.1.0 // indirect github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 github.com/matttproud/golang_protobuf_extensions v1.0.0 // indirect github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/alertmanager v0.14.0 github.com/prometheus/client_golang v0.8.0 github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 // indirect github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89 // indirect github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d // indirect - github.com/stretchr/objx v0.1.0 // indirect - github.com/stretchr/testify v1.2.1 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect github.com/xconstruct/go-pushbullet v0.0.0-20171206132031-67759df45fbb golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect diff --git a/go.sum b/go.sum index e095086..74cde77 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,34 @@ +github.com/aliyun/alibaba-cloud-sdk-go v1.60.327 h1:MZrGWhrO7yXMOv+Ul0V/yXzxQ3Pso6WGy+SNP2102+c= +github.com/aliyun/alibaba-cloud-sdk-go v1.60.327/go.mod h1:mNZkuqaeM5UCiAdkV4r+lrheu8Q5fe/487bRFrGYZ8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/carlosdp/twiliogo v0.0.0-20140102225436-f61c8230fa91 h1:fIflfwVZsOHJD5nWJXEmdGrHnhVGVWtvVZAXMsHlCDU= github.com/carlosdp/twiliogo v0.0.0-20140102225436-f61c8230fa91/go.mod h1:pAxCBpjl/0JxYZlWGP/Dyi8f/LQSCQD2WAsG/iNzqQ8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 h1:GT4RsKmHh1uZyhmTkWJTDALRjSHYQp6FRKrotf0zhAs= github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40/go.mod h1:NtmN9h8vrTveVQRLHcX2HQ5wIPBDCsZ351TGbZWgg38= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/matttproud/golang_protobuf_extensions v1.0.0 h1:YNOwxxSJzSUARoD9KRZLzM9Y858MNGCOACTvCW9TSAc= github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e h1:hsSmRHe7psyLMQ/Kn8xgr0koZKB4rfgO4dsKgP6S4Dc= github.com/messagebird/go-rest-api v0.0.0-20180517131710-a9514230491e/go.mod h1:+XI/mPytD/HkPfkOm6IDu6hWgIyePQYZ4Fb5Nlm2las= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/alertmanager v0.14.0 h1:pO6S2wb3PAX0LedGvfaFlJQZNSAB0HrsST5//thlBq0= @@ -26,18 +41,29 @@ github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89 h1:7KBNF1zLlfEkG github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d h1:RCcsxyRr6+/pLg6wr0cUjPovhEhSNOtPh0SOz6u3hGU= github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/xconstruct/go-pushbullet v0.0.0-20171206132031-67759df45fbb h1:m+CPNoRrlFVxLKZeodSyEc9cc1GBWYJutHO/eOByUo8= github.com/xconstruct/go-pushbullet v0.0.0-20171206132031-67759df45fbb/go.mod h1:OdGNyFi3/K/Fl/3pZu3lAGKMBhTQDl9Lgjn08LSA95Q= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/njern/gonexmo.v1 v1.0.1 h1:fTAudpN4nmfmdyGU+W4FbU0Ifh+jUsQao/F5neKD2Hs= gopkg.in/njern/gonexmo.v1 v1.0.1/go.mod h1:PwngK45ZxAYI4/2IVT5FELDeSohbM1e4kyjYTO2OkCg= gopkg.in/telegram-bot-api.v4 v4.6.2 h1:oUu8dyT/KzUWusD3OiPWTLoFM6n9uskQlW1GLoxjQcE= diff --git a/provider/aliyun/aliyun.go b/provider/aliyun/aliyun.go new file mode 100644 index 0000000..803aaf2 --- /dev/null +++ b/provider/aliyun/aliyun.go @@ -0,0 +1,61 @@ +package aliyun + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi" + "github.com/messagebird/sachet" +) + +type AliyunConfig struct { + AccessKey string `yaml:"access_key"` + AccessKeySecret string `yaml:"access_key_secret"` + + SignName string `yaml:"sign_name"` + TemplateCode string `yaml:"template_code"` + TemplateParamKey string `yaml:"template_param_key"` +} + +type Aliyun struct { + client *dysmsapi.Client + config *AliyunConfig +} + +func NewAliyun(config AliyunConfig) (*Aliyun, error) { + client, err := dysmsapi.NewClientWithAccessKey("cn-hangzhou", config.AccessKey, config.AccessKeySecret) + if err != nil { + return nil, err + } + return &Aliyun{ + client: client, + config: &config, + }, nil +} + +func (aliyun *Aliyun) Send(message sachet.Message) error { + var err error = nil + switch message.Type { + case "", "text": + request := dysmsapi.CreateSendSmsRequest() + request.Scheme = "https" + request.SignName = aliyun.config.SignName + request.TemplateCode = aliyun.config.TemplateCode + request.PhoneNumbers = strings.Join(message.To, ",") + templateParam := make(map[string]string) + templateParam[aliyun.config.TemplateParamKey] = message.Text + templateParamByte, err := json.Marshal(templateParam) + if err == nil { + request.TemplateParam = string(templateParamByte) + var response *dysmsapi.SendSmsResponse + response, err = aliyun.client.SendSms(request) + if err == nil && (!response.IsSuccess() || response.Code != "") { + err = fmt.Errorf(response.String()) + } + } + default: + return fmt.Errorf("unknown message type %s", message.Type) + } + return err +} From 9c75287e825106f396d863a8e72b547424873f41 Mon Sep 17 00:00:00 2001 From: Herb Date: Fri, 10 Jan 2020 16:10:56 +0800 Subject: [PATCH 21/63] add example config --- examples/config.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/config.yaml b/examples/config.yaml index 4c79b01..2baaa47 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -1,4 +1,10 @@ providers: + aliyun: + access_key: access_key + access_key_secret: access_key_secret + sign_name: sign_name + template_code: template_code + template_param_key: text messagebird: access_key: 'live_qKwVZ02ULV70GqabBYxLU8d5r' debug: true From cf8e28d0d95b74285c70e5c7ed9ccfa53db27fca Mon Sep 17 00:00:00 2001 From: Herb Date: Fri, 10 Jan 2020 16:19:46 +0800 Subject: [PATCH 22/63] add vendor --- .../aliyun/alibaba-cloud-sdk-go/LICENSE | 201 + .../alibaba-cloud-sdk-go/sdk/api_timeout.go | 249 + .../sdk/auth/credential.go | 18 + .../auth/credentials/access_key_credential.go | 34 + .../credentials/bearer_token_credential.go | 12 + .../sdk/auth/credentials/ecs_ram_role.go | 29 + .../sdk/auth/credentials/provider/env.go | 30 + .../provider/instance_credentials.go | 92 + .../provider/profile_credentials.go | 159 + .../sdk/auth/credentials/provider/provider.go | 19 + .../credentials/provider/provider_chain.go | 34 + .../credentials/rsa_key_pair_credential.go | 15 + .../sdk/auth/credentials/sts_credential.go | 15 + .../credentials/sts_role_arn_credential.go | 61 + .../sdk/auth/roa_signature_composer.go | 138 + .../sdk/auth/rpc_signature_composer.go | 94 + .../alibaba-cloud-sdk-go/sdk/auth/signer.go | 98 + .../sdk/auth/signers/algorithms.go | 57 + .../sdk/auth/signers/credential_updater.go | 54 + .../sdk/auth/signers/session_credential.go | 7 + .../sdk/auth/signers/signer_access_key.go | 54 + .../sdk/auth/signers/signer_bearer_token.go | 35 + .../sdk/auth/signers/signer_ecs_ram_role.go | 167 + .../sdk/auth/signers/signer_key_pair.go | 148 + .../sdk/auth/signers/signer_ram_role_arn.go | 175 + .../sdk/auth/signers/signer_sts_token.go | 54 + .../sdk/auth/signers/signer_v2.go | 54 + .../aliyun/alibaba-cloud-sdk-go/sdk/client.go | 794 ++++ .../aliyun/alibaba-cloud-sdk-go/sdk/config.go | 91 + .../sdk/endpoints/endpoints_config.go | 4126 +++++++++++++++++ .../sdk/endpoints/local_global_resolver.go | 43 + .../sdk/endpoints/local_regional_resolver.go | 48 + .../sdk/endpoints/location_resolver.go | 176 + .../sdk/endpoints/mapping_resolver.go | 49 + .../sdk/endpoints/resolver.go | 96 + .../sdk/errors/client_error.go | 92 + .../alibaba-cloud-sdk-go/sdk/errors/error.go | 23 + .../sdk/errors/server_error.go | 123 + .../signature_does_not_match_wrapper.go | 45 + .../aliyun/alibaba-cloud-sdk-go/sdk/logger.go | 116 + .../sdk/requests/acs_request.go | 442 ++ .../sdk/requests/common_request.go | 108 + .../sdk/requests/roa_request.go | 152 + .../sdk/requests/rpc_request.go | 79 + .../sdk/requests/types.go | 53 + .../sdk/responses/json_parser.go | 328 ++ .../sdk/responses/response.go | 144 + .../alibaba-cloud-sdk-go/sdk/utils/debug.go | 36 + .../alibaba-cloud-sdk-go/sdk/utils/utils.go | 141 + .../services/dysmsapi/add_sms_sign.go | 118 + .../services/dysmsapi/add_sms_template.go | 112 + .../services/dysmsapi/client.go | 129 + .../services/dysmsapi/delete_sms_sign.go | 109 + .../services/dysmsapi/delete_sms_template.go | 109 + .../services/dysmsapi/endpoint.go | 36 + .../services/dysmsapi/modify_sms_sign.go | 118 + .../services/dysmsapi/modify_sms_template.go | 113 + .../services/dysmsapi/query_send_details.go | 114 + .../services/dysmsapi/query_sms_sign.go | 112 + .../services/dysmsapi/query_sms_template.go | 115 + .../services/dysmsapi/send_batch_sms.go | 113 + .../services/dysmsapi/send_sms.go | 114 + .../dysmsapi/struct_sms_send_detail_dt_os.go | 21 + .../dysmsapi/struct_sms_send_detail_dto.go | 28 + vendor/github.com/davecgh/go-spew/LICENSE | 2 +- .../github.com/davecgh/go-spew/spew/bypass.go | 187 +- .../davecgh/go-spew/spew/bypasssafe.go | 2 +- .../github.com/davecgh/go-spew/spew/common.go | 2 +- .../github.com/davecgh/go-spew/spew/dump.go | 10 +- .../github.com/davecgh/go-spew/spew/format.go | 4 +- .../jmespath/go-jmespath/.gitignore | 4 + .../jmespath/go-jmespath/.travis.yml | 9 + .../github.com/jmespath/go-jmespath/LICENSE | 13 + .../github.com/jmespath/go-jmespath/Makefile | 44 + .../github.com/jmespath/go-jmespath/README.md | 7 + vendor/github.com/jmespath/go-jmespath/api.go | 49 + .../go-jmespath/astnodetype_string.go | 16 + .../jmespath/go-jmespath/functions.go | 842 ++++ .../jmespath/go-jmespath/interpreter.go | 418 ++ .../github.com/jmespath/go-jmespath/lexer.go | 420 ++ .../github.com/jmespath/go-jmespath/parser.go | 603 +++ .../jmespath/go-jmespath/toktype_string.go | 16 + .../github.com/jmespath/go-jmespath/util.go | 185 + .../github.com/json-iterator/go/.codecov.yml | 3 + vendor/github.com/json-iterator/go/.gitignore | 4 + .../github.com/json-iterator/go/.travis.yml | 14 + vendor/github.com/json-iterator/go/Gopkg.lock | 21 + vendor/github.com/json-iterator/go/Gopkg.toml | 26 + vendor/github.com/json-iterator/go/LICENSE | 21 + vendor/github.com/json-iterator/go/README.md | 91 + vendor/github.com/json-iterator/go/adapter.go | 150 + vendor/github.com/json-iterator/go/any.go | 321 ++ .../github.com/json-iterator/go/any_array.go | 278 ++ .../github.com/json-iterator/go/any_bool.go | 137 + .../github.com/json-iterator/go/any_float.go | 83 + .../github.com/json-iterator/go/any_int32.go | 74 + .../github.com/json-iterator/go/any_int64.go | 74 + .../json-iterator/go/any_invalid.go | 82 + vendor/github.com/json-iterator/go/any_nil.go | 69 + .../github.com/json-iterator/go/any_number.go | 123 + .../github.com/json-iterator/go/any_object.go | 374 ++ vendor/github.com/json-iterator/go/any_str.go | 166 + .../github.com/json-iterator/go/any_uint32.go | 74 + .../github.com/json-iterator/go/any_uint64.go | 74 + vendor/github.com/json-iterator/go/build.sh | 12 + vendor/github.com/json-iterator/go/config.go | 375 ++ .../go/fuzzy_mode_convert_table.md | 7 + vendor/github.com/json-iterator/go/iter.go | 322 ++ .../github.com/json-iterator/go/iter_array.go | 58 + .../github.com/json-iterator/go/iter_float.go | 347 ++ .../github.com/json-iterator/go/iter_int.go | 345 ++ .../json-iterator/go/iter_object.go | 251 + .../github.com/json-iterator/go/iter_skip.go | 129 + .../json-iterator/go/iter_skip_sloppy.go | 144 + .../json-iterator/go/iter_skip_strict.go | 89 + .../github.com/json-iterator/go/iter_str.go | 215 + .../github.com/json-iterator/go/jsoniter.go | 18 + vendor/github.com/json-iterator/go/pool.go | 42 + vendor/github.com/json-iterator/go/reflect.go | 332 ++ .../json-iterator/go/reflect_array.go | 104 + .../json-iterator/go/reflect_dynamic.go | 70 + .../json-iterator/go/reflect_extension.go | 483 ++ .../json-iterator/go/reflect_json_number.go | 112 + .../go/reflect_json_raw_message.go | 60 + .../json-iterator/go/reflect_map.go | 326 ++ .../json-iterator/go/reflect_marshaler.go | 218 + .../json-iterator/go/reflect_native.go | 451 ++ .../json-iterator/go/reflect_optional.go | 133 + .../json-iterator/go/reflect_slice.go | 99 + .../go/reflect_struct_decoder.go | 1048 +++++ .../go/reflect_struct_encoder.go | 210 + vendor/github.com/json-iterator/go/stream.go | 211 + .../json-iterator/go/stream_float.go | 94 + .../github.com/json-iterator/go/stream_int.go | 190 + .../github.com/json-iterator/go/stream_str.go | 372 ++ vendor/github.com/json-iterator/go/test.sh | 12 + .../modern-go/concurrent/.gitignore | 1 + .../modern-go/concurrent/.travis.yml | 14 + .../github.com/modern-go/concurrent/LICENSE | 201 + .../github.com/modern-go/concurrent/README.md | 49 + .../modern-go/concurrent/executor.go | 14 + .../modern-go/concurrent/go_above_19.go | 15 + .../modern-go/concurrent/go_below_19.go | 33 + vendor/github.com/modern-go/concurrent/log.go | 13 + .../github.com/modern-go/concurrent/test.sh | 12 + .../concurrent/unbounded_executor.go | 119 + .../github.com/modern-go/reflect2/.gitignore | 2 + .../github.com/modern-go/reflect2/.travis.yml | 15 + .../github.com/modern-go/reflect2/Gopkg.lock | 15 + .../github.com/modern-go/reflect2/Gopkg.toml | 35 + vendor/github.com/modern-go/reflect2/LICENSE | 201 + .../github.com/modern-go/reflect2/README.md | 71 + .../modern-go/reflect2/go_above_17.go | 8 + .../modern-go/reflect2/go_above_19.go | 14 + .../modern-go/reflect2/go_below_17.go | 9 + .../modern-go/reflect2/go_below_19.go | 14 + .../github.com/modern-go/reflect2/reflect2.go | 298 ++ .../modern-go/reflect2/reflect2_amd64.s | 0 .../modern-go/reflect2/reflect2_kind.go | 30 + .../modern-go/reflect2/relfect2_386.s | 0 .../modern-go/reflect2/relfect2_amd64p32.s | 0 .../modern-go/reflect2/relfect2_arm.s | 0 .../modern-go/reflect2/relfect2_arm64.s | 0 .../modern-go/reflect2/relfect2_mips64x.s | 0 .../modern-go/reflect2/relfect2_mipsx.s | 0 .../modern-go/reflect2/relfect2_ppc64x.s | 0 .../modern-go/reflect2/relfect2_s390x.s | 0 .../modern-go/reflect2/safe_field.go | 58 + .../github.com/modern-go/reflect2/safe_map.go | 101 + .../modern-go/reflect2/safe_slice.go | 92 + .../modern-go/reflect2/safe_struct.go | 29 + .../modern-go/reflect2/safe_type.go | 78 + vendor/github.com/modern-go/reflect2/test.sh | 12 + .../github.com/modern-go/reflect2/type_map.go | 103 + .../modern-go/reflect2/unsafe_array.go | 65 + .../modern-go/reflect2/unsafe_eface.go | 59 + .../modern-go/reflect2/unsafe_field.go | 74 + .../modern-go/reflect2/unsafe_iface.go | 64 + .../modern-go/reflect2/unsafe_link.go | 70 + .../modern-go/reflect2/unsafe_map.go | 138 + .../modern-go/reflect2/unsafe_ptr.go | 46 + .../modern-go/reflect2/unsafe_slice.go | 177 + .../modern-go/reflect2/unsafe_struct.go | 59 + .../modern-go/reflect2/unsafe_type.go | 85 + vendor/github.com/stretchr/testify/LICENSE | 35 +- .../testify/assert/assertion_format.go | 139 +- .../testify/assert/assertion_format.go.tmpl | 1 + .../testify/assert/assertion_forward.go | 278 +- .../testify/assert/assertion_forward.go.tmpl | 1 + .../stretchr/testify/assert/assertions.go | 242 +- .../testify/assert/http_assertions.go | 22 +- .../github.com/stretchr/testify/mock/mock.go | 129 +- vendor/gopkg.in/ini.v1/.gitignore | 6 + vendor/gopkg.in/ini.v1/.travis.yml | 17 + vendor/gopkg.in/ini.v1/LICENSE | 191 + vendor/gopkg.in/ini.v1/Makefile | 15 + vendor/gopkg.in/ini.v1/README.md | 46 + vendor/gopkg.in/ini.v1/error.go | 32 + vendor/gopkg.in/ini.v1/file.go | 418 ++ vendor/gopkg.in/ini.v1/ini.go | 219 + vendor/gopkg.in/ini.v1/key.go | 752 +++ vendor/gopkg.in/ini.v1/parser.go | 488 ++ vendor/gopkg.in/ini.v1/section.go | 259 ++ vendor/gopkg.in/ini.v1/struct.go | 512 ++ vendor/modules.txt | 32 +- 205 files changed, 28958 insertions(+), 209 deletions(-) create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/LICENSE create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/api_timeout.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credential.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/access_key_credential.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/bearer_token_credential.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/ecs_ram_role.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/env.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/instance_credentials.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/profile_credentials.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider_chain.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_credential.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_role_arn_credential.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/roa_signature_composer.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/rpc_signature_composer.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signer.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/credential_updater.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/session_credential.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_bearer_token.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/client.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/config.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/endpoints_config.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_global_resolver.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_regional_resolver.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/location_resolver.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/mapping_resolver.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/resolver.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/client_error.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/error.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/server_error.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/signature_does_not_match_wrapper.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/logger.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/common_request.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/roa_request.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/rpc_request.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/types.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/json_parser.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/response.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/debug.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_sign.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_template.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/client.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_sign.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_template.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/endpoint.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_sign.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_template.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_send_details.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_sign.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_template.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_batch_sms.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_sms.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dt_os.go create mode 100644 vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dto.go create mode 100644 vendor/github.com/jmespath/go-jmespath/.gitignore create mode 100644 vendor/github.com/jmespath/go-jmespath/.travis.yml create mode 100644 vendor/github.com/jmespath/go-jmespath/LICENSE create mode 100644 vendor/github.com/jmespath/go-jmespath/Makefile create mode 100644 vendor/github.com/jmespath/go-jmespath/README.md create mode 100644 vendor/github.com/jmespath/go-jmespath/api.go create mode 100644 vendor/github.com/jmespath/go-jmespath/astnodetype_string.go create mode 100644 vendor/github.com/jmespath/go-jmespath/functions.go create mode 100644 vendor/github.com/jmespath/go-jmespath/interpreter.go create mode 100644 vendor/github.com/jmespath/go-jmespath/lexer.go create mode 100644 vendor/github.com/jmespath/go-jmespath/parser.go create mode 100644 vendor/github.com/jmespath/go-jmespath/toktype_string.go create mode 100644 vendor/github.com/jmespath/go-jmespath/util.go create mode 100644 vendor/github.com/json-iterator/go/.codecov.yml create mode 100644 vendor/github.com/json-iterator/go/.gitignore create mode 100644 vendor/github.com/json-iterator/go/.travis.yml create mode 100644 vendor/github.com/json-iterator/go/Gopkg.lock create mode 100644 vendor/github.com/json-iterator/go/Gopkg.toml create mode 100644 vendor/github.com/json-iterator/go/LICENSE create mode 100644 vendor/github.com/json-iterator/go/README.md create mode 100644 vendor/github.com/json-iterator/go/adapter.go create mode 100644 vendor/github.com/json-iterator/go/any.go create mode 100644 vendor/github.com/json-iterator/go/any_array.go create mode 100644 vendor/github.com/json-iterator/go/any_bool.go create mode 100644 vendor/github.com/json-iterator/go/any_float.go create mode 100644 vendor/github.com/json-iterator/go/any_int32.go create mode 100644 vendor/github.com/json-iterator/go/any_int64.go create mode 100644 vendor/github.com/json-iterator/go/any_invalid.go create mode 100644 vendor/github.com/json-iterator/go/any_nil.go create mode 100644 vendor/github.com/json-iterator/go/any_number.go create mode 100644 vendor/github.com/json-iterator/go/any_object.go create mode 100644 vendor/github.com/json-iterator/go/any_str.go create mode 100644 vendor/github.com/json-iterator/go/any_uint32.go create mode 100644 vendor/github.com/json-iterator/go/any_uint64.go create mode 100644 vendor/github.com/json-iterator/go/build.sh create mode 100644 vendor/github.com/json-iterator/go/config.go create mode 100644 vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md create mode 100644 vendor/github.com/json-iterator/go/iter.go create mode 100644 vendor/github.com/json-iterator/go/iter_array.go create mode 100644 vendor/github.com/json-iterator/go/iter_float.go create mode 100644 vendor/github.com/json-iterator/go/iter_int.go create mode 100644 vendor/github.com/json-iterator/go/iter_object.go create mode 100644 vendor/github.com/json-iterator/go/iter_skip.go create mode 100644 vendor/github.com/json-iterator/go/iter_skip_sloppy.go create mode 100644 vendor/github.com/json-iterator/go/iter_skip_strict.go create mode 100644 vendor/github.com/json-iterator/go/iter_str.go create mode 100644 vendor/github.com/json-iterator/go/jsoniter.go create mode 100644 vendor/github.com/json-iterator/go/pool.go create mode 100644 vendor/github.com/json-iterator/go/reflect.go create mode 100644 vendor/github.com/json-iterator/go/reflect_array.go create mode 100644 vendor/github.com/json-iterator/go/reflect_dynamic.go create mode 100644 vendor/github.com/json-iterator/go/reflect_extension.go create mode 100644 vendor/github.com/json-iterator/go/reflect_json_number.go create mode 100644 vendor/github.com/json-iterator/go/reflect_json_raw_message.go create mode 100644 vendor/github.com/json-iterator/go/reflect_map.go create mode 100644 vendor/github.com/json-iterator/go/reflect_marshaler.go create mode 100644 vendor/github.com/json-iterator/go/reflect_native.go create mode 100644 vendor/github.com/json-iterator/go/reflect_optional.go create mode 100644 vendor/github.com/json-iterator/go/reflect_slice.go create mode 100644 vendor/github.com/json-iterator/go/reflect_struct_decoder.go create mode 100644 vendor/github.com/json-iterator/go/reflect_struct_encoder.go create mode 100644 vendor/github.com/json-iterator/go/stream.go create mode 100644 vendor/github.com/json-iterator/go/stream_float.go create mode 100644 vendor/github.com/json-iterator/go/stream_int.go create mode 100644 vendor/github.com/json-iterator/go/stream_str.go create mode 100644 vendor/github.com/json-iterator/go/test.sh create mode 100644 vendor/github.com/modern-go/concurrent/.gitignore create mode 100644 vendor/github.com/modern-go/concurrent/.travis.yml create mode 100644 vendor/github.com/modern-go/concurrent/LICENSE create mode 100644 vendor/github.com/modern-go/concurrent/README.md create mode 100644 vendor/github.com/modern-go/concurrent/executor.go create mode 100644 vendor/github.com/modern-go/concurrent/go_above_19.go create mode 100644 vendor/github.com/modern-go/concurrent/go_below_19.go create mode 100644 vendor/github.com/modern-go/concurrent/log.go create mode 100644 vendor/github.com/modern-go/concurrent/test.sh create mode 100644 vendor/github.com/modern-go/concurrent/unbounded_executor.go create mode 100644 vendor/github.com/modern-go/reflect2/.gitignore create mode 100644 vendor/github.com/modern-go/reflect2/.travis.yml create mode 100644 vendor/github.com/modern-go/reflect2/Gopkg.lock create mode 100644 vendor/github.com/modern-go/reflect2/Gopkg.toml create mode 100644 vendor/github.com/modern-go/reflect2/LICENSE create mode 100644 vendor/github.com/modern-go/reflect2/README.md create mode 100644 vendor/github.com/modern-go/reflect2/go_above_17.go create mode 100644 vendor/github.com/modern-go/reflect2/go_above_19.go create mode 100644 vendor/github.com/modern-go/reflect2/go_below_17.go create mode 100644 vendor/github.com/modern-go/reflect2/go_below_19.go create mode 100644 vendor/github.com/modern-go/reflect2/reflect2.go create mode 100644 vendor/github.com/modern-go/reflect2/reflect2_amd64.s create mode 100644 vendor/github.com/modern-go/reflect2/reflect2_kind.go create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_386.s create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_amd64p32.s create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_arm.s create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_arm64.s create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_mips64x.s create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_mipsx.s create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_ppc64x.s create mode 100644 vendor/github.com/modern-go/reflect2/relfect2_s390x.s create mode 100644 vendor/github.com/modern-go/reflect2/safe_field.go create mode 100644 vendor/github.com/modern-go/reflect2/safe_map.go create mode 100644 vendor/github.com/modern-go/reflect2/safe_slice.go create mode 100644 vendor/github.com/modern-go/reflect2/safe_struct.go create mode 100644 vendor/github.com/modern-go/reflect2/safe_type.go create mode 100644 vendor/github.com/modern-go/reflect2/test.sh create mode 100644 vendor/github.com/modern-go/reflect2/type_map.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_array.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_eface.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_field.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_iface.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_link.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_map.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_ptr.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_slice.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_struct.go create mode 100644 vendor/github.com/modern-go/reflect2/unsafe_type.go create mode 100644 vendor/gopkg.in/ini.v1/.gitignore create mode 100644 vendor/gopkg.in/ini.v1/.travis.yml create mode 100644 vendor/gopkg.in/ini.v1/LICENSE create mode 100644 vendor/gopkg.in/ini.v1/Makefile create mode 100644 vendor/gopkg.in/ini.v1/README.md create mode 100644 vendor/gopkg.in/ini.v1/error.go create mode 100644 vendor/gopkg.in/ini.v1/file.go create mode 100644 vendor/gopkg.in/ini.v1/ini.go create mode 100644 vendor/gopkg.in/ini.v1/key.go create mode 100644 vendor/gopkg.in/ini.v1/parser.go create mode 100644 vendor/gopkg.in/ini.v1/section.go create mode 100644 vendor/gopkg.in/ini.v1/struct.go diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/LICENSE b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/LICENSE new file mode 100644 index 0000000..0c44dce --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2009-present, Alibaba Cloud All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/api_timeout.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/api_timeout.go new file mode 100644 index 0000000..d7968da --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/api_timeout.go @@ -0,0 +1,249 @@ +package sdk + +import ( + "encoding/json" + "strings" + "time" +) + +var apiTimeouts = `{ + "ecs": { + "ActivateRouterInterface": 10, + "AddTags": 61, + "AllocateDedicatedHosts": 10, + "AllocateEipAddress": 17, + "AllocatePublicIpAddress": 36, + "ApplyAutoSnapshotPolicy": 10, + "AssignIpv6Addresses": 10, + "AssignPrivateIpAddresses": 10, + "AssociateEipAddress": 17, + "AttachClassicLinkVpc": 14, + "AttachDisk": 36, + "AttachInstanceRamRole": 11, + "AttachKeyPair": 16, + "AttachNetworkInterface": 16, + "AuthorizeSecurityGroupEgress": 16, + "AuthorizeSecurityGroup": 16, + "CancelAutoSnapshotPolicy": 10, + "CancelCopyImage": 10, + "CancelPhysicalConnection": 10, + "CancelSimulatedSystemEvents": 10, + "CancelTask": 10, + "ConnectRouterInterface": 10, + "ConvertNatPublicIpToEip": 12, + "CopyImage": 10, + "CreateAutoSnapshotPolicy": 10, + "CreateCommand": 16, + "CreateDeploymentSet": 16, + "CreateDisk": 36, + "CreateHpcCluster": 10, + "CreateImage": 36, + "CreateInstance": 86, + "CreateKeyPair": 10, + "CreateLaunchTemplate": 10, + "CreateLaunchTemplateVersion": 10, + "CreateNatGateway": 36, + "CreateNetworkInterfacePermission": 13, + "CreateNetworkInterface": 16, + "CreatePhysicalConnection": 10, + "CreateRouteEntry": 17, + "CreateRouterInterface": 10, + "CreateSecurityGroup": 86, + "CreateSimulatedSystemEvents": 10, + "CreateSnapshot": 86, + "CreateVirtualBorderRouter": 10, + "CreateVpc": 16, + "CreateVSwitch": 17, + "DeactivateRouterInterface": 10, + "DeleteAutoSnapshotPolicy": 10, + "DeleteBandwidthPackage": 10, + "DeleteCommand": 16, + "DeleteDeploymentSet": 12, + "DeleteDisk": 16, + "DeleteHpcCluster": 10, + "DeleteImage": 36, + "DeleteInstance": 66, + "DeleteKeyPairs": 10, + "DeleteLaunchTemplate": 10, + "DeleteLaunchTemplateVersion": 10, + "DeleteNatGateway": 10, + "DeleteNetworkInterfacePermission": 10, + "DeleteNetworkInterface": 16, + "DeletePhysicalConnection": 10, + "DeleteRouteEntry": 16, + "DeleteRouterInterface": 10, + "DeleteSecurityGroup": 87, + "DeleteSnapshot": 17, + "DeleteVirtualBorderRouter": 10, + "DeleteVpc": 17, + "DeleteVSwitch": 17, + "DescribeAccessPoints": 10, + "DescribeAccountAttributes": 10, + "DescribeAutoSnapshotPolicyEx": 16, + "DescribeAvailableResource": 10, + "DescribeBandwidthLimitation": 16, + "DescribeBandwidthPackages": 10, + "DescribeClassicLinkInstances": 15, + "DescribeCloudAssistantStatus": 16, + "DescribeClusters": 10, + "DescribeCommands": 16, + "DescribeDedicatedHosts": 10, + "DescribeDedicatedHostTypes": 10, + "DescribeDeploymentSets": 26, + "DescribeDiskMonitorData": 16, + "DescribeDisksFullStatus": 14, + "DescribeDisks": 19, + "DescribeEipAddresses": 16, + "DescribeEipMonitorData": 16, + "DescribeEniMonitorData": 10, + "DescribeHaVips": 10, + "DescribeHpcClusters": 16, + "DescribeImageSharePermission": 10, + "DescribeImages": 38, + "DescribeImageSupportInstanceTypes": 16, + "DescribeInstanceAttribute": 36, + "DescribeInstanceAutoRenewAttribute": 17, + "DescribeInstanceHistoryEvents": 19, + "DescribeInstanceMonitorData": 19, + "DescribeInstancePhysicalAttribute": 10, + "DescribeInstanceRamRole": 11, + "DescribeInstancesFullStatus": 14, + "DescribeInstances": 10, + "DescribeInstanceStatus": 26, + "DescribeInstanceTopology": 12, + "DescribeInstanceTypeFamilies": 17, + "DescribeInstanceTypes": 17, + "DescribeInstanceVncPasswd": 10, + "DescribeInstanceVncUrl": 36, + "DescribeInvocationResults": 16, + "DescribeInvocations": 16, + "DescribeKeyPairs": 12, + "DescribeLaunchTemplates": 16, + "DescribeLaunchTemplateVersions": 16, + "DescribeLimitation": 36, + "DescribeNatGateways": 10, + "DescribeNetworkInterfacePermissions": 13, + "DescribeNetworkInterfaces": 16, + "DescribeNewProjectEipMonitorData": 16, + "DescribePhysicalConnections": 10, + "DescribePrice": 16, + "DescribeRecommendInstanceType": 10, + "DescribeRegions": 19, + "DescribeRenewalPrice": 16, + "DescribeResourceByTags": 10, + "DescribeResourcesModification": 17, + "DescribeRouterInterfaces": 10, + "DescribeRouteTables": 17, + "DescribeSecurityGroupAttribute": 133, + "DescribeSecurityGroupReferences": 16, + "DescribeSecurityGroups": 25, + "DescribeSnapshotLinks": 17, + "DescribeSnapshotMonitorData": 12, + "DescribeSnapshotPackage": 10, + "DescribeSnapshots": 26, + "DescribeSnapshotsUsage": 26, + "DescribeSpotPriceHistory": 22, + "DescribeTags": 17, + "DescribeTaskAttribute": 10, + "DescribeTasks": 11, + "DescribeUserBusinessBehavior": 13, + "DescribeUserData": 10, + "DescribeVirtualBorderRoutersForPhysicalConnection": 10, + "DescribeVirtualBorderRouters": 10, + "DescribeVpcs": 41, + "DescribeVRouters": 17, + "DescribeVSwitches": 17, + "DescribeZones": 103, + "DetachClassicLinkVpc": 14, + "DetachDisk": 17, + "DetachInstanceRamRole": 10, + "DetachKeyPair": 10, + "DetachNetworkInterface": 16, + "EipFillParams": 19, + "EipFillProduct": 13, + "EipNotifyPaid": 10, + "EnablePhysicalConnection": 10, + "ExportImage": 10, + "GetInstanceConsoleOutput": 14, + "GetInstanceScreenshot": 14, + "ImportImage": 29, + "ImportKeyPair": 10, + "InstallCloudAssistant": 10, + "InvokeCommand": 16, + "JoinResourceGroup": 10, + "JoinSecurityGroup": 66, + "LeaveSecurityGroup": 66, + "ModifyAutoSnapshotPolicyEx": 10, + "ModifyBandwidthPackageSpec": 11, + "ModifyCommand": 10, + "ModifyDeploymentSetAttribute": 10, + "ModifyDiskAttribute": 16, + "ModifyDiskChargeType": 13, + "ModifyEipAddressAttribute": 14, + "ModifyImageAttribute": 10, + "ModifyImageSharePermission": 16, + "ModifyInstanceAttribute": 22, + "ModifyInstanceAutoReleaseTime": 15, + "ModifyInstanceAutoRenewAttribute": 16, + "ModifyInstanceChargeType": 22, + "ModifyInstanceDeployment": 10, + "ModifyInstanceNetworkSpec": 36, + "ModifyInstanceSpec": 62, + "ModifyInstanceVncPasswd": 35, + "ModifyInstanceVpcAttribute": 15, + "ModifyLaunchTemplateDefaultVersion": 10, + "ModifyNetworkInterfaceAttribute": 10, + "ModifyPhysicalConnectionAttribute": 10, + "ModifyPrepayInstanceSpec": 13, + "ModifyRouterInterfaceAttribute": 10, + "ModifySecurityGroupAttribute": 10, + "ModifySecurityGroupEgressRule": 10, + "ModifySecurityGroupPolicy": 10, + "ModifySecurityGroupRule": 16, + "ModifySnapshotAttribute": 10, + "ModifyUserBusinessBehavior": 10, + "ModifyVirtualBorderRouterAttribute": 10, + "ModifyVpcAttribute": 10, + "ModifyVRouterAttribute": 10, + "ModifyVSwitchAttribute": 10, + "ReActivateInstances": 10, + "RebootInstance": 27, + "RedeployInstance": 14, + "ReInitDisk": 16, + "ReleaseDedicatedHost": 10, + "ReleaseEipAddress": 16, + "ReleasePublicIpAddress": 10, + "RemoveTags": 10, + "RenewInstance": 19, + "ReplaceSystemDisk": 36, + "ResetDisk": 36, + "ResizeDisk": 11, + "RevokeSecurityGroupEgress": 13, + "RevokeSecurityGroup": 16, + "RunInstances": 86, + "StartInstance": 46, + "StopInstance": 27, + "StopInvocation": 10, + "TerminatePhysicalConnection": 10, + "TerminateVirtualBorderRouter": 10, + "UnassignIpv6Addresses": 10, + "UnassignPrivateIpAddresses": 10, + "UnassociateEipAddress": 16 + } +} +` + +func getAPIMaxTimeout(product, actionName string) (time.Duration, bool) { + timeout := make(map[string]map[string]int) + err := json.Unmarshal([]byte(apiTimeouts), &timeout) + if err != nil { + return 0 * time.Millisecond, false + } + + obj := timeout[strings.ToLower(product)] + if obj != nil && obj[actionName] != 0 { + return time.Duration(obj[actionName]) * time.Second, true + } + + return 0 * time.Millisecond, false +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credential.go new file mode 100644 index 0000000..7f20b7a --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credential.go @@ -0,0 +1,18 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package auth + +type Credential interface { +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/access_key_credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/access_key_credential.go new file mode 100644 index 0000000..68f8226 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/access_key_credential.go @@ -0,0 +1,34 @@ +package credentials + +// Deprecated: Use AccessKeyCredential in this package instead. +type BaseCredential struct { + AccessKeyId string + AccessKeySecret string +} + +type AccessKeyCredential struct { + AccessKeyId string + AccessKeySecret string +} + +// Deprecated: Use NewAccessKeyCredential in this package instead. +func NewBaseCredential(accessKeyId, accessKeySecret string) *BaseCredential { + return &BaseCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + } +} + +func (baseCred *BaseCredential) ToAccessKeyCredential() *AccessKeyCredential { + return &AccessKeyCredential{ + AccessKeyId: baseCred.AccessKeyId, + AccessKeySecret: baseCred.AccessKeySecret, + } +} + +func NewAccessKeyCredential(accessKeyId, accessKeySecret string) *AccessKeyCredential { + return &AccessKeyCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/bearer_token_credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/bearer_token_credential.go new file mode 100644 index 0000000..6d4763e --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/bearer_token_credential.go @@ -0,0 +1,12 @@ +package credentials + +type BearerTokenCredential struct { + BearerToken string +} + +// NewBearerTokenCredential return a BearerTokenCredential object +func NewBearerTokenCredential(token string) *BearerTokenCredential { + return &BearerTokenCredential{ + BearerToken: token, + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/ecs_ram_role.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/ecs_ram_role.go new file mode 100644 index 0000000..55a5c2d --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/ecs_ram_role.go @@ -0,0 +1,29 @@ +package credentials + +func (oldCred *StsRoleNameOnEcsCredential) ToEcsRamRoleCredential() *EcsRamRoleCredential { + return &EcsRamRoleCredential{ + RoleName: oldCred.RoleName, + } +} + +type EcsRamRoleCredential struct { + RoleName string +} + +func NewEcsRamRoleCredential(roleName string) *EcsRamRoleCredential { + return &EcsRamRoleCredential{ + RoleName: roleName, + } +} + +// Deprecated: Use EcsRamRoleCredential in this package instead. +type StsRoleNameOnEcsCredential struct { + RoleName string +} + +// Deprecated: Use NewEcsRamRoleCredential in this package instead. +func NewStsRoleNameOnEcsCredential(roleName string) *StsRoleNameOnEcsCredential { + return &StsRoleNameOnEcsCredential{ + RoleName: roleName, + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/env.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/env.go new file mode 100644 index 0000000..3cd0d02 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/env.go @@ -0,0 +1,30 @@ +package provider + +import ( + "errors" + "os" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" +) + +type EnvProvider struct{} + +var ProviderEnv = new(EnvProvider) + +func NewEnvProvider() Provider { + return &EnvProvider{} +} + +func (p *EnvProvider) Resolve() (auth.Credential, error) { + accessKeyID, ok1 := os.LookupEnv(ENVAccessKeyID) + accessKeySecret, ok2 := os.LookupEnv(ENVAccessKeySecret) + if !ok1 || !ok2 { + return nil, nil + } + if accessKeyID == "" || accessKeySecret == "" { + return nil, errors.New("Environmental variable (ALIBABACLOUD_ACCESS_KEY_ID or ALIBABACLOUD_ACCESS_KEY_SECRET) is empty") + } + return credentials.NewAccessKeyCredential(accessKeyID, accessKeySecret), nil +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/instance_credentials.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/instance_credentials.go new file mode 100644 index 0000000..1906d21 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/instance_credentials.go @@ -0,0 +1,92 @@ +package provider + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/http" + "os" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" +) + +var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/" + +type InstanceCredentialsProvider struct{} + +var ProviderInstance = new(InstanceCredentialsProvider) + +var HookGet = func(fn func(string) (int, []byte, error)) func(string) (int, []byte, error) { + return fn +} + +func NewInstanceCredentialsProvider() Provider { + return &InstanceCredentialsProvider{} +} + +func (p *InstanceCredentialsProvider) Resolve() (auth.Credential, error) { + roleName, ok := os.LookupEnv(ENVEcsMetadata) + if !ok { + return nil, nil + } + if roleName == "" { + return nil, errors.New("Environmental variable 'ALIBABA_CLOUD_ECS_METADATA' are empty") + } + status, content, err := HookGet(get)(securityCredURL + roleName) + if err != nil { + return nil, err + } + if status != 200 { + if status == 404 { + return nil, fmt.Errorf("The role was not found in the instance") + } + return nil, fmt.Errorf("Received %d when getting security credentials for %s", status, roleName) + } + body := make(map[string]interface{}) + + if err := json.Unmarshal(content, &body); err != nil { + return nil, err + } + + accessKeyID, err := extractString(body, "AccessKeyId") + if err != nil { + return nil, err + } + accessKeySecret, err := extractString(body, "AccessKeySecret") + if err != nil { + return nil, err + } + securityToken, err := extractString(body, "SecurityToken") + if err != nil { + return nil, err + } + + return credentials.NewStsTokenCredential(accessKeyID, accessKeySecret, securityToken), nil +} + +func get(url string) (status int, content []byte, err error) { + httpClient := http.DefaultClient + httpClient.Timeout = time.Second * 1 + resp, err := httpClient.Get(url) + if err != nil { + return + } + defer resp.Body.Close() + content, err = ioutil.ReadAll(resp.Body) + return resp.StatusCode, content, err +} + +func extractString(m map[string]interface{}, key string) (string, error) { + raw, ok := m[key] + if !ok { + return "", fmt.Errorf("%s not in map", key) + } + str, ok := raw.(string) + if !ok { + return "", fmt.Errorf("%s is not a string in map", key) + } + return str, nil +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/profile_credentials.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/profile_credentials.go new file mode 100644 index 0000000..146b979 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/profile_credentials.go @@ -0,0 +1,159 @@ +package provider + +import ( + "bufio" + "errors" + "os" + "runtime" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + + ini "gopkg.in/ini.v1" +) + +type ProfileProvider struct { + Profile string +} + +var ProviderProfile = NewProfileProvider() + +// NewProfileProvider receive zero or more parameters, +// when length of name is 0, the value of field Profile will be "default", +// and when there are multiple inputs, the function will take the +// first one and discard the other values. +func NewProfileProvider(name ...string) Provider { + p := new(ProfileProvider) + if len(name) == 0 { + p.Profile = "default" + } else { + p.Profile = name[0] + } + return p +} + +// Resolve implements the Provider interface +// when credential type is rsa_key_pair, the content of private_key file +// must be able to be parsed directly into the required string +// that NewRsaKeyPairCredential function needed +func (p *ProfileProvider) Resolve() (auth.Credential, error) { + path, ok := os.LookupEnv(ENVCredentialFile) + if !ok { + var err error + path, err = checkDefaultPath() + if err != nil { + return nil, err + } + if path == "" { + return nil, nil + } + } else if path == "" { + return nil, errors.New("Environment variable '" + ENVCredentialFile + "' cannot be empty") + } + + ini, err := ini.Load(path) + if err != nil { + return nil, errors.New("ERROR: Can not open file" + err.Error()) + } + + section, err := ini.GetSection(p.Profile) + if err != nil { + return nil, errors.New("ERROR: Can not load section" + err.Error()) + } + + value, err := section.GetKey("type") + if err != nil { + return nil, errors.New("ERROR: Can not find credential type" + err.Error()) + } + + switch value.String() { + case "access_key": + value1, err1 := section.GetKey("access_key_id") + value2, err2 := section.GetKey("access_key_secret") + if err1 != nil || err2 != nil { + return nil, errors.New("ERROR: Failed to get value") + } + if value1.String() == "" || value2.String() == "" { + return nil, errors.New("ERROR: Value can't be empty") + } + return credentials.NewAccessKeyCredential(value1.String(), value2.String()), nil + case "ecs_ram_role": + value1, err1 := section.GetKey("role_name") + if err1 != nil { + return nil, errors.New("ERROR: Failed to get value") + } + if value1.String() == "" { + return nil, errors.New("ERROR: Value can't be empty") + } + return credentials.NewEcsRamRoleCredential(value1.String()), nil + case "ram_role_arn": + value1, err1 := section.GetKey("access_key_id") + value2, err2 := section.GetKey("access_key_secret") + value3, err3 := section.GetKey("role_arn") + value4, err4 := section.GetKey("role_session_name") + if err1 != nil || err2 != nil || err3 != nil || err4 != nil { + return nil, errors.New("ERROR: Failed to get value") + } + if value1.String() == "" || value2.String() == "" || value3.String() == "" || value4.String() == "" { + return nil, errors.New("ERROR: Value can't be empty") + } + return credentials.NewRamRoleArnCredential(value1.String(), value2.String(), value3.String(), value4.String(), 3600), nil + case "rsa_key_pair": + value1, err1 := section.GetKey("public_key_id") + value2, err2 := section.GetKey("private_key_file") + if err1 != nil || err2 != nil { + return nil, errors.New("ERROR: Failed to get value") + } + if value1.String() == "" || value2.String() == "" { + return nil, errors.New("ERROR: Value can't be empty") + } + file, err := os.Open(value2.String()) + if err != nil { + return nil, errors.New("ERROR: Can not get private_key") + } + defer file.Close() + var privateKey string + scan := bufio.NewScanner(file) + var data string + for scan.Scan() { + if strings.HasPrefix(scan.Text(), "----") { + continue + } + data += scan.Text() + "\n" + } + return credentials.NewRsaKeyPairCredential(privateKey, value1.String(), 3600), nil + default: + return nil, errors.New("ERROR: Failed to get credential") + } +} + +// GetHomePath return home directory according to the system. +// if the environmental virables does not exist, will return empty +func GetHomePath() string { + if runtime.GOOS == "windows" { + path, ok := os.LookupEnv("USERPROFILE") + if !ok { + return "" + } + return path + } + path, ok := os.LookupEnv("HOME") + if !ok { + return "" + } + return path +} + +func checkDefaultPath() (path string, err error) { + path = GetHomePath() + if path == "" { + return "", errors.New("The default credential file path is invalid") + } + path = strings.Replace("~/.alibabacloud/credentials", "~", path, 1) + _, err = os.Stat(path) + if err != nil { + return "", nil + } + return path, nil +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider.go new file mode 100644 index 0000000..ae4e168 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider.go @@ -0,0 +1,19 @@ +package provider + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" +) + +//Environmental virables that may be used by the provider +const ( + ENVAccessKeyID = "ALIBABA_CLOUD_ACCESS_KEY_ID" + ENVAccessKeySecret = "ALIBABA_CLOUD_ACCESS_KEY_SECRET" + ENVCredentialFile = "ALIBABA_CLOUD_CREDENTIALS_FILE" + ENVEcsMetadata = "ALIBABA_CLOUD_ECS_METADATA" + PATHCredentialFile = "~/.alibabacloud/credentials" +) + +// When you want to customize the provider, you only need to implement the method of the interface. +type Provider interface { + Resolve() (auth.Credential, error) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider_chain.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider_chain.go new file mode 100644 index 0000000..3f9315d --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider_chain.go @@ -0,0 +1,34 @@ +package provider + +import ( + "errors" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" +) + +type ProviderChain struct { + Providers []Provider +} + +var defaultproviders = []Provider{ProviderEnv, ProviderProfile, ProviderInstance} +var DefaultChain = NewProviderChain(defaultproviders) + +func NewProviderChain(providers []Provider) Provider { + return &ProviderChain{ + Providers: providers, + } +} + +func (p *ProviderChain) Resolve() (auth.Credential, error) { + for _, provider := range p.Providers { + creds, err := provider.Resolve() + if err != nil { + return nil, err + } else if err == nil && creds == nil { + continue + } + return creds, err + } + return nil, errors.New("No credential found") + +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go new file mode 100644 index 0000000..00d688e --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go @@ -0,0 +1,15 @@ +package credentials + +type RsaKeyPairCredential struct { + PrivateKey string + PublicKeyId string + SessionExpiration int +} + +func NewRsaKeyPairCredential(privateKey, publicKeyId string, sessionExpiration int) *RsaKeyPairCredential { + return &RsaKeyPairCredential{ + PrivateKey: privateKey, + PublicKeyId: publicKeyId, + SessionExpiration: sessionExpiration, + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_credential.go new file mode 100644 index 0000000..554431f --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_credential.go @@ -0,0 +1,15 @@ +package credentials + +type StsTokenCredential struct { + AccessKeyId string + AccessKeySecret string + AccessKeyStsToken string +} + +func NewStsTokenCredential(accessKeyId, accessKeySecret, accessKeyStsToken string) *StsTokenCredential { + return &StsTokenCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + AccessKeyStsToken: accessKeyStsToken, + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_role_arn_credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_role_arn_credential.go new file mode 100644 index 0000000..27602fd --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_role_arn_credential.go @@ -0,0 +1,61 @@ +package credentials + +// Deprecated: Use RamRoleArnCredential in this package instead. +type StsRoleArnCredential struct { + AccessKeyId string + AccessKeySecret string + RoleArn string + RoleSessionName string + RoleSessionExpiration int +} + +type RamRoleArnCredential struct { + AccessKeyId string + AccessKeySecret string + RoleArn string + RoleSessionName string + RoleSessionExpiration int + Policy string +} + +// Deprecated: Use RamRoleArnCredential in this package instead. +func NewStsRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName string, roleSessionExpiration int) *StsRoleArnCredential { + return &StsRoleArnCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + RoleArn: roleArn, + RoleSessionName: roleSessionName, + RoleSessionExpiration: roleSessionExpiration, + } +} + +func (oldCred *StsRoleArnCredential) ToRamRoleArnCredential() *RamRoleArnCredential { + return &RamRoleArnCredential{ + AccessKeyId: oldCred.AccessKeyId, + AccessKeySecret: oldCred.AccessKeySecret, + RoleArn: oldCred.RoleArn, + RoleSessionName: oldCred.RoleSessionName, + RoleSessionExpiration: oldCred.RoleSessionExpiration, + } +} + +func NewRamRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName string, roleSessionExpiration int) *RamRoleArnCredential { + return &RamRoleArnCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + RoleArn: roleArn, + RoleSessionName: roleSessionName, + RoleSessionExpiration: roleSessionExpiration, + } +} + +func NewRamRoleArnWithPolicyCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string, roleSessionExpiration int) *RamRoleArnCredential { + return &RamRoleArnCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + RoleArn: roleArn, + RoleSessionName: roleSessionName, + RoleSessionExpiration: roleSessionExpiration, + Policy: policy, + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/roa_signature_composer.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/roa_signature_composer.go new file mode 100644 index 0000000..2a96261 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/roa_signature_composer.go @@ -0,0 +1,138 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package auth + +import ( + "bytes" + "sort" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +var debug utils.Debug + +var hookGetDate = func(fn func() string) string { + return fn() +} + +func init() { + debug = utils.Init("sdk") +} + +func signRoaRequest(request requests.AcsRequest, signer Signer, regionId string) (err error) { + completeROASignParams(request, signer, regionId) + stringToSign := buildRoaStringToSign(request) + request.SetStringToSign(stringToSign) + accessKeyId, err := signer.GetAccessKeyId() + if err != nil { + return err + } + + signature := signer.Sign(stringToSign, "") + request.GetHeaders()["Authorization"] = "acs " + accessKeyId + ":" + signature + + return +} + +func completeROASignParams(request requests.AcsRequest, signer Signer, regionId string) { + headerParams := request.GetHeaders() + + // complete query params + queryParams := request.GetQueryParams() + //if _, ok := queryParams["RegionId"]; !ok { + // queryParams["RegionId"] = regionId + //} + if extraParam := signer.GetExtraParam(); extraParam != nil { + for key, value := range extraParam { + if key == "SecurityToken" { + headerParams["x-acs-security-token"] = value + continue + } + if key == "BearerToken" { + headerParams["x-acs-bearer-token"] = value + continue + } + queryParams[key] = value + } + } + + // complete header params + headerParams["Date"] = hookGetDate(utils.GetTimeInFormatRFC2616) + headerParams["x-acs-signature-method"] = signer.GetName() + headerParams["x-acs-signature-version"] = signer.GetVersion() + if request.GetFormParams() != nil && len(request.GetFormParams()) > 0 { + formString := utils.GetUrlFormedMap(request.GetFormParams()) + request.SetContent([]byte(formString)) + if headerParams["Content-Type"] == "" { + headerParams["Content-Type"] = requests.Form + } + } + contentMD5 := utils.GetMD5Base64(request.GetContent()) + headerParams["Content-MD5"] = contentMD5 + if _, contains := headerParams["Content-Type"]; !contains { + headerParams["Content-Type"] = requests.Raw + } + switch format := request.GetAcceptFormat(); format { + case "JSON": + headerParams["Accept"] = requests.Json + case "XML": + headerParams["Accept"] = requests.Xml + default: + headerParams["Accept"] = requests.Raw + } +} + +func buildRoaStringToSign(request requests.AcsRequest) (stringToSign string) { + + headers := request.GetHeaders() + + stringToSignBuilder := bytes.Buffer{} + stringToSignBuilder.WriteString(request.GetMethod()) + stringToSignBuilder.WriteString(requests.HeaderSeparator) + + // append header keys for sign + appendIfContain(headers, &stringToSignBuilder, "Accept", requests.HeaderSeparator) + appendIfContain(headers, &stringToSignBuilder, "Content-MD5", requests.HeaderSeparator) + appendIfContain(headers, &stringToSignBuilder, "Content-Type", requests.HeaderSeparator) + appendIfContain(headers, &stringToSignBuilder, "Date", requests.HeaderSeparator) + + // sort and append headers witch starts with 'x-acs-' + var acsHeaders []string + for key := range headers { + if strings.HasPrefix(key, "x-acs-") { + acsHeaders = append(acsHeaders, key) + } + } + sort.Strings(acsHeaders) + for _, key := range acsHeaders { + stringToSignBuilder.WriteString(key + ":" + headers[key]) + stringToSignBuilder.WriteString(requests.HeaderSeparator) + } + + // append query params + stringToSignBuilder.WriteString(request.BuildQueries()) + stringToSign = stringToSignBuilder.String() + debug("stringToSign: %s", stringToSign) + return +} + +func appendIfContain(sourceMap map[string]string, target *bytes.Buffer, key, separator string) { + if value, contain := sourceMap[key]; contain && len(value) > 0 { + target.WriteString(sourceMap[key]) + target.WriteString(separator) + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/rpc_signature_composer.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/rpc_signature_composer.go new file mode 100644 index 0000000..33967b9 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/rpc_signature_composer.go @@ -0,0 +1,94 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package auth + +import ( + "net/url" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +var hookGetNonce = func(fn func() string) string { + return fn() +} + +func signRpcRequest(request requests.AcsRequest, signer Signer, regionId string) (err error) { + err = completeRpcSignParams(request, signer, regionId) + if err != nil { + return + } + // remove while retry + if _, containsSign := request.GetQueryParams()["Signature"]; containsSign { + delete(request.GetQueryParams(), "Signature") + } + stringToSign := buildRpcStringToSign(request) + request.SetStringToSign(stringToSign) + signature := signer.Sign(stringToSign, "&") + request.GetQueryParams()["Signature"] = signature + + return +} + +func completeRpcSignParams(request requests.AcsRequest, signer Signer, regionId string) (err error) { + queryParams := request.GetQueryParams() + queryParams["Version"] = request.GetVersion() + queryParams["Action"] = request.GetActionName() + queryParams["Format"] = request.GetAcceptFormat() + queryParams["Timestamp"] = hookGetDate(utils.GetTimeInFormatISO8601) + queryParams["SignatureMethod"] = signer.GetName() + queryParams["SignatureType"] = signer.GetType() + queryParams["SignatureVersion"] = signer.GetVersion() + queryParams["SignatureNonce"] = hookGetNonce(utils.GetUUID) + queryParams["AccessKeyId"], err = signer.GetAccessKeyId() + + if err != nil { + return + } + + if _, contains := queryParams["RegionId"]; !contains { + queryParams["RegionId"] = regionId + } + if extraParam := signer.GetExtraParam(); extraParam != nil { + for key, value := range extraParam { + queryParams[key] = value + } + } + + request.GetHeaders()["Content-Type"] = requests.Form + formString := utils.GetUrlFormedMap(request.GetFormParams()) + request.SetContent([]byte(formString)) + + return +} + +func buildRpcStringToSign(request requests.AcsRequest) (stringToSign string) { + signParams := make(map[string]string) + for key, value := range request.GetQueryParams() { + signParams[key] = value + } + for key, value := range request.GetFormParams() { + signParams[key] = value + } + + stringToSign = utils.GetUrlFormedMap(signParams) + stringToSign = strings.Replace(stringToSign, "+", "%20", -1) + stringToSign = strings.Replace(stringToSign, "*", "%2A", -1) + stringToSign = strings.Replace(stringToSign, "%7E", "~", -1) + stringToSign = url.QueryEscape(stringToSign) + stringToSign = request.GetMethod() + "&%2F&" + stringToSign + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signer.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signer.go new file mode 100644 index 0000000..cbbc3ce --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signer.go @@ -0,0 +1,98 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package auth + +import ( + "fmt" + "reflect" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +type Signer interface { + GetName() string + GetType() string + GetVersion() string + GetAccessKeyId() (string, error) + GetExtraParam() map[string]string + Sign(stringToSign, secretSuffix string) string +} + +func NewSignerWithCredential(credential Credential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer Signer, err error) { + switch instance := credential.(type) { + case *credentials.AccessKeyCredential: + { + signer = signers.NewAccessKeySigner(instance) + } + case *credentials.StsTokenCredential: + { + signer = signers.NewStsTokenSigner(instance) + } + case *credentials.BearerTokenCredential: + { + signer = signers.NewBearerTokenSigner(instance) + } + case *credentials.RamRoleArnCredential: + { + signer, err = signers.NewRamRoleArnSigner(instance, commonApi) + } + case *credentials.RsaKeyPairCredential: + { + signer, err = signers.NewSignerKeyPair(instance, commonApi) + } + case *credentials.EcsRamRoleCredential: + { + signer = signers.NewEcsRamRoleSigner(instance, commonApi) + } + case *credentials.BaseCredential: // deprecated user interface + { + signer = signers.NewAccessKeySigner(instance.ToAccessKeyCredential()) + } + case *credentials.StsRoleArnCredential: // deprecated user interface + { + signer, err = signers.NewRamRoleArnSigner(instance.ToRamRoleArnCredential(), commonApi) + } + case *credentials.StsRoleNameOnEcsCredential: // deprecated user interface + { + signer = signers.NewEcsRamRoleSigner(instance.ToEcsRamRoleCredential(), commonApi) + } + default: + message := fmt.Sprintf(errors.UnsupportedCredentialErrorMessage, reflect.TypeOf(credential)) + err = errors.NewClientError(errors.UnsupportedCredentialErrorCode, message, nil) + } + return +} + +func Sign(request requests.AcsRequest, signer Signer, regionId string) (err error) { + switch request.GetStyle() { + case requests.ROA: + { + err = signRoaRequest(request, signer, regionId) + } + case requests.RPC: + { + err = signRpcRequest(request, signer, regionId) + } + default: + message := fmt.Sprintf(errors.UnknownRequestTypeErrorMessage, reflect.TypeOf(request)) + err = errors.NewClientError(errors.UnknownRequestTypeErrorCode, message, nil) + } + + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go new file mode 100644 index 0000000..887f502 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go @@ -0,0 +1,57 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "crypto" + "crypto/hmac" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "crypto/x509" + "encoding/base64" +) + +func ShaHmac1(source, secret string) string { + key := []byte(secret) + hmac := hmac.New(sha1.New, key) + hmac.Write([]byte(source)) + signedBytes := hmac.Sum(nil) + signedString := base64.StdEncoding.EncodeToString(signedBytes) + return signedString +} + +func Sha256WithRsa(source, secret string) string { + // block, _ := pem.Decode([]byte(secret)) + decodeString, err := base64.StdEncoding.DecodeString(secret) + if err != nil { + panic(err) + } + private, err := x509.ParsePKCS8PrivateKey(decodeString) + if err != nil { + panic(err) + } + + h := crypto.Hash.New(crypto.SHA256) + h.Write([]byte(source)) + hashed := h.Sum(nil) + signature, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey), + crypto.SHA256, hashed) + if err != nil { + panic(err) + } + + return base64.StdEncoding.EncodeToString(signature) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/credential_updater.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/credential_updater.go new file mode 100644 index 0000000..ba291a4 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/credential_updater.go @@ -0,0 +1,54 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +const defaultInAdvanceScale = 0.95 + +type credentialUpdater struct { + credentialExpiration int + lastUpdateTimestamp int64 + inAdvanceScale float64 + buildRequestMethod func() (*requests.CommonRequest, error) + responseCallBack func(response *responses.CommonResponse) error + refreshApi func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) +} + +func (updater *credentialUpdater) needUpdateCredential() (result bool) { + if updater.inAdvanceScale == 0 { + updater.inAdvanceScale = defaultInAdvanceScale + } + return time.Now().Unix()-updater.lastUpdateTimestamp >= int64(float64(updater.credentialExpiration)*updater.inAdvanceScale) +} + +func (updater *credentialUpdater) updateCredential() (err error) { + request, err := updater.buildRequestMethod() + if err != nil { + return + } + response, err := updater.refreshApi(request) + if err != nil { + return + } + updater.lastUpdateTimestamp = time.Now().Unix() + err = updater.responseCallBack(response) + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/session_credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/session_credential.go new file mode 100644 index 0000000..99c624c --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/session_credential.go @@ -0,0 +1,7 @@ +package signers + +type SessionCredential struct { + AccessKeyId string + AccessKeySecret string + StsToken string +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go new file mode 100644 index 0000000..bc4f35b --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go @@ -0,0 +1,54 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" +) + +type AccessKeySigner struct { + credential *credentials.AccessKeyCredential +} + +func (signer *AccessKeySigner) GetExtraParam() map[string]string { + return nil +} + +func NewAccessKeySigner(credential *credentials.AccessKeyCredential) *AccessKeySigner { + return &AccessKeySigner{ + credential: credential, + } +} + +func (*AccessKeySigner) GetName() string { + return "HMAC-SHA1" +} + +func (*AccessKeySigner) GetType() string { + return "" +} + +func (*AccessKeySigner) GetVersion() string { + return "1.0" +} + +func (signer *AccessKeySigner) GetAccessKeyId() (accessKeyId string, err error) { + return signer.credential.AccessKeyId, nil +} + +func (signer *AccessKeySigner) Sign(stringToSign, secretSuffix string) string { + secret := signer.credential.AccessKeySecret + secretSuffix + return ShaHmac1(stringToSign, secret) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_bearer_token.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_bearer_token.go new file mode 100644 index 0000000..75b7843 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_bearer_token.go @@ -0,0 +1,35 @@ +package signers + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" +) + +type BearerTokenSigner struct { + credential *credentials.BearerTokenCredential +} + +func NewBearerTokenSigner(credential *credentials.BearerTokenCredential) *BearerTokenSigner { + return &BearerTokenSigner{ + credential: credential, + } +} + +func (signer *BearerTokenSigner) GetExtraParam() map[string]string { + return map[string]string{"BearerToken": signer.credential.BearerToken} +} + +func (*BearerTokenSigner) GetName() string { + return "" +} +func (*BearerTokenSigner) GetType() string { + return "BEARERTOKEN" +} +func (*BearerTokenSigner) GetVersion() string { + return "1.0" +} +func (signer *BearerTokenSigner) GetAccessKeyId() (accessKeyId string, err error) { + return "", nil +} +func (signer *BearerTokenSigner) Sign(stringToSign, secretSuffix string) string { + return "" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go new file mode 100644 index 0000000..7378842 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go @@ -0,0 +1,167 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + jmespath "github.com/jmespath/go-jmespath" +) + +var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/" + +type EcsRamRoleSigner struct { + *credentialUpdater + sessionCredential *SessionCredential + credential *credentials.EcsRamRoleCredential + commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error) +} + +func NewEcsRamRoleSigner(credential *credentials.EcsRamRoleCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *EcsRamRoleSigner) { + signer = &EcsRamRoleSigner{ + credential: credential, + commonApi: commonApi, + } + + signer.credentialUpdater = &credentialUpdater{ + credentialExpiration: defaultDurationSeconds / 60, + buildRequestMethod: signer.buildCommonRequest, + responseCallBack: signer.refreshCredential, + refreshApi: signer.refreshApi, + } + + return signer +} + +func (*EcsRamRoleSigner) GetName() string { + return "HMAC-SHA1" +} + +func (*EcsRamRoleSigner) GetType() string { + return "" +} + +func (*EcsRamRoleSigner) GetVersion() string { + return "1.0" +} + +func (signer *EcsRamRoleSigner) GetAccessKeyId() (accessKeyId string, err error) { + if signer.sessionCredential == nil || signer.needUpdateCredential() { + err = signer.updateCredential() + if err != nil { + return + } + } + if signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0 { + return "", nil + } + return signer.sessionCredential.AccessKeyId, nil +} + +func (signer *EcsRamRoleSigner) GetExtraParam() map[string]string { + if signer.sessionCredential == nil { + return make(map[string]string) + } + if len(signer.sessionCredential.StsToken) <= 0 { + return make(map[string]string) + } + return map[string]string{"SecurityToken": signer.sessionCredential.StsToken} +} + +func (signer *EcsRamRoleSigner) Sign(stringToSign, secretSuffix string) string { + secret := signer.sessionCredential.AccessKeySecret + secretSuffix + return ShaHmac1(stringToSign, secret) +} + +func (signer *EcsRamRoleSigner) buildCommonRequest() (request *requests.CommonRequest, err error) { + return +} + +func (signer *EcsRamRoleSigner) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) { + requestUrl := securityCredURL + signer.credential.RoleName + httpRequest, err := http.NewRequest(requests.GET, requestUrl, strings.NewReader("")) + if err != nil { + err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error()) + return + } + httpClient := &http.Client{} + httpResponse, err := httpClient.Do(httpRequest) + if err != nil { + err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error()) + return + } + + response = responses.NewCommonResponse() + err = responses.Unmarshal(response, httpResponse, "") + return +} + +func (signer *EcsRamRoleSigner) refreshCredential(response *responses.CommonResponse) (err error) { + if response.GetHttpStatus() != http.StatusOK { + return fmt.Errorf("refresh Ecs sts token err, httpStatus: %d, message = %s", response.GetHttpStatus(), response.GetHttpContentString()) + } + var data interface{} + err = json.Unmarshal(response.GetHttpContentBytes(), &data) + if err != nil { + return fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error()) + } + code, err := jmespath.Search("Code", data) + if err != nil { + return fmt.Errorf("refresh Ecs sts token err, fail to get Code: %s", err.Error()) + } + if code.(string) != "Success" { + return fmt.Errorf("refresh Ecs sts token err, Code is not Success") + } + accessKeyId, err := jmespath.Search("AccessKeyId", data) + if err != nil { + return fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeyId: %s", err.Error()) + } + accessKeySecret, err := jmespath.Search("AccessKeySecret", data) + if err != nil { + return fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeySecret: %s", err.Error()) + } + securityToken, err := jmespath.Search("SecurityToken", data) + if err != nil { + return fmt.Errorf("refresh Ecs sts token err, fail to get SecurityToken: %s", err.Error()) + } + expiration, err := jmespath.Search("Expiration", data) + if err != nil { + return fmt.Errorf("refresh Ecs sts token err, fail to get Expiration: %s", err.Error()) + } + if accessKeyId == nil || accessKeySecret == nil || securityToken == nil || expiration == nil { + return + } + + expirationTime, err := time.Parse("2006-01-02T15:04:05Z", expiration.(string)) + signer.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix()) + signer.sessionCredential = &SessionCredential{ + AccessKeyId: accessKeyId.(string), + AccessKeySecret: accessKeySecret.(string), + StsToken: securityToken.(string), + } + + return +} + +func (signer *EcsRamRoleSigner) GetSessionCredential() *SessionCredential { + return signer.sessionCredential +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go new file mode 100644 index 0000000..19273d5 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go @@ -0,0 +1,148 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + jmespath "github.com/jmespath/go-jmespath" +) + +type SignerKeyPair struct { + *credentialUpdater + sessionCredential *SessionCredential + credential *credentials.RsaKeyPairCredential + commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error) +} + +func NewSignerKeyPair(credential *credentials.RsaKeyPairCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerKeyPair, err error) { + signer = &SignerKeyPair{ + credential: credential, + commonApi: commonApi, + } + + signer.credentialUpdater = &credentialUpdater{ + credentialExpiration: credential.SessionExpiration, + buildRequestMethod: signer.buildCommonRequest, + responseCallBack: signer.refreshCredential, + refreshApi: signer.refreshApi, + } + + if credential.SessionExpiration > 0 { + if credential.SessionExpiration >= 900 && credential.SessionExpiration <= 3600 { + signer.credentialExpiration = credential.SessionExpiration + } else { + err = errors.NewClientError(errors.InvalidParamErrorCode, "Key Pair session duration should be in the range of 15min - 1Hr", nil) + } + } else { + signer.credentialExpiration = defaultDurationSeconds + } + return +} + +func (*SignerKeyPair) GetName() string { + return "HMAC-SHA1" +} + +func (*SignerKeyPair) GetType() string { + return "" +} + +func (*SignerKeyPair) GetVersion() string { + return "1.0" +} + +func (signer *SignerKeyPair) ensureCredential() error { + if signer.sessionCredential == nil || signer.needUpdateCredential() { + return signer.updateCredential() + } + return nil +} + +func (signer *SignerKeyPair) GetAccessKeyId() (accessKeyId string, err error) { + err = signer.ensureCredential() + if err != nil { + return + } + if signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0 { + accessKeyId = "" + return + } + + accessKeyId = signer.sessionCredential.AccessKeyId + return +} + +func (signer *SignerKeyPair) GetExtraParam() map[string]string { + return make(map[string]string) +} + +func (signer *SignerKeyPair) Sign(stringToSign, secretSuffix string) string { + secret := signer.sessionCredential.AccessKeySecret + secretSuffix + return ShaHmac1(stringToSign, secret) +} + +func (signer *SignerKeyPair) buildCommonRequest() (request *requests.CommonRequest, err error) { + request = requests.NewCommonRequest() + request.Product = "Sts" + request.Version = "2015-04-01" + request.ApiName = "GenerateSessionAccessKey" + request.Scheme = requests.HTTPS + request.SetDomain("sts.ap-northeast-1.aliyuncs.com") + request.QueryParams["PublicKeyId"] = signer.credential.PublicKeyId + request.QueryParams["DurationSeconds"] = strconv.Itoa(signer.credentialExpiration) + return +} + +func (signer *SignerKeyPair) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) { + signerV2 := NewSignerV2(signer.credential) + return signer.commonApi(request, signerV2) +} + +func (signer *SignerKeyPair) refreshCredential(response *responses.CommonResponse) (err error) { + if response.GetHttpStatus() != http.StatusOK { + message := "refresh session AccessKey failed" + err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), message) + return + } + var data interface{} + err = json.Unmarshal(response.GetHttpContentBytes(), &data) + if err != nil { + return fmt.Errorf("refresh KeyPair err, json.Unmarshal fail: %s", err.Error()) + } + accessKeyId, err := jmespath.Search("SessionAccessKey.SessionAccessKeyId", data) + if err != nil { + return fmt.Errorf("refresh KeyPair err, fail to get SessionAccessKeyId: %s", err.Error()) + } + accessKeySecret, err := jmespath.Search("SessionAccessKey.SessionAccessKeySecret", data) + if err != nil { + return fmt.Errorf("refresh KeyPair err, fail to get SessionAccessKeySecret: %s", err.Error()) + } + if accessKeyId == nil || accessKeySecret == nil { + return + } + signer.sessionCredential = &SessionCredential{ + AccessKeyId: accessKeyId.(string), + AccessKeySecret: accessKeySecret.(string), + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go new file mode 100644 index 0000000..c945c8a --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go @@ -0,0 +1,175 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + jmespath "github.com/jmespath/go-jmespath" +) + +const ( + defaultDurationSeconds = 3600 +) + +type RamRoleArnSigner struct { + *credentialUpdater + roleSessionName string + sessionCredential *SessionCredential + credential *credentials.RamRoleArnCredential + commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error) +} + +func NewRamRoleArnSigner(credential *credentials.RamRoleArnCredential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer *RamRoleArnSigner, err error) { + signer = &RamRoleArnSigner{ + credential: credential, + commonApi: commonApi, + } + + signer.credentialUpdater = &credentialUpdater{ + credentialExpiration: credential.RoleSessionExpiration, + buildRequestMethod: signer.buildCommonRequest, + responseCallBack: signer.refreshCredential, + refreshApi: signer.refreshApi, + } + + if len(credential.RoleSessionName) > 0 { + signer.roleSessionName = credential.RoleSessionName + } else { + signer.roleSessionName = "aliyun-go-sdk-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10) + } + if credential.RoleSessionExpiration > 0 { + if credential.RoleSessionExpiration >= 900 && credential.RoleSessionExpiration <= 3600 { + signer.credentialExpiration = credential.RoleSessionExpiration + } else { + err = errors.NewClientError(errors.InvalidParamErrorCode, "Assume Role session duration should be in the range of 15min - 1Hr", nil) + } + } else { + signer.credentialExpiration = defaultDurationSeconds + } + return +} + +func (*RamRoleArnSigner) GetName() string { + return "HMAC-SHA1" +} + +func (*RamRoleArnSigner) GetType() string { + return "" +} + +func (*RamRoleArnSigner) GetVersion() string { + return "1.0" +} + +func (signer *RamRoleArnSigner) GetAccessKeyId() (accessKeyId string, err error) { + if signer.sessionCredential == nil || signer.needUpdateCredential() { + err = signer.updateCredential() + if err != nil { + return + } + } + + if signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0 { + return "", err + } + + return signer.sessionCredential.AccessKeyId, nil +} + +func (signer *RamRoleArnSigner) GetExtraParam() map[string]string { + if signer.sessionCredential == nil || signer.needUpdateCredential() { + signer.updateCredential() + } + if signer.sessionCredential == nil || len(signer.sessionCredential.StsToken) <= 0 { + return make(map[string]string) + } + return map[string]string{"SecurityToken": signer.sessionCredential.StsToken} +} + +func (signer *RamRoleArnSigner) Sign(stringToSign, secretSuffix string) string { + secret := signer.sessionCredential.AccessKeySecret + secretSuffix + return ShaHmac1(stringToSign, secret) +} + +func (signer *RamRoleArnSigner) buildCommonRequest() (request *requests.CommonRequest, err error) { + request = requests.NewCommonRequest() + request.Product = "Sts" + request.Version = "2015-04-01" + request.ApiName = "AssumeRole" + request.Scheme = requests.HTTPS + request.QueryParams["RoleArn"] = signer.credential.RoleArn + if signer.credential.Policy != "" { + request.QueryParams["Policy"] = signer.credential.Policy + } + request.QueryParams["RoleSessionName"] = signer.credential.RoleSessionName + request.QueryParams["DurationSeconds"] = strconv.Itoa(signer.credentialExpiration) + return +} + +func (signer *RamRoleArnSigner) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) { + credential := &credentials.AccessKeyCredential{ + AccessKeyId: signer.credential.AccessKeyId, + AccessKeySecret: signer.credential.AccessKeySecret, + } + signerV1 := NewAccessKeySigner(credential) + return signer.commonApi(request, signerV1) +} + +func (signer *RamRoleArnSigner) refreshCredential(response *responses.CommonResponse) (err error) { + if response.GetHttpStatus() != http.StatusOK { + message := "refresh session token failed" + err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), message) + return + } + var data interface{} + err = json.Unmarshal(response.GetHttpContentBytes(), &data) + if err != nil { + return fmt.Errorf("refresh RoleArn sts token err, json.Unmarshal fail: %s", err.Error()) + } + accessKeyId, err := jmespath.Search("Credentials.AccessKeyId", data) + if err != nil { + return fmt.Errorf("refresh RoleArn sts token err, fail to get AccessKeyId: %s", err.Error()) + } + accessKeySecret, err := jmespath.Search("Credentials.AccessKeySecret", data) + if err != nil { + return fmt.Errorf("refresh RoleArn sts token err, fail to get AccessKeySecret: %s", err.Error()) + } + securityToken, err := jmespath.Search("Credentials.SecurityToken", data) + if err != nil { + return fmt.Errorf("refresh RoleArn sts token err, fail to get SecurityToken: %s", err.Error()) + } + if accessKeyId == nil || accessKeySecret == nil || securityToken == nil { + return + } + signer.sessionCredential = &SessionCredential{ + AccessKeyId: accessKeyId.(string), + AccessKeySecret: accessKeySecret.(string), + StsToken: securityToken.(string), + } + return +} + +func (signer *RamRoleArnSigner) GetSessionCredential() *SessionCredential { + return signer.sessionCredential +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go new file mode 100644 index 0000000..d0ce36c --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go @@ -0,0 +1,54 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" +) + +type StsTokenSigner struct { + credential *credentials.StsTokenCredential +} + +func NewStsTokenSigner(credential *credentials.StsTokenCredential) *StsTokenSigner { + return &StsTokenSigner{ + credential: credential, + } +} + +func (*StsTokenSigner) GetName() string { + return "HMAC-SHA1" +} + +func (*StsTokenSigner) GetType() string { + return "" +} + +func (*StsTokenSigner) GetVersion() string { + return "1.0" +} + +func (signer *StsTokenSigner) GetAccessKeyId() (accessKeyId string, err error) { + return signer.credential.AccessKeyId, nil +} + +func (signer *StsTokenSigner) GetExtraParam() map[string]string { + return map[string]string{"SecurityToken": signer.credential.AccessKeyStsToken} +} + +func (signer *StsTokenSigner) Sign(stringToSign, secretSuffix string) string { + secret := signer.credential.AccessKeySecret + secretSuffix + return ShaHmac1(stringToSign, secret) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go new file mode 100644 index 0000000..9734852 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go @@ -0,0 +1,54 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package signers + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" +) + +type SignerV2 struct { + credential *credentials.RsaKeyPairCredential +} + +func (signer *SignerV2) GetExtraParam() map[string]string { + return nil +} + +func NewSignerV2(credential *credentials.RsaKeyPairCredential) *SignerV2 { + return &SignerV2{ + credential: credential, + } +} + +func (*SignerV2) GetName() string { + return "SHA256withRSA" +} + +func (*SignerV2) GetType() string { + return "PRIVATEKEY" +} + +func (*SignerV2) GetVersion() string { + return "1.0" +} + +func (signer *SignerV2) GetAccessKeyId() (accessKeyId string, err error) { + return signer.credential.PublicKeyId, err +} + +func (signer *SignerV2) Sign(stringToSign, secretSuffix string) string { + secret := signer.credential.PrivateKey + return Sha256WithRsa(stringToSign, secret) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/client.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/client.go new file mode 100644 index 0000000..3a5cf12 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/client.go @@ -0,0 +1,794 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sdk + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "net/http" + "net/url" + "os" + "runtime" + "strconv" + "strings" + "sync" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +var debug utils.Debug + +func init() { + debug = utils.Init("sdk") +} + +// Version this value will be replaced while build: -ldflags="-X sdk.version=x.x.x" +var Version = "0.0.1" +var defaultConnectTimeout = 5 * time.Second +var defaultReadTimeout = 10 * time.Second + +var DefaultUserAgent = fmt.Sprintf("AlibabaCloud (%s; %s) Golang/%s Core/%s", runtime.GOOS, runtime.GOARCH, strings.Trim(runtime.Version(), "go"), Version) + +var hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) { + return fn +} + +// Client the type Client +type Client struct { + isInsecure bool + regionId string + config *Config + httpProxy string + httpsProxy string + noProxy string + logger *Logger + userAgent map[string]string + signer auth.Signer + httpClient *http.Client + asyncTaskQueue chan func() + readTimeout time.Duration + connectTimeout time.Duration + EndpointMap map[string]string + EndpointType string + Network string + Domain string + + debug bool + isRunning bool + // void "panic(write to close channel)" cause of addAsync() after Shutdown() + asyncChanLock *sync.RWMutex +} + +func (client *Client) Init() (err error) { + panic("not support yet") +} + +func (client *Client) SetEndpointRules(endpointMap map[string]string, endpointType string, netWork string) { + client.EndpointMap = endpointMap + client.Network = netWork + client.EndpointType = endpointType +} + +func (client *Client) SetHTTPSInsecure(isInsecure bool) { + client.isInsecure = isInsecure +} + +func (client *Client) GetHTTPSInsecure() bool { + return client.isInsecure +} + +func (client *Client) SetHttpsProxy(httpsProxy string) { + client.httpsProxy = httpsProxy +} + +func (client *Client) GetHttpsProxy() string { + return client.httpsProxy +} + +func (client *Client) SetHttpProxy(httpProxy string) { + client.httpProxy = httpProxy +} + +func (client *Client) GetHttpProxy() string { + return client.httpProxy +} + +func (client *Client) SetNoProxy(noProxy string) { + client.noProxy = noProxy +} + +func (client *Client) GetNoProxy() string { + return client.noProxy +} + +// InitWithProviderChain will get credential from the providerChain, +// the RsaKeyPairCredential Only applicable to regionID `ap-northeast-1`, +// if your providerChain may return a credential type with RsaKeyPairCredential, +// please ensure your regionID is `ap-northeast-1`. +func (client *Client) InitWithProviderChain(regionId string, provider provider.Provider) (err error) { + config := client.InitClientConfig() + credential, err := provider.Resolve() + if err != nil { + return + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitWithOptions(regionId string, config *Config, credential auth.Credential) (err error) { + client.isRunning = true + client.asyncChanLock = new(sync.RWMutex) + client.regionId = regionId + client.config = config + client.httpClient = &http.Client{} + + if config.HttpTransport != nil { + client.httpClient.Transport = config.HttpTransport + } + + if config.Timeout > 0 { + client.httpClient.Timeout = config.Timeout + } + + if config.EnableAsync { + client.EnableAsync(config.GoRoutinePoolSize, config.MaxTaskQueueSize) + } + + client.signer, err = auth.NewSignerWithCredential(credential, client.ProcessCommonRequestWithSigner) + + return +} + +func (client *Client) SetReadTimeout(readTimeout time.Duration) { + client.readTimeout = readTimeout +} + +func (client *Client) SetConnectTimeout(connectTimeout time.Duration) { + client.connectTimeout = connectTimeout +} + +func (client *Client) GetReadTimeout() time.Duration { + return client.readTimeout +} + +func (client *Client) GetConnectTimeout() time.Duration { + return client.connectTimeout +} + +func (client *Client) getHttpProxy(scheme string) (proxy *url.URL, err error) { + if scheme == "https" { + if client.GetHttpsProxy() != "" { + proxy, err = url.Parse(client.httpsProxy) + } else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" { + proxy, err = url.Parse(rawurl) + } else if rawurl := os.Getenv("https_proxy"); rawurl != "" { + proxy, err = url.Parse(rawurl) + } + } else { + if client.GetHttpProxy() != "" { + proxy, err = url.Parse(client.httpProxy) + } else if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" { + proxy, err = url.Parse(rawurl) + } else if rawurl := os.Getenv("http_proxy"); rawurl != "" { + proxy, err = url.Parse(rawurl) + } + } + + return proxy, err +} + +func (client *Client) getNoProxy(scheme string) []string { + var urls []string + if client.GetNoProxy() != "" { + urls = strings.Split(client.noProxy, ",") + } else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" { + urls = strings.Split(rawurl, ",") + } else if rawurl := os.Getenv("no_proxy"); rawurl != "" { + urls = strings.Split(rawurl, ",") + } + + return urls +} + +// EnableAsync enable the async task queue +func (client *Client) EnableAsync(routinePoolSize, maxTaskQueueSize int) { + client.asyncTaskQueue = make(chan func(), maxTaskQueueSize) + for i := 0; i < routinePoolSize; i++ { + go func() { + for client.isRunning { + select { + case task, notClosed := <-client.asyncTaskQueue: + if notClosed { + task() + } + } + } + }() + } +} + +func (client *Client) InitWithAccessKey(regionId, accessKeyId, accessKeySecret string) (err error) { + config := client.InitClientConfig() + credential := &credentials.BaseCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitWithStsToken(regionId, accessKeyId, accessKeySecret, securityToken string) (err error) { + config := client.InitClientConfig() + credential := &credentials.StsTokenCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + AccessKeyStsToken: securityToken, + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (err error) { + config := client.InitClientConfig() + credential := &credentials.RamRoleArnCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + RoleArn: roleArn, + RoleSessionName: roleSessionName, + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitWithRamRoleArnAndPolicy(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string) (err error) { + config := client.InitClientConfig() + credential := &credentials.RamRoleArnCredential{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + RoleArn: roleArn, + RoleSessionName: roleSessionName, + Policy: policy, + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitWithRsaKeyPair(regionId, publicKeyId, privateKey string, sessionExpiration int) (err error) { + config := client.InitClientConfig() + credential := &credentials.RsaKeyPairCredential{ + PrivateKey: privateKey, + PublicKeyId: publicKeyId, + SessionExpiration: sessionExpiration, + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitWithEcsRamRole(regionId, roleName string) (err error) { + config := client.InitClientConfig() + credential := &credentials.EcsRamRoleCredential{ + RoleName: roleName, + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitWithBearerToken(regionId, bearerToken string) (err error) { + config := client.InitClientConfig() + credential := &credentials.BearerTokenCredential{ + BearerToken: bearerToken, + } + return client.InitWithOptions(regionId, config, credential) +} + +func (client *Client) InitClientConfig() (config *Config) { + if client.config != nil { + return client.config + } else { + return NewConfig() + } +} + +func (client *Client) DoAction(request requests.AcsRequest, response responses.AcsResponse) (err error) { + return client.DoActionWithSigner(request, response, nil) +} + +func (client *Client) GetEndpointRules(regionId string, product string) (endpointRaw string, err error) { + if client.EndpointType == "regional" { + if regionId == "" { + err = fmt.Errorf("RegionId is empty, please set a valid RegionId.") + return "", err + } + endpointRaw = strings.Replace("..aliyuncs.com", "", regionId, 1) + } else { + endpointRaw = ".aliyuncs.com" + } + endpointRaw = strings.Replace(endpointRaw, "", strings.ToLower(product), 1) + if client.Network == "" || client.Network == "public" { + endpointRaw = strings.Replace(endpointRaw, "", "", 1) + } else { + endpointRaw = strings.Replace(endpointRaw, "", "-"+client.Network, 1) + } + return endpointRaw, nil +} + +func (client *Client) buildRequestWithSigner(request requests.AcsRequest, signer auth.Signer) (httpRequest *http.Request, err error) { + // add clientVersion + request.GetHeaders()["x-sdk-core-version"] = Version + + regionId := client.regionId + if len(request.GetRegionId()) > 0 { + regionId = request.GetRegionId() + } + + // resolve endpoint + endpoint := request.GetDomain() + + if endpoint == "" && client.Domain != "" { + endpoint = client.Domain + } + + if endpoint == "" { + endpoint = endpoints.GetEndpointFromMap(regionId, request.GetProduct()) + } + + if endpoint == "" && client.EndpointType != "" && request.GetProduct() != "Sts" { + if client.EndpointMap != nil && client.Network == "" || client.Network == "public" { + endpoint = client.EndpointMap[regionId] + } + + if endpoint == "" { + endpoint, err = client.GetEndpointRules(regionId, request.GetProduct()) + if err != nil { + return + } + } + } + + if endpoint == "" { + resolveParam := &endpoints.ResolveParam{ + Domain: request.GetDomain(), + Product: request.GetProduct(), + RegionId: regionId, + LocationProduct: request.GetLocationServiceCode(), + LocationEndpointType: request.GetLocationEndpointType(), + CommonApi: client.ProcessCommonRequest, + } + endpoint, err = endpoints.Resolve(resolveParam) + if err != nil { + return + } + } + + request.SetDomain(endpoint) + if request.GetScheme() == "" { + request.SetScheme(client.config.Scheme) + } + // init request params + err = requests.InitParams(request) + if err != nil { + return + } + + // signature + var finalSigner auth.Signer + if signer != nil { + finalSigner = signer + } else { + finalSigner = client.signer + } + httpRequest, err = buildHttpRequest(request, finalSigner, regionId) + if err == nil { + userAgent := DefaultUserAgent + getSendUserAgent(client.config.UserAgent, client.userAgent, request.GetUserAgent()) + httpRequest.Header.Set("User-Agent", userAgent) + } + + return +} + +func getSendUserAgent(configUserAgent string, clientUserAgent, requestUserAgent map[string]string) string { + realUserAgent := "" + for key1, value1 := range clientUserAgent { + for key2, _ := range requestUserAgent { + if key1 == key2 { + key1 = "" + } + } + if key1 != "" { + realUserAgent += fmt.Sprintf(" %s/%s", key1, value1) + + } + } + for key, value := range requestUserAgent { + realUserAgent += fmt.Sprintf(" %s/%s", key, value) + } + if configUserAgent != "" { + return realUserAgent + fmt.Sprintf(" Extra/%s", configUserAgent) + } + return realUserAgent +} + +func (client *Client) AppendUserAgent(key, value string) { + newkey := true + + if client.userAgent == nil { + client.userAgent = make(map[string]string) + } + if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" { + for tag, _ := range client.userAgent { + if tag == key { + client.userAgent[tag] = value + newkey = false + } + } + if newkey { + client.userAgent[key] = value + } + } +} + +func (client *Client) BuildRequestWithSigner(request requests.AcsRequest, signer auth.Signer) (err error) { + _, err = client.buildRequestWithSigner(request, signer) + return +} + +func (client *Client) getTimeout(request requests.AcsRequest) (time.Duration, time.Duration) { + readTimeout := defaultReadTimeout + connectTimeout := defaultConnectTimeout + + reqReadTimeout := request.GetReadTimeout() + reqConnectTimeout := request.GetConnectTimeout() + if reqReadTimeout != 0*time.Millisecond { + readTimeout = reqReadTimeout + } else if client.readTimeout != 0*time.Millisecond { + readTimeout = client.readTimeout + } else if client.httpClient.Timeout != 0 { + readTimeout = client.httpClient.Timeout + } else if timeout, ok := getAPIMaxTimeout(request.GetProduct(), request.GetActionName()); ok { + readTimeout = timeout + } + + if reqConnectTimeout != 0*time.Millisecond { + connectTimeout = reqConnectTimeout + } else if client.connectTimeout != 0*time.Millisecond { + connectTimeout = client.connectTimeout + } + return readTimeout, connectTimeout +} + +func Timeout(connectTimeout time.Duration) func(cxt context.Context, net, addr string) (c net.Conn, err error) { + return func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{ + Timeout: connectTimeout, + DualStack: true, + }).DialContext(ctx, network, address) + } +} + +func (client *Client) setTimeout(request requests.AcsRequest) { + readTimeout, connectTimeout := client.getTimeout(request) + client.httpClient.Timeout = readTimeout + if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil { + trans.DialContext = Timeout(connectTimeout) + client.httpClient.Transport = trans + } else { + client.httpClient.Transport = &http.Transport{ + DialContext: Timeout(connectTimeout), + } + } +} + +func (client *Client) getHTTPSInsecure(request requests.AcsRequest) (insecure bool) { + if request.GetHTTPSInsecure() != nil { + insecure = *request.GetHTTPSInsecure() + } else { + insecure = client.GetHTTPSInsecure() + } + return insecure +} + +func (client *Client) DoActionWithSigner(request requests.AcsRequest, response responses.AcsResponse, signer auth.Signer) (err error) { + + fieldMap := make(map[string]string) + initLogMsg(fieldMap) + defer func() { + client.printLog(fieldMap, err) + }() + httpRequest, err := client.buildRequestWithSigner(request, signer) + if err != nil { + return + } + + client.setTimeout(request) + proxy, err := client.getHttpProxy(httpRequest.URL.Scheme) + if err != nil { + return err + } + + noProxy := client.getNoProxy(httpRequest.URL.Scheme) + + var flag bool + for _, value := range noProxy { + if value == httpRequest.Host { + flag = true + break + } + } + + // Set whether to ignore certificate validation. + // Default InsecureSkipVerify is false. + if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil { + trans.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: client.getHTTPSInsecure(request), + } + if proxy != nil && !flag { + trans.Proxy = http.ProxyURL(proxy) + } + client.httpClient.Transport = trans + } + + var httpResponse *http.Response + for retryTimes := 0; retryTimes <= client.config.MaxRetryTime; retryTimes++ { + if proxy != nil && proxy.User != nil { + if password, passwordSet := proxy.User.Password(); passwordSet { + httpRequest.SetBasicAuth(proxy.User.Username(), password) + } + } + if retryTimes > 0 { + client.printLog(fieldMap, err) + initLogMsg(fieldMap) + } + putMsgToMap(fieldMap, httpRequest) + debug("> %s %s %s", httpRequest.Method, httpRequest.URL.RequestURI(), httpRequest.Proto) + debug("> Host: %s", httpRequest.Host) + for key, value := range httpRequest.Header { + debug("> %s: %v", key, strings.Join(value, "")) + } + debug(">") + debug(" Retry Times: %d.", retryTimes) + + startTime := time.Now() + fieldMap["{start_time}"] = startTime.Format("2006-01-02 15:04:05") + httpResponse, err = hookDo(client.httpClient.Do)(httpRequest) + fieldMap["{cost}"] = time.Now().Sub(startTime).String() + if err == nil { + fieldMap["{code}"] = strconv.Itoa(httpResponse.StatusCode) + fieldMap["{res_headers}"] = TransToString(httpResponse.Header) + debug("< %s %s", httpResponse.Proto, httpResponse.Status) + for key, value := range httpResponse.Header { + debug("< %s: %v", key, strings.Join(value, "")) + } + } + debug("<") + // receive error + if err != nil { + debug(" Error: %s.", err.Error()) + if !client.config.AutoRetry { + return + } else if retryTimes >= client.config.MaxRetryTime { + // timeout but reached the max retry times, return + times := strconv.Itoa(retryTimes + 1) + timeoutErrorMsg := fmt.Sprintf(errors.TimeoutErrorMessage, times, times) + if strings.Contains(err.Error(), "Client.Timeout") { + timeoutErrorMsg += " Read timeout. Please set a valid ReadTimeout." + } else { + timeoutErrorMsg += " Connect timeout. Please set a valid ConnectTimeout." + } + err = errors.NewClientError(errors.TimeoutErrorCode, timeoutErrorMsg, err) + return + } + } + if isCertificateError(err) { + return + } + + // if status code >= 500 or timeout, will trigger retry + if client.config.AutoRetry && (err != nil || isServerError(httpResponse)) { + client.setTimeout(request) + // rewrite signatureNonce and signature + httpRequest, err = client.buildRequestWithSigner(request, signer) + // buildHttpRequest(request, finalSigner, regionId) + if err != nil { + return + } + continue + } + break + } + + err = responses.Unmarshal(response, httpResponse, request.GetAcceptFormat()) + fieldMap["{res_body}"] = response.GetHttpContentString() + debug("%s", response.GetHttpContentString()) + // wrap server errors + if serverErr, ok := err.(*errors.ServerError); ok { + var wrapInfo = map[string]string{} + wrapInfo["StringToSign"] = request.GetStringToSign() + err = errors.WrapServerError(serverErr, wrapInfo) + } + return +} + +func isCertificateError(err error) bool { + if err != nil && strings.Contains(err.Error(), "x509: certificate signed by unknown authority") { + return true + } + return false +} + +func putMsgToMap(fieldMap map[string]string, request *http.Request) { + fieldMap["{host}"] = request.Host + fieldMap["{method}"] = request.Method + fieldMap["{uri}"] = request.URL.RequestURI() + fieldMap["{pid}"] = strconv.Itoa(os.Getpid()) + fieldMap["{version}"] = strings.Split(request.Proto, "/")[1] + hostname, _ := os.Hostname() + fieldMap["{hostname}"] = hostname + fieldMap["{req_headers}"] = TransToString(request.Header) + fieldMap["{target}"] = request.URL.Path + request.URL.RawQuery +} + +func buildHttpRequest(request requests.AcsRequest, singer auth.Signer, regionId string) (httpRequest *http.Request, err error) { + err = auth.Sign(request, singer, regionId) + if err != nil { + return + } + requestMethod := request.GetMethod() + requestUrl := request.BuildUrl() + body := request.GetBodyReader() + httpRequest, err = http.NewRequest(requestMethod, requestUrl, body) + if err != nil { + return + } + for key, value := range request.GetHeaders() { + httpRequest.Header[key] = []string{value} + } + // host is a special case + if host, containsHost := request.GetHeaders()["Host"]; containsHost { + httpRequest.Host = host + } + return +} + +func isServerError(httpResponse *http.Response) bool { + return httpResponse.StatusCode >= http.StatusInternalServerError +} + +/** +only block when any one of the following occurs: +1. the asyncTaskQueue is full, increase the queue size to avoid this +2. Shutdown() in progressing, the client is being closed +**/ +func (client *Client) AddAsyncTask(task func()) (err error) { + if client.asyncTaskQueue != nil { + client.asyncChanLock.RLock() + defer client.asyncChanLock.RUnlock() + if client.isRunning { + client.asyncTaskQueue <- task + } + } else { + err = errors.NewClientError(errors.AsyncFunctionNotEnabledCode, errors.AsyncFunctionNotEnabledMessage, nil) + } + return +} + +func (client *Client) GetConfig() *Config { + return client.config +} + +func NewClient() (client *Client, err error) { + client = &Client{} + err = client.Init() + return +} + +func NewClientWithProvider(regionId string, providers ...provider.Provider) (client *Client, err error) { + client = &Client{} + var pc provider.Provider + if len(providers) == 0 { + pc = provider.DefaultChain + } else { + pc = provider.NewProviderChain(providers) + } + err = client.InitWithProviderChain(regionId, pc) + return +} + +func NewClientWithOptions(regionId string, config *Config, credential auth.Credential) (client *Client, err error) { + client = &Client{} + err = client.InitWithOptions(regionId, config, credential) + return +} + +func NewClientWithAccessKey(regionId, accessKeyId, accessKeySecret string) (client *Client, err error) { + client = &Client{} + err = client.InitWithAccessKey(regionId, accessKeyId, accessKeySecret) + return +} + +func NewClientWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken string) (client *Client, err error) { + client = &Client{} + err = client.InitWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken) + return +} + +func NewClientWithRamRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) { + client = &Client{} + err = client.InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName) + return +} + +func NewClientWithRamRoleArnAndPolicy(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string) (client *Client, err error) { + client = &Client{} + err = client.InitWithRamRoleArnAndPolicy(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy) + return +} + +func NewClientWithEcsRamRole(regionId string, roleName string) (client *Client, err error) { + client = &Client{} + err = client.InitWithEcsRamRole(regionId, roleName) + return +} + +func NewClientWithRsaKeyPair(regionId string, publicKeyId, privateKey string, sessionExpiration int) (client *Client, err error) { + client = &Client{} + err = client.InitWithRsaKeyPair(regionId, publicKeyId, privateKey, sessionExpiration) + return +} + +func NewClientWithBearerToken(regionId, bearerToken string) (client *Client, err error) { + client = &Client{} + err = client.InitWithBearerToken(regionId, bearerToken) + return +} + +func (client *Client) ProcessCommonRequest(request *requests.CommonRequest) (response *responses.CommonResponse, err error) { + request.TransToAcsRequest() + response = responses.NewCommonResponse() + err = client.DoAction(request, response) + return +} + +func (client *Client) ProcessCommonRequestWithSigner(request *requests.CommonRequest, signerInterface interface{}) (response *responses.CommonResponse, err error) { + if signer, isSigner := signerInterface.(auth.Signer); isSigner { + request.TransToAcsRequest() + response = responses.NewCommonResponse() + err = client.DoActionWithSigner(request, response, signer) + return + } + panic("should not be here") +} + +func (client *Client) Shutdown() { + // lock the addAsync() + client.asyncChanLock.Lock() + defer client.asyncChanLock.Unlock() + if client.asyncTaskQueue != nil { + close(client.asyncTaskQueue) + } + client.isRunning = false +} + +// Deprecated: Use NewClientWithRamRoleArn in this package instead. +func NewClientWithStsRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) { + return NewClientWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName) +} + +// Deprecated: Use NewClientWithEcsRamRole in this package instead. +func NewClientWithStsRoleNameOnEcs(regionId string, roleName string) (client *Client, err error) { + return NewClientWithEcsRamRole(regionId, roleName) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/config.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/config.go new file mode 100644 index 0000000..5e50166 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/config.go @@ -0,0 +1,91 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sdk + +import ( + "net/http" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +type Config struct { + AutoRetry bool `default:"true"` + MaxRetryTime int `default:"3"` + UserAgent string `default:""` + Debug bool `default:"false"` + HttpTransport *http.Transport `default:""` + EnableAsync bool `default:"false"` + MaxTaskQueueSize int `default:"1000"` + GoRoutinePoolSize int `default:"5"` + Scheme string `default:"HTTP"` + Timeout time.Duration +} + +func NewConfig() (config *Config) { + config = &Config{} + utils.InitStructWithDefaultTag(config) + return +} + +func (c *Config) WithAutoRetry(isAutoRetry bool) *Config { + c.AutoRetry = isAutoRetry + return c +} + +func (c *Config) WithMaxRetryTime(maxRetryTime int) *Config { + c.MaxRetryTime = maxRetryTime + return c +} + +func (c *Config) WithUserAgent(userAgent string) *Config { + c.UserAgent = userAgent + return c +} + +func (c *Config) WithDebug(isDebug bool) *Config { + c.Debug = isDebug + return c +} + +func (c *Config) WithTimeout(timeout time.Duration) *Config { + c.Timeout = timeout + return c +} + +func (c *Config) WithHttpTransport(httpTransport *http.Transport) *Config { + c.HttpTransport = httpTransport + return c +} + +func (c *Config) WithEnableAsync(isEnableAsync bool) *Config { + c.EnableAsync = isEnableAsync + return c +} + +func (c *Config) WithMaxTaskQueueSize(maxTaskQueueSize int) *Config { + c.MaxTaskQueueSize = maxTaskQueueSize + return c +} + +func (c *Config) WithGoRoutinePoolSize(goRoutinePoolSize int) *Config { + c.GoRoutinePoolSize = goRoutinePoolSize + return c +} + +func (c *Config) WithScheme(scheme string) *Config { + c.Scheme = scheme + return c +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/endpoints_config.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/endpoints_config.go new file mode 100644 index 0000000..a4fc470 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/endpoints_config.go @@ -0,0 +1,4126 @@ + +package endpoints + +import ( + "encoding/json" + "fmt" + "sync" +) + +const endpointsJson =`{ + "products": [ + { + "code": "emr", + "document_id": "28140", + "location_service_code": "emr", + "regional_endpoints": [ + { + "region": "cn-qingdao", + "endpoint": "emr.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "emr.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "emr.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "emr.eu-west-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "emr.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "emr.me-east-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "emr.ap-northeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "emr.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "emr.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "emr.ap-south-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "emr.us-east-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "emr.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "emr.cn-hongkong.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "emr.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "emr.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "emr.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "emr.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "emr.ap-southeast-5.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "emr.aliyuncs.com" + } + ], + "global_endpoint": "emr.aliyuncs.com", + "regional_endpoint_pattern": "emr.[RegionId].aliyuncs.com" + }, + { + "code": "petadata", + "document_id": "", + "location_service_code": "petadata", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "petadata.me-east-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "petadata.ap-southeast-2.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "petadata.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "petadata.ap-southeast-5.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "petadata.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "petadata.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "petadata.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "petadata.aliyuncs.com" + } + ], + "global_endpoint": "petadata.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "dbs", + "document_id": "", + "location_service_code": "dbs", + "regional_endpoints": [ + { + "region": "cn-shenzhen", + "endpoint": "dbs-api.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "dbs-api.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "dbs-api.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "dbs-api.ap-northeast-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "dbs-api.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "dbs-api.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "dbs-api.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "dbs-api.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "alidnsgtm", + "document_id": "", + "location_service_code": "alidnsgtm", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "alidns.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "alidns.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "elasticsearch", + "document_id": "", + "location_service_code": "elasticsearch", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "elasticsearch.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "elasticsearch.cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "elasticsearch.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "elasticsearch.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "elasticsearch.cn-hongkong.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "elasticsearch.ap-southeast-3.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "elasticsearch.us-west-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "elasticsearch.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "elasticsearch.ap-southeast-5.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "elasticsearch.eu-central-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "elasticsearch.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "elasticsearch.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "elasticsearch.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "elasticsearch.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "elasticsearch.ap-northeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "baas", + "document_id": "", + "location_service_code": "baas", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "baas.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "baas.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "baas.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "baas.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "baas.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "baas.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cr", + "document_id": "60716", + "location_service_code": "cr", + "regional_endpoints": null, + "global_endpoint": "cr.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "cloudap", + "document_id": "", + "location_service_code": "cloudap", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "cloudwf.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "imagesearch", + "document_id": "", + "location_service_code": "imagesearch", + "regional_endpoints": [ + { + "region": "ap-southeast-2", + "endpoint": "imagesearch.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "imagesearch.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "imagesearch.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "imagesearch.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "pts", + "document_id": "", + "location_service_code": "pts", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "pts.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ehs", + "document_id": "", + "location_service_code": "ehs", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "ehpc.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "ehpc.cn-hongkong.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "ehpc.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "ehpc.cn-qingdao.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "ehpc.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "ehpc.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "ehpc.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "ehpc.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ehpc.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "ehpc.cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "ehpc.ap-southeast-2.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "polardb", + "document_id": "58764", + "location_service_code": "polardb", + "regional_endpoints": [ + { + "region": "ap-south-1", + "endpoint": "polardb.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "polardb.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "polardb.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "polardb.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "polardb.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "polardb.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "polardb.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "polardb.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "polardb.ap-southeast-5.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "polardb.aliyuncs.com" + }, + { + "code": "r-kvstore", + "document_id": "60831", + "location_service_code": "redisa", + "regional_endpoints": [ + { + "region": "cn-shenzhen", + "endpoint": "r-kvstore.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "r-kvstore.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "r-kvstore.ap-southeast-3.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "r-kvstore.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "r-kvstore.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "r-kvstore.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "r-kvstore.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "r-kvstore.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "r-kvstore.cn-hongkong.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "r-kvstore.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "r-kvstore.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "r-kvstore.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "r-kvstore.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "r-kvstore.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "r-kvstore.eu-west-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "r-kvstore.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "r-kvstore.me-east-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "r-kvstore.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "r-kvstore.ap-southeast-5.aliyuncs.com" + } + ], + "global_endpoint": "r-kvstore.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "xianzhi", + "document_id": "", + "location_service_code": "xianzhi", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "xianzhi.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "pcdn", + "document_id": "", + "location_service_code": "pcdn", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "pcdn.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cdn", + "document_id": "27148", + "location_service_code": "cdn", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "cdn.aliyuncs.com" + } + ], + "global_endpoint": "cdn.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "cloudauth", + "document_id": "60687", + "location_service_code": "cloudauth", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "cloudauth.aliyuncs.com" + } + ], + "global_endpoint": "cloudauth.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "nas", + "document_id": "62598", + "location_service_code": "nas", + "regional_endpoints": [ + { + "region": "ap-southeast-2", + "endpoint": "nas.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "nas.ap-south-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "nas.eu-central-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "nas.us-west-1.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "nas.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "nas.cn-qingdao.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "nas.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "nas.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "nas.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "nas.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "nas.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "nas.ap-northeast-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "nas.us-east-1.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "nas.cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "nas.ap-southeast-5.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "nas.cn-hongkong.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "nas.ap-southeast-3.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "alidns", + "document_id": "29739", + "location_service_code": "alidns", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "alidns.aliyuncs.com" + } + ], + "global_endpoint": "alidns.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "dts", + "document_id": "", + "location_service_code": "dts", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "dts.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "dts.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "emas", + "document_id": "", + "location_service_code": "emas", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "mhub.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "mhub.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "dysmsapi", + "document_id": "", + "location_service_code": "dysmsapi", + "regional_endpoints": [ + { + "region": "ap-southeast-3", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "dysmsapi.aliyuncs.com" + }, + { + "region": "cn-chengdu", + "endpoint": "dysmsapi.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "dysmsapi.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "dysmsapi.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "dysmsapi.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "dysmsapi.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "dysmsapi.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "dysmsapi.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cloudwf", + "document_id": "58111", + "location_service_code": "cloudwf", + "regional_endpoints": null, + "global_endpoint": "cloudwf.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "fc", + "document_id": "", + "location_service_code": "fc", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "cn-beijing.fc.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "ap-southeast-2.fc.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "cn-huhehaote.fc.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "cn-shanghai.fc.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "cn-hangzhou.fc.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "cn-shenzhen.fc.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "saf", + "document_id": "", + "location_service_code": "saf", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "saf.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "saf.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "saf.cn-shenzhen.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "rds", + "document_id": "26223", + "location_service_code": "rds", + "regional_endpoints": [ + { + "region": "ap-northeast-1", + "endpoint": "rds.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "rds.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "rds.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "rds.eu-west-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "rds.ap-southeast-3.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "rds.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "rds.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "rds.ap-southeast-5.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "rds.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "rds.me-east-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "rds.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "rds.aliyuncs.com" + } + ], + "global_endpoint": "rds.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "vpc", + "document_id": "34962", + "location_service_code": "vpc", + "regional_endpoints": [ + { + "region": "ap-south-1", + "endpoint": "vpc.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "vpc.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "vpc.ap-northeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "vpc.cn-huhehaote.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "vpc.me-east-1.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "vpc.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "vpc.ap-southeast-3.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "vpc.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "vpc.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "vpc.eu-west-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "vpc.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "vpc.aliyuncs.com" + } + ], + "global_endpoint": "vpc.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "gpdb", + "document_id": "", + "location_service_code": "gpdb", + "regional_endpoints": [ + { + "region": "ap-southeast-3", + "endpoint": "gpdb.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "gpdb.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "gpdb.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "gpdb.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "gpdb.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "gpdb.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "gpdb.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "gpdb.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "gpdb.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "gpdb.ap-southeast-2.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "gpdb.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "gpdb.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "gpdb.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "gpdb.ap-northeast-1.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "gpdb.eu-west-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "gpdb.ap-south-1.aliyuncs.com" + } + ], + "global_endpoint": "gpdb.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "yunmarket", + "document_id": "", + "location_service_code": "yunmarket", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "market.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "pvtz", + "document_id": "", + "location_service_code": "pvtz", + "regional_endpoints": [ + { + "region": "ap-southeast-1", + "endpoint": "pvtz.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "pvtz.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "oss", + "document_id": "", + "location_service_code": "oss", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "oss-cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "oss-cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "oss-cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "oss-cn-hongkong.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "oss-cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "oss-ap-southeast-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "oss-us-west-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "oss-cn-qingdao.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "foas", + "document_id": "", + "location_service_code": "foas", + "regional_endpoints": [ + { + "region": "cn-qingdao", + "endpoint": "foas.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "foas.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "foas.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "foas.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "foas.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "foas.cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "foas.ap-northeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ddos", + "document_id": "", + "location_service_code": "ddos", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ddospro.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "ddospro.cn-hongkong.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cbn", + "document_id": "", + "location_service_code": "cbn", + "regional_endpoints": [ + { + "region": "ap-southeast-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "cbn.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "cbn.aliyuncs.com" + } + ], + "global_endpoint": "cbn.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "nlp", + "document_id": "", + "location_service_code": "nlp", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "nlp.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "hsm", + "document_id": "", + "location_service_code": "hsm", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "hsm.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "hsm.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "hsm.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "hsm.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "hsm.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "hsm.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ons", + "document_id": "44416", + "location_service_code": "ons", + "regional_endpoints": [ + { + "region": "ap-southeast-1", + "endpoint": "ons.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "ons.cn-huhehaote.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "ons.us-east-1.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "ons.cn-hongkong.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "ons.cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "ons.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "ons.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "ons.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "ons.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "ons.me-east-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "ons.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "ons.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "ons.cn-hangzhou.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "ons.eu-central-1.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "ons.eu-west-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "ons.us-west-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "ons.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ons.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "kms", + "document_id": "", + "location_service_code": "kms", + "regional_endpoints": [ + { + "region": "cn-hongkong", + "endpoint": "kms.cn-hongkong.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "kms.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "kms.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "kms.cn-qingdao.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "kms.eu-west-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "kms.us-east-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "kms.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "kms.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "kms.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "kms.ap-southeast-5.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "kms.cn-huhehaote.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "kms.me-east-1.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "kms.cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "kms.ap-southeast-3.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "kms.us-west-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "kms.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "kms.ap-southeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "kms.eu-central-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "kms.ap-northeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cps", + "document_id": "", + "location_service_code": "cps", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "cloudpush.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ensdisk", + "document_id": "", + "location_service_code": "ensdisk", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ens.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cloudapi", + "document_id": "43590", + "location_service_code": "apigateway", + "regional_endpoints": [ + { + "region": "ap-southeast-2", + "endpoint": "apigateway.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "apigateway.ap-south-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "apigateway.us-east-1.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "apigateway.me-east-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "apigateway.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "apigateway.cn-beijing.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "apigateway.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "apigateway.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "apigateway.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "apigateway.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "apigateway.ap-southeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "apigateway.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "apigateway.cn-hangzhou.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "apigateway.us-west-1.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "apigateway.cn-shenzhen.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "apigateway.eu-west-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "apigateway.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "apigateway.ap-northeast-1.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "apigateway.cn-hongkong.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "apigateway.[RegionId].aliyuncs.com" + }, + { + "code": "eci", + "document_id": "", + "location_service_code": "eci", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "eci.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "eci.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "eci.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "eci.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "eci.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "eci.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "onsvip", + "document_id": "", + "location_service_code": "onsvip", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "ons.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "ons.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ons.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "ons.cn-shenzhen.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "ons.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "ons.cn-qingdao.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "linkwan", + "document_id": "", + "location_service_code": "linkwan", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "linkwan.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "linkwan.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ddosdip", + "document_id": "", + "location_service_code": "ddosdip", + "regional_endpoints": [ + { + "region": "ap-southeast-1", + "endpoint": "ddosdip.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "batchcompute", + "document_id": "44717", + "location_service_code": "batchcompute", + "regional_endpoints": [ + { + "region": "us-west-1", + "endpoint": "batchcompute.us-west-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "batchcompute.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "batchcompute.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "batchcompute.cn-shenzhen.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "batchcompute.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "batchcompute.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "batchcompute.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "batchcompute.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "batchcompute.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "batchcompute.[RegionId].aliyuncs.com" + }, + { + "code": "aegis", + "document_id": "28449", + "location_service_code": "vipaegis", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "aegis.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "aegis.ap-southeast-3.aliyuncs.com" + } + ], + "global_endpoint": "aegis.cn-hangzhou.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "arms", + "document_id": "42924", + "location_service_code": "arms", + "regional_endpoints": [ + { + "region": "cn-hongkong", + "endpoint": "arms.cn-hongkong.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "arms.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "arms.cn-shenzhen.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "arms.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "arms.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "arms.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "arms.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "arms.[RegionId].aliyuncs.com" + }, + { + "code": "live", + "document_id": "48207", + "location_service_code": "live", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "live.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "live.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "live.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "live.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "live.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "live.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "live.aliyuncs.com" + } + ], + "global_endpoint": "live.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "alimt", + "document_id": "", + "location_service_code": "alimt", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "mt.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "actiontrail", + "document_id": "", + "location_service_code": "actiontrail", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "actiontrail.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "actiontrail.cn-qingdao.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "actiontrail.us-east-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "actiontrail.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "actiontrail.ap-southeast-3.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "actiontrail.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "actiontrail.ap-south-1.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "actiontrail.me-east-1.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "actiontrail.cn-hongkong.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "actiontrail.cn-shenzhen.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "actiontrail.cn-hangzhou.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "actiontrail.eu-west-1.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "actiontrail.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "actiontrail.ap-northeast-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "actiontrail.us-west-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "actiontrail.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "actiontrail.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "actiontrail.cn-beijing.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "actiontrail.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "smartag", + "document_id": "", + "location_service_code": "smartag", + "regional_endpoints": [ + { + "region": "ap-southeast-3", + "endpoint": "smartag.ap-southeast-3.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "smartag.ap-southeast-5.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "smartag.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "smartag.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "smartag.cn-hongkong.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "smartag.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "smartag.ap-southeast-2.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "vod", + "document_id": "60574", + "location_service_code": "vod", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "vod.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "vod.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "vod.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "vod.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "vod.ap-southeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "vod.eu-central-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "domain", + "document_id": "42875", + "location_service_code": "domain", + "regional_endpoints": [ + { + "region": "ap-southeast-1", + "endpoint": "domain-intl.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "domain.aliyuncs.com" + } + ], + "global_endpoint": "domain.aliyuncs.com", + "regional_endpoint_pattern": "domain.aliyuncs.com" + }, + { + "code": "ros", + "document_id": "28899", + "location_service_code": "ros", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ros.aliyuncs.com" + } + ], + "global_endpoint": "ros.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "cloudphoto", + "document_id": "59902", + "location_service_code": "cloudphoto", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "cloudphoto.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "cloudphoto.[RegionId].aliyuncs.com" + }, + { + "code": "rtc", + "document_id": "", + "location_service_code": "rtc", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "rtc.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "odpsmayi", + "document_id": "", + "location_service_code": "odpsmayi", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "bsb.cloud.alipay.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "bsb.cloud.alipay.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ims", + "document_id": "", + "location_service_code": "ims", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ims.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "csb", + "document_id": "64837", + "location_service_code": "csb", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "csb.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "csb.cn-beijing.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "csb.[RegionId].aliyuncs.com" + }, + { + "code": "cds", + "document_id": "62887", + "location_service_code": "codepipeline", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "cds.cn-beijing.aliyuncs.com" + } + ], + "global_endpoint": "cds.cn-beijing.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "ddosbgp", + "document_id": "", + "location_service_code": "ddosbgp", + "regional_endpoints": [ + { + "region": "cn-huhehaote", + "endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "ddosbgp.cn-hongkong.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "ddosbgp.us-west-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "dybaseapi", + "document_id": "", + "location_service_code": "dybaseapi", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "cn-chengdu", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "dybaseapi.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ecs", + "document_id": "25484", + "location_service_code": "ecs", + "regional_endpoints": [ + { + "region": "cn-huhehaote", + "endpoint": "ecs.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "ecs.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "ecs.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "ecs.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "ecs.ap-southeast-3.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "ecs.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "ecs.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "ecs.eu-west-1.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "ecs.me-east-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "ecs.ap-southeast-5.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "ecs-cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "ecs-cn-hangzhou.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "ccc", + "document_id": "63027", + "location_service_code": "ccc", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ccc.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ccc.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "ccc.[RegionId].aliyuncs.com" + }, + { + "code": "cs", + "document_id": "26043", + "location_service_code": "cs", + "regional_endpoints": null, + "global_endpoint": "cs.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "drdspre", + "document_id": "", + "location_service_code": "drdspre", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "drds.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "drds.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "drds.cn-shenzhen.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "drds.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "drds.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "drds.cn-qingdao.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "drds.cn-beijing.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "dcdn", + "document_id": "", + "location_service_code": "dcdn", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "dcdn.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "dcdn.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "linkedmall", + "document_id": "", + "location_service_code": "linkedmall", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "linkedmall.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "linkedmall.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "trademark", + "document_id": "", + "location_service_code": "trademark", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "trademark.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "openanalytics", + "document_id": "", + "location_service_code": "openanalytics", + "regional_endpoints": [ + { + "region": "cn-shenzhen", + "endpoint": "openanalytics.cn-shenzhen.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "openanalytics.eu-west-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "openanalytics.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "openanalytics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "openanalytics.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "openanalytics.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "openanalytics.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "openanalytics.cn-zhangjiakou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "sts", + "document_id": "28756", + "location_service_code": "sts", + "regional_endpoints": null, + "global_endpoint": "sts.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "waf", + "document_id": "62847", + "location_service_code": "waf", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "wafopenapi.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ots", + "document_id": "", + "location_service_code": "ots", + "regional_endpoints": [ + { + "region": "me-east-1", + "endpoint": "ots.me-east-1.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "ots.ap-southeast-5.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "ots.eu-west-1.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "ots.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "ots.cn-beijing.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "ots.ap-southeast-2.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "ots.us-west-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "ots.us-east-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "ots.ap-south-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "ots.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "ots.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "ots.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "ots.ap-northeast-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ots.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "ots.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "ots.ap-southeast-3.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cloudfirewall", + "document_id": "", + "location_service_code": "cloudfirewall", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "cloudfw.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "dm", + "document_id": "29434", + "location_service_code": "dm", + "regional_endpoints": [ + { + "region": "ap-southeast-2", + "endpoint": "dm.ap-southeast-2.aliyuncs.com" + } + ], + "global_endpoint": "dm.aliyuncs.com", + "regional_endpoint_pattern": "dm.[RegionId].aliyuncs.com" + }, + { + "code": "oas", + "document_id": "", + "location_service_code": "oas", + "regional_endpoints": [ + { + "region": "cn-shenzhen", + "endpoint": "cn-shenzhen.oas.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "cn-beijing.oas.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "cn-hangzhou.oas.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ddoscoo", + "document_id": "", + "location_service_code": "ddoscoo", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ddoscoo.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "jaq", + "document_id": "35037", + "location_service_code": "jaq", + "regional_endpoints": null, + "global_endpoint": "jaq.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "iovcc", + "document_id": "", + "location_service_code": "iovcc", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "iovcc.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "sas-api", + "document_id": "28498", + "location_service_code": "sas", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "sas.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "chatbot", + "document_id": "60760", + "location_service_code": "beebot", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "chatbot.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "chatbot.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "chatbot.[RegionId].aliyuncs.com" + }, + { + "code": "airec", + "document_id": "", + "location_service_code": "airec", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "airec.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "airec.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "airec.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "dmsenterprise", + "document_id": "", + "location_service_code": "dmsenterprise", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "dms-enterprise.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "dms-enterprise.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "dms-enterprise.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "dms-enterprise.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "dms-enterprise.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "dms-enterprise.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ivision", + "document_id": "", + "location_service_code": "ivision", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ivision.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "ivision.cn-beijing.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "odpsplusmayi", + "document_id": "", + "location_service_code": "odpsplusmayi", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "bsb.cloud.alipay.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "bsb.cloud.alipay.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "bsb.cloud.alipay.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "gameshield", + "document_id": "", + "location_service_code": "gameshield", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "gameshield.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "gameshield.cn-zhangjiakou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "scdn", + "document_id": "", + "location_service_code": "scdn", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "scdn.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "hitsdb", + "document_id": "", + "location_service_code": "hitsdb", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "hitsdb.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "hdm", + "document_id": "", + "location_service_code": "hdm", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "hdm-api.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "slb", + "document_id": "27565", + "location_service_code": "slb", + "regional_endpoints": [ + { + "region": "cn-shenzhen", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "slb.eu-west-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "slb.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "slb.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "slb.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "slb.ap-south-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "slb.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "slb.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "slb.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "slb.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "slb.me-east-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "slb.cn-zhangjiakou.aliyuncs.com" + } + ], + "global_endpoint": "slb.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "green", + "document_id": "28427", + "location_service_code": "green", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "green.cn-beijing.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "green.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "green.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "green.cn-hangzhou.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "green.us-west-1.aliyuncs.com" + } + ], + "global_endpoint": "green.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "cccvn", + "document_id": "", + "location_service_code": "cccvn", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "voicenavigator.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ddosrewards", + "document_id": "", + "location_service_code": "ddosrewards", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ddosright.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "iot", + "document_id": "30557", + "location_service_code": "iot", + "regional_endpoints": [ + { + "region": "us-east-1", + "endpoint": "iot.us-east-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "iot.ap-northeast-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "iot.us-west-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "iot.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "iot.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "iot.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "iot.[RegionId].aliyuncs.com" + }, + { + "code": "bssopenapi", + "document_id": "", + "location_service_code": "bssopenapi", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "business.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "business.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "sca", + "document_id": "", + "location_service_code": "sca", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "qualitycheck.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "luban", + "document_id": "", + "location_service_code": "luban", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "luban.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "luban.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "drdspost", + "document_id": "", + "location_service_code": "drdspost", + "regional_endpoints": [ + { + "region": "cn-shanghai", + "endpoint": "drds.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "drds.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "drds.ap-southeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "drds", + "document_id": "51111", + "location_service_code": "drds", + "regional_endpoints": [ + { + "region": "ap-southeast-1", + "endpoint": "drds.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "drds.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "drds.aliyuncs.com", + "regional_endpoint_pattern": "drds.aliyuncs.com" + }, + { + "code": "httpdns", + "document_id": "52679", + "location_service_code": "httpdns", + "regional_endpoints": null, + "global_endpoint": "httpdns-api.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "cas", + "document_id": "", + "location_service_code": "cas", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "cas.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "cas.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "cas.ap-northeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "cas.eu-central-1.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "cas.me-east-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "hpc", + "document_id": "35201", + "location_service_code": "hpc", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "hpc.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "hpc.aliyuncs.com" + } + ], + "global_endpoint": "hpc.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "ddosbasic", + "document_id": "", + "location_service_code": "ddosbasic", + "regional_endpoints": [ + { + "region": "ap-south-1", + "endpoint": "antiddos-openapi.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "antiddos-openapi.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "antiddos-openapi.ap-southeast-3.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "antiddos-openapi.me-east-1.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "antiddos-openapi.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "antiddos-openapi.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "antiddos-openapi.eu-west-1.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "antiddos-openapi.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "antiddos-openapi.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "antiddos.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "antiddos-openapi.ap-northeast-1.aliyuncs.com" + } + ], + "global_endpoint": "antiddos.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "clouddesktop", + "document_id": "", + "location_service_code": "clouddesktop", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "clouddesktop.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "clouddesktop.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "clouddesktop.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "clouddesktop.cn-shenzhen.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "uis", + "document_id": "", + "location_service_code": "uis", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "uis.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "imm", + "document_id": "", + "location_service_code": "imm", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "imm.cn-beijing.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "imm.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "imm.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "imm.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "imm.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "imm.cn-shenzhen.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ens", + "document_id": "", + "location_service_code": "ens", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ens.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ram", + "document_id": "28672", + "location_service_code": "ram", + "regional_endpoints": null, + "global_endpoint": "ram.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "hcs_mgw", + "document_id": "", + "location_service_code": "hcs_mgw", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "mgw.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "mgw.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "mgw.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "itaas", + "document_id": "55759", + "location_service_code": "itaas", + "regional_endpoints": null, + "global_endpoint": "itaas.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "qualitycheck", + "document_id": "50807", + "location_service_code": "qualitycheck", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "qualitycheck.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "alikafka", + "document_id": "", + "location_service_code": "alikafka", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "alikafka.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "alikafka.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "alikafka.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "alikafka.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "alikafka.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "alikafka.cn-shenzhen.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "alikafka.cn-hongkong.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "alikafka.cn-qingdao.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "faas", + "document_id": "", + "location_service_code": "faas", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "faas.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "faas.cn-shenzhen.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "faas.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "faas.cn-beijing.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "alidfs", + "document_id": "", + "location_service_code": "alidfs", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "dfs.cn-beijing.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "dfs.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "cms", + "document_id": "28615", + "location_service_code": "cms", + "regional_endpoints": [ + { + "region": "ap-southeast-3", + "endpoint": "metrics.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "metrics.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "metrics.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "metrics.eu-west-1.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "metrics.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "metrics.ap-northeast-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "metrics.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "metrics.cn-hangzhou.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "domain-intl", + "document_id": "", + "location_service_code": "domain-intl", + "regional_endpoints": null, + "global_endpoint": "domain-intl.aliyuncs.com", + "regional_endpoint_pattern": "domain-intl.aliyuncs.com" + }, + { + "code": "kvstore", + "document_id": "", + "location_service_code": "kvstore", + "regional_endpoints": [ + { + "region": "ap-northeast-1", + "endpoint": "r-kvstore.ap-northeast-1.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ccs", + "document_id": "", + "location_service_code": "ccs", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "ccs.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "ess", + "document_id": "25925", + "location_service_code": "ess", + "regional_endpoints": [ + { + "region": "cn-huhehaote", + "endpoint": "ess.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "ess.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "ess.eu-west-1.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "ess.ap-southeast-5.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "ess.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "ess.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "ess.me-east-1.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "ess.ap-northeast-1.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "ess.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "ess.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "ess.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "ess.aliyuncs.com" + } + ], + "global_endpoint": "ess.aliyuncs.com", + "regional_endpoint_pattern": "ess.[RegionId].aliyuncs.com" + }, + { + "code": "dds", + "document_id": "61715", + "location_service_code": "dds", + "regional_endpoints": [ + { + "region": "me-east-1", + "endpoint": "mongodb.me-east-1.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "mongodb.ap-southeast-3.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "mongodb.ap-southeast-5.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "mongodb.ap-northeast-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "mongodb.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "mongodb.eu-west-1.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "cn-huhehaote", + "endpoint": "mongodb.cn-huhehaote.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "mongodb.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "mongodb.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "mongodb.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "mongodb.ap-south-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "mongodb.aliyuncs.com" + } + ], + "global_endpoint": "mongodb.aliyuncs.com", + "regional_endpoint_pattern": "mongodb.[RegionId].aliyuncs.com" + }, + { + "code": "mts", + "document_id": "29212", + "location_service_code": "mts", + "regional_endpoints": [ + { + "region": "cn-beijing", + "endpoint": "mts.cn-beijing.aliyuncs.com" + }, + { + "region": "ap-northeast-1", + "endpoint": "mts.ap-northeast-1.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "mts.cn-hongkong.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "mts.cn-shenzhen.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "mts.cn-zhangjiakou.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "mts.ap-south-1.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "mts.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "mts.ap-southeast-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "mts.us-west-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "mts.eu-central-1.aliyuncs.com" + }, + { + "region": "eu-west-1", + "endpoint": "mts.eu-west-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "mts.cn-hangzhou.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "push", + "document_id": "30074", + "location_service_code": "push", + "regional_endpoints": null, + "global_endpoint": "cloudpush.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "hcs_sgw", + "document_id": "", + "location_service_code": "hcs_sgw", + "regional_endpoints": [ + { + "region": "eu-central-1", + "endpoint": "sgw.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "sgw.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-zhangjiakou", + "endpoint": "sgw.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "sgw.ap-southeast-1.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "sgw.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-hongkong", + "endpoint": "sgw.cn-shanghai.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "sgw.ap-southeast-2.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "sgw.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "sgw.cn-shanghai.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "sgw.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "hbase", + "document_id": "", + "location_service_code": "hbase", + "regional_endpoints": [ + { + "region": "cn-huhehaote", + "endpoint": "hbase.cn-huhehaote.aliyuncs.com" + }, + { + "region": "ap-south-1", + "endpoint": "hbase.ap-south-1.aliyuncs.com" + }, + { + "region": "us-west-1", + "endpoint": "hbase.aliyuncs.com" + }, + { + "region": "me-east-1", + "endpoint": "hbase.me-east-1.aliyuncs.com" + }, + { + "region": "eu-central-1", + "endpoint": "hbase.eu-central-1.aliyuncs.com" + }, + { + "region": "cn-qingdao", + "endpoint": "hbase.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "hbase.aliyuncs.com" + }, + { + "region": "cn-shenzhen", + "endpoint": "hbase.aliyuncs.com" + }, + { + "region": "ap-southeast-2", + "endpoint": "hbase.ap-southeast-2.aliyuncs.com" + }, + { + "region": "ap-southeast-3", + "endpoint": "hbase.ap-southeast-3.aliyuncs.com" + }, + { + "region": "cn-hangzhou", + "endpoint": "hbase.aliyuncs.com" + }, + { + "region": "us-east-1", + "endpoint": "hbase.aliyuncs.com" + }, + { + "region": "ap-southeast-5", + "endpoint": "hbase.ap-southeast-5.aliyuncs.com" + }, + { + "region": "cn-beijing", + "endpoint": "hbase.aliyuncs.com" + }, + { + "region": "ap-southeast-1", + "endpoint": "hbase.aliyuncs.com" + } + ], + "global_endpoint": "hbase.aliyuncs.com", + "regional_endpoint_pattern": "" + }, + { + "code": "bastionhost", + "document_id": "", + "location_service_code": "bastionhost", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "yundun-bastionhost.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + }, + { + "code": "vs", + "document_id": "", + "location_service_code": "vs", + "regional_endpoints": [ + { + "region": "cn-hangzhou", + "endpoint": "vs.cn-hangzhou.aliyuncs.com" + }, + { + "region": "cn-shanghai", + "endpoint": "vs.cn-shanghai.aliyuncs.com" + } + ], + "global_endpoint": "", + "regional_endpoint_pattern": "" + } + ] +}` +var initOnce sync.Once +var data interface{} + +func getEndpointConfigData() interface{} { + initOnce.Do(func() { + err := json.Unmarshal([]byte(endpointsJson), &data) + if err != nil { + panic(fmt.Sprintf("init endpoint config data failed. %s", err)) + } + }) + return data +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_global_resolver.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_global_resolver.go new file mode 100644 index 0000000..160e62c --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_global_resolver.go @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package endpoints + +import ( + "fmt" + "strings" + + "github.com/jmespath/go-jmespath" +) + +type LocalGlobalResolver struct { +} + +func (resolver *LocalGlobalResolver) GetName() (name string) { + name = "local global resolver" + return +} + +func (resolver *LocalGlobalResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) { + // get the global endpoints configs + endpointExpression := fmt.Sprintf("products[?code=='%s'].global_endpoint", strings.ToLower(param.Product)) + endpointData, err := jmespath.Search(endpointExpression, getEndpointConfigData()) + if err == nil && endpointData != nil && len(endpointData.([]interface{})) > 0 { + endpoint = endpointData.([]interface{})[0].(string) + support = len(endpoint) > 0 + return + } + support = false + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_regional_resolver.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_regional_resolver.go new file mode 100644 index 0000000..7fee64d --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_regional_resolver.go @@ -0,0 +1,48 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package endpoints + +import ( + "fmt" + "strings" + + "github.com/jmespath/go-jmespath" +) + +type LocalRegionalResolver struct { +} + +func (resolver *LocalRegionalResolver) GetName() (name string) { + name = "local regional resolver" + return +} + +func (resolver *LocalRegionalResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) { + // get the regional endpoints configs + regionalExpression := fmt.Sprintf("products[?code=='%s'].regional_endpoints", strings.ToLower(param.Product)) + regionalData, err := jmespath.Search(regionalExpression, getEndpointConfigData()) + if err == nil && regionalData != nil && len(regionalData.([]interface{})) > 0 { + endpointExpression := fmt.Sprintf("[0][?region=='%s'].endpoint", strings.ToLower(param.RegionId)) + var endpointData interface{} + endpointData, err = jmespath.Search(endpointExpression, regionalData) + if err == nil && endpointData != nil && len(endpointData.([]interface{})) > 0 { + endpoint = endpointData.([]interface{})[0].(string) + support = len(endpoint) > 0 + return + } + } + support = false + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/location_resolver.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/location_resolver.go new file mode 100644 index 0000000..cc354cc --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/location_resolver.go @@ -0,0 +1,176 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package endpoints + +import ( + "encoding/json" + "sync" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" +) + +const ( + // EndpointCacheExpireTime ... + EndpointCacheExpireTime = 3600 //Seconds +) + +// Cache caches endpoint for specific product and region +type Cache struct { + sync.RWMutex + cache map[string]interface{} +} + +// Get ... +func (c *Cache) Get(k string) (v interface{}) { + c.RLock() + v = c.cache[k] + c.RUnlock() + return +} + +// Set ... +func (c *Cache) Set(k string, v interface{}) { + c.Lock() + c.cache[k] = v + c.Unlock() +} + +var lastClearTimePerProduct = &Cache{cache: make(map[string]interface{})} +var endpointCache = &Cache{cache: make(map[string]interface{})} + +// LocationResolver ... +type LocationResolver struct { +} + +func (resolver *LocationResolver) GetName() (name string) { + name = "location resolver" + return +} + +// TryResolve resolves endpoint giving product and region +func (resolver *LocationResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) { + if len(param.LocationProduct) <= 0 { + support = false + return + } + + //get from cache + cacheKey := param.Product + "#" + param.RegionId + var ok bool + endpoint, ok = endpointCache.Get(cacheKey).(string) + + if ok && len(endpoint) > 0 && !CheckCacheIsExpire(cacheKey) { + support = true + return + } + + //get from remote + getEndpointRequest := requests.NewCommonRequest() + + getEndpointRequest.Product = "Location" + getEndpointRequest.Version = "2015-06-12" + getEndpointRequest.ApiName = "DescribeEndpoints" + getEndpointRequest.Domain = "location-readonly.aliyuncs.com" + getEndpointRequest.Method = "GET" + getEndpointRequest.Scheme = requests.HTTPS + + getEndpointRequest.QueryParams["Id"] = param.RegionId + getEndpointRequest.QueryParams["ServiceCode"] = param.LocationProduct + if len(param.LocationEndpointType) > 0 { + getEndpointRequest.QueryParams["Type"] = param.LocationEndpointType + } else { + getEndpointRequest.QueryParams["Type"] = "openAPI" + } + + response, err := param.CommonApi(getEndpointRequest) + if err != nil { + support = false + return + } + + if !response.IsSuccess() { + support = false + return + } + + var getEndpointResponse GetEndpointResponse + err = json.Unmarshal([]byte(response.GetHttpContentString()), &getEndpointResponse) + if err != nil { + support = false + return + } + + if !getEndpointResponse.Success || getEndpointResponse.Endpoints == nil { + support = false + return + } + if len(getEndpointResponse.Endpoints.Endpoint) <= 0 { + support = false + return + } + if len(getEndpointResponse.Endpoints.Endpoint[0].Endpoint) > 0 { + endpoint = getEndpointResponse.Endpoints.Endpoint[0].Endpoint + endpointCache.Set(cacheKey, endpoint) + lastClearTimePerProduct.Set(cacheKey, time.Now().Unix()) + support = true + return + } + + support = false + return +} + +// CheckCacheIsExpire ... +func CheckCacheIsExpire(cacheKey string) bool { + lastClearTime, ok := lastClearTimePerProduct.Get(cacheKey).(int64) + if !ok { + return true + } + + if lastClearTime <= 0 { + lastClearTime = time.Now().Unix() + lastClearTimePerProduct.Set(cacheKey, lastClearTime) + } + + now := time.Now().Unix() + elapsedTime := now - lastClearTime + if elapsedTime > EndpointCacheExpireTime { + return true + } + + return false +} + +// GetEndpointResponse ... +type GetEndpointResponse struct { + Endpoints *EndpointsObj + RequestId string + Success bool +} + +// EndpointsObj ... +type EndpointsObj struct { + Endpoint []EndpointObj +} + +// EndpointObj ... +type EndpointObj struct { + // Protocols map[string]string + Type string + Namespace string + Id string + SerivceCode string + Endpoint string +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/mapping_resolver.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/mapping_resolver.go new file mode 100644 index 0000000..a415a16 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/mapping_resolver.go @@ -0,0 +1,49 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package endpoints + +import ( + "fmt" + "strings" + "sync" +) + +const keyFormatter = "%s::%s" + +type EndpointMapping struct { + sync.RWMutex + endpoint map[string]string +} + +var endpointMapping = EndpointMapping{endpoint: make(map[string]string)} + +// AddEndpointMapping use productId and regionId as key to store the endpoint into inner map +// when using the same productId and regionId as key, the endpoint will be covered. +func AddEndpointMapping(regionId, productId, endpoint string) (err error) { + key := fmt.Sprintf(keyFormatter, strings.ToLower(regionId), strings.ToLower(productId)) + endpointMapping.Lock() + endpointMapping.endpoint[key] = endpoint + endpointMapping.Unlock() + return nil +} + +// GetEndpointFromMap use Product and RegionId as key to find endpoint from inner map +func GetEndpointFromMap(regionId, productId string) string { + key := fmt.Sprintf(keyFormatter, strings.ToLower(regionId), strings.ToLower(productId)) + endpointMapping.RLock() + endpoint := endpointMapping.endpoint[key] + endpointMapping.RUnlock() + return endpoint +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/resolver.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/resolver.go new file mode 100644 index 0000000..a73b8b1 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/resolver.go @@ -0,0 +1,96 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package endpoints + +import ( + "encoding/json" + "fmt" + "sync" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +var debug utils.Debug + +func init() { + debug = utils.Init("sdk") +} + +const ( + ResolveEndpointUserGuideLink = "" +) + +var once sync.Once +var resolvers []Resolver + +type Resolver interface { + TryResolve(param *ResolveParam) (endpoint string, support bool, err error) + GetName() (name string) +} + +// Resolve resolve endpoint with params +// It will resolve with each supported resolver until anyone resolved +func Resolve(param *ResolveParam) (endpoint string, err error) { + supportedResolvers := getAllResolvers() + var lastErr error + for _, resolver := range supportedResolvers { + endpoint, supported, resolveErr := resolver.TryResolve(param) + if resolveErr != nil { + lastErr = resolveErr + } + + if supported { + debug("resolve endpoint with %s\n", param) + debug("\t%s by resolver(%s)\n", endpoint, resolver.GetName()) + return endpoint, nil + } + } + + // not support + errorMsg := fmt.Sprintf(errors.CanNotResolveEndpointErrorMessage, param, ResolveEndpointUserGuideLink) + err = errors.NewClientError(errors.CanNotResolveEndpointErrorCode, errorMsg, lastErr) + return +} + +func getAllResolvers() []Resolver { + once.Do(func() { + resolvers = []Resolver{ + &LocationResolver{}, + &LocalRegionalResolver{}, + &LocalGlobalResolver{}, + } + }) + return resolvers +} + +type ResolveParam struct { + Domain string + Product string + RegionId string + LocationProduct string + LocationEndpointType string + CommonApi func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) `json:"-"` +} + +func (param *ResolveParam) String() string { + jsonBytes, err := json.Marshal(param) + if err != nil { + return fmt.Sprint("ResolveParam.String() process error:", err) + } + return string(jsonBytes) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/client_error.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/client_error.go new file mode 100644 index 0000000..1e2d9c0 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/client_error.go @@ -0,0 +1,92 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package errors + +import "fmt" + +const ( + DefaultClientErrorStatus = 400 + DefaultClientErrorCode = "SDK.ClientError" + + UnsupportedCredentialErrorCode = "SDK.UnsupportedCredential" + UnsupportedCredentialErrorMessage = "Specified credential (type = %s) is not supported, please check" + + CanNotResolveEndpointErrorCode = "SDK.CanNotResolveEndpoint" + CanNotResolveEndpointErrorMessage = "Can not resolve endpoint(param = %s), please check your accessKey with secret, and read the user guide\n %s" + + UnsupportedParamPositionErrorCode = "SDK.UnsupportedParamPosition" + UnsupportedParamPositionErrorMessage = "Specified param position (%s) is not supported, please upgrade sdk and retry" + + AsyncFunctionNotEnabledCode = "SDK.AsyncFunctionNotEnabled" + AsyncFunctionNotEnabledMessage = "Async function is not enabled in client, please invoke 'client.EnableAsync' function" + + UnknownRequestTypeErrorCode = "SDK.UnknownRequestType" + UnknownRequestTypeErrorMessage = "Unknown Request Type: %s" + + MissingParamErrorCode = "SDK.MissingParam" + InvalidParamErrorCode = "SDK.InvalidParam" + + JsonUnmarshalErrorCode = "SDK.JsonUnmarshalError" + JsonUnmarshalErrorMessage = "Failed to unmarshal response, but you can get the data via response.GetHttpStatusCode() and response.GetHttpContentString()" + + TimeoutErrorCode = "SDK.TimeoutError" + TimeoutErrorMessage = "The request timed out %s times(%s for retry), perhaps we should have the threshold raised a little?" +) + +type ClientError struct { + errorCode string + message string + originError error +} + +func NewClientError(errorCode, message string, originErr error) Error { + return &ClientError{ + errorCode: errorCode, + message: message, + originError: originErr, + } +} + +func (err *ClientError) Error() string { + clientErrMsg := fmt.Sprintf("[%s] %s", err.ErrorCode(), err.message) + if err.originError != nil { + return clientErrMsg + "\ncaused by:\n" + err.originError.Error() + } + return clientErrMsg +} + +func (err *ClientError) OriginError() error { + return err.originError +} + +func (*ClientError) HttpStatus() int { + return DefaultClientErrorStatus +} + +func (err *ClientError) ErrorCode() string { + if err.errorCode == "" { + return DefaultClientErrorCode + } else { + return err.errorCode + } +} + +func (err *ClientError) Message() string { + return err.message +} + +func (err *ClientError) String() string { + return err.Error() +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/error.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/error.go new file mode 100644 index 0000000..49962f3 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/error.go @@ -0,0 +1,23 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package errors + +type Error interface { + error + HttpStatus() int + ErrorCode() string + Message() string + OriginError() error +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/server_error.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/server_error.go new file mode 100644 index 0000000..1b78104 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/server_error.go @@ -0,0 +1,123 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package errors + +import ( + "encoding/json" + "fmt" + + "github.com/jmespath/go-jmespath" +) + +var wrapperList = []ServerErrorWrapper{ + &SignatureDostNotMatchWrapper{}, +} + +type ServerError struct { + httpStatus int + requestId string + hostId string + errorCode string + recommend string + message string + comment string +} + +type ServerErrorWrapper interface { + tryWrap(error *ServerError, wrapInfo map[string]string) bool +} + +func (err *ServerError) Error() string { + return fmt.Sprintf("SDK.ServerError\nErrorCode: %s\nRecommend: %s\nRequestId: %s\nMessage: %s", + err.errorCode, err.comment+err.recommend, err.requestId, err.message) +} + +func NewServerError(httpStatus int, responseContent, comment string) Error { + result := &ServerError{ + httpStatus: httpStatus, + message: responseContent, + comment: comment, + } + + var data interface{} + err := json.Unmarshal([]byte(responseContent), &data) + if err == nil { + requestId, _ := jmespath.Search("RequestId", data) + hostId, _ := jmespath.Search("HostId", data) + errorCode, _ := jmespath.Search("Code", data) + recommend, _ := jmespath.Search("Recommend", data) + message, _ := jmespath.Search("Message", data) + + if requestId != nil { + result.requestId = requestId.(string) + } + if hostId != nil { + result.hostId = hostId.(string) + } + if errorCode != nil { + result.errorCode = errorCode.(string) + } + if recommend != nil { + result.recommend = recommend.(string) + } + if message != nil { + result.message = message.(string) + } + } + + return result +} + +func WrapServerError(originError *ServerError, wrapInfo map[string]string) *ServerError { + for _, wrapper := range wrapperList { + ok := wrapper.tryWrap(originError, wrapInfo) + if ok { + return originError + } + } + return originError +} + +func (err *ServerError) HttpStatus() int { + return err.httpStatus +} + +func (err *ServerError) ErrorCode() string { + return err.errorCode +} + +func (err *ServerError) Message() string { + return err.message +} + +func (err *ServerError) OriginError() error { + return nil +} + +func (err *ServerError) HostId() string { + return err.hostId +} + +func (err *ServerError) RequestId() string { + return err.requestId +} + +func (err *ServerError) Recommend() string { + return err.recommend +} + +func (err *ServerError) Comment() string { + return err.comment +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/signature_does_not_match_wrapper.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/signature_does_not_match_wrapper.go new file mode 100644 index 0000000..4b09d7d --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/signature_does_not_match_wrapper.go @@ -0,0 +1,45 @@ +package errors + +import ( + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +const SignatureDostNotMatchErrorCode = "SignatureDoesNotMatch" +const IncompleteSignatureErrorCode = "IncompleteSignature" +const MessageContain = "server string to sign is:" + +var debug utils.Debug + +func init() { + debug = utils.Init("sdk") +} + +type SignatureDostNotMatchWrapper struct { +} + +func (*SignatureDostNotMatchWrapper) tryWrap(error *ServerError, wrapInfo map[string]string) (ok bool) { + clientStringToSign := wrapInfo["StringToSign"] + if (error.errorCode == SignatureDostNotMatchErrorCode || error.errorCode == IncompleteSignatureErrorCode) && clientStringToSign != "" { + message := error.message + if strings.Contains(message, MessageContain) { + str := strings.Split(message, MessageContain) + serverStringToSign := str[1] + + if clientStringToSign == serverStringToSign { + // user secret is error + error.recommend = "InvalidAccessKeySecret: Please check you AccessKeySecret" + } else { + debug("Client StringToSign: %s", clientStringToSign) + debug("Server StringToSign: %s", serverStringToSign) + error.recommend = "This may be a bug with the SDK and we hope you can submit this question in the " + + "github issue(https://github.com/aliyun/alibaba-cloud-sdk-go/issues), thanks very much" + } + } + ok = true + return + } + ok = false + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/logger.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/logger.go new file mode 100644 index 0000000..a01a7bb --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/logger.go @@ -0,0 +1,116 @@ +package sdk + +import ( + "encoding/json" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" + "io" + "log" + "os" + "strings" + "time" +) + +var logChannel string +var defaultChannel = "AlibabaCloud" + +type Logger struct { + *log.Logger + formatTemplate string + isOpen bool + lastLogMsg string +} + +var defaultLoggerTemplate = `{time} {channel}: "{method} {uri} HTTP/{version}" {code} {cost} {hostname}` +var loggerParam = []string{"{time}", "{start_time}", "{ts}", "{channel}", "{pid}", "{host}", "{method}", "{uri}", "{version}", "{target}", "{hostname}", "{code}", "{error}", "{req_headers}", "{res_body}", "{res_headers}", "{cost}"} + +func initLogMsg(fieldMap map[string]string) { + for _, value := range loggerParam { + fieldMap[value] = "" + } +} + +func (client *Client) GetLogger() *Logger { + return client.logger +} + +func (client *Client) GetLoggerMsg() string { + if client.logger == nil { + client.SetLogger("", "", os.Stdout, "") + } + return client.logger.lastLogMsg +} + +func (client *Client) SetLogger(level string, channel string, out io.Writer, template string) { + if level == "" { + level = "info" + } + + logChannel = "AlibabaCloud" + if channel != "" { + logChannel = channel + } + log := log.New(out, "["+strings.ToUpper(level)+"]", log.Lshortfile) + if template == "" { + template = defaultLoggerTemplate + } + + client.logger = &Logger{ + Logger: log, + formatTemplate: template, + isOpen: true, + } +} + +func (client *Client) OpenLogger() { + if client.logger == nil { + client.SetLogger("", "", os.Stdout, "") + } + client.logger.isOpen = true +} + +func (client *Client) CloseLogger() { + if client.logger != nil { + client.logger.isOpen = false + } +} + +func (client *Client) SetTemplate(template string) { + if client.logger == nil { + client.SetLogger("", "", os.Stdout, "") + } + client.logger.formatTemplate = template +} + +func (client *Client) GetTemplate() string { + if client.logger == nil { + client.SetLogger("", "", os.Stdout, "") + } + return client.logger.formatTemplate +} + +func TransToString(object interface{}) string { + byt, err := json.Marshal(object) + if err != nil { + return "" + } + return string(byt) +} + +func (client *Client) printLog(fieldMap map[string]string, err error) { + if err != nil { + fieldMap["{error}"] = err.Error() + } + fieldMap["{time}"] = time.Now().Format("2006-01-02 15:04:05") + fieldMap["{ts}"] = utils.GetTimeInFormatISO8601() + fieldMap["{channel}"] = logChannel + if client.logger != nil { + logMsg := client.logger.formatTemplate + for key, value := range fieldMap { + logMsg = strings.Replace(logMsg, key, value, -1) + } + client.logger.lastLogMsg = logMsg + if client.logger.isOpen == true { + client.logger.Output(2, logMsg) + } + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go new file mode 100644 index 0000000..19890cf --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go @@ -0,0 +1,442 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package requests + +import ( + "encoding/json" + "fmt" + "io" + "reflect" + "strconv" + "strings" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" +) + +const ( + RPC = "RPC" + ROA = "ROA" + + HTTP = "HTTP" + HTTPS = "HTTPS" + + DefaultHttpPort = "80" + + GET = "GET" + PUT = "PUT" + POST = "POST" + DELETE = "DELETE" + HEAD = "HEAD" + OPTIONS = "OPTIONS" + + Json = "application/json" + Xml = "application/xml" + Raw = "application/octet-stream" + Form = "application/x-www-form-urlencoded" + + Header = "Header" + Query = "Query" + Body = "Body" + Path = "Path" + + HeaderSeparator = "\n" +) + +// interface +type AcsRequest interface { + GetScheme() string + GetMethod() string + GetDomain() string + GetPort() string + GetRegionId() string + GetHeaders() map[string]string + GetQueryParams() map[string]string + GetFormParams() map[string]string + GetContent() []byte + GetBodyReader() io.Reader + GetStyle() string + GetProduct() string + GetVersion() string + SetVersion(version string) + GetActionName() string + GetAcceptFormat() string + GetLocationServiceCode() string + GetLocationEndpointType() string + GetReadTimeout() time.Duration + GetConnectTimeout() time.Duration + SetReadTimeout(readTimeout time.Duration) + SetConnectTimeout(connectTimeout time.Duration) + SetHTTPSInsecure(isInsecure bool) + GetHTTPSInsecure() *bool + + GetUserAgent() map[string]string + + SetStringToSign(stringToSign string) + GetStringToSign() string + + SetDomain(domain string) + SetContent(content []byte) + SetScheme(scheme string) + BuildUrl() string + BuildQueries() string + + addHeaderParam(key, value string) + addQueryParam(key, value string) + addFormParam(key, value string) + addPathParam(key, value string) +} + +// base class +type baseRequest struct { + Scheme string + Method string + Domain string + Port string + RegionId string + ReadTimeout time.Duration + ConnectTimeout time.Duration + isInsecure *bool + + userAgent map[string]string + product string + version string + + actionName string + + AcceptFormat string + + QueryParams map[string]string + Headers map[string]string + FormParams map[string]string + Content []byte + + locationServiceCode string + locationEndpointType string + + queries string + + stringToSign string +} + +func (request *baseRequest) GetQueryParams() map[string]string { + return request.QueryParams +} + +func (request *baseRequest) GetFormParams() map[string]string { + return request.FormParams +} + +func (request *baseRequest) GetReadTimeout() time.Duration { + return request.ReadTimeout +} + +func (request *baseRequest) GetConnectTimeout() time.Duration { + return request.ConnectTimeout +} + +func (request *baseRequest) SetReadTimeout(readTimeout time.Duration) { + request.ReadTimeout = readTimeout +} + +func (request *baseRequest) SetConnectTimeout(connectTimeout time.Duration) { + request.ConnectTimeout = connectTimeout +} + +func (request *baseRequest) GetHTTPSInsecure() *bool { + return request.isInsecure +} + +func (request *baseRequest) SetHTTPSInsecure(isInsecure bool) { + request.isInsecure = &isInsecure +} + +func (request *baseRequest) GetContent() []byte { + return request.Content +} + +func (request *baseRequest) SetVersion(version string) { + request.version = version +} + +func (request *baseRequest) GetVersion() string { + return request.version +} + +func (request *baseRequest) GetActionName() string { + return request.actionName +} + +func (request *baseRequest) SetContent(content []byte) { + request.Content = content +} + +func (request *baseRequest) GetUserAgent() map[string]string { + return request.userAgent +} + +func (request *baseRequest) AppendUserAgent(key, value string) { + newkey := true + if request.userAgent == nil { + request.userAgent = make(map[string]string) + } + if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" { + for tag, _ := range request.userAgent { + if tag == key { + request.userAgent[tag] = value + newkey = false + } + } + if newkey { + request.userAgent[key] = value + } + } +} + +func (request *baseRequest) addHeaderParam(key, value string) { + request.Headers[key] = value +} + +func (request *baseRequest) addQueryParam(key, value string) { + request.QueryParams[key] = value +} + +func (request *baseRequest) addFormParam(key, value string) { + request.FormParams[key] = value +} + +func (request *baseRequest) GetAcceptFormat() string { + return request.AcceptFormat +} + +func (request *baseRequest) GetLocationServiceCode() string { + return request.locationServiceCode +} + +func (request *baseRequest) GetLocationEndpointType() string { + return request.locationEndpointType +} + +func (request *baseRequest) GetProduct() string { + return request.product +} + +func (request *baseRequest) GetScheme() string { + return request.Scheme +} + +func (request *baseRequest) SetScheme(scheme string) { + request.Scheme = scheme +} + +func (request *baseRequest) GetMethod() string { + return request.Method +} + +func (request *baseRequest) GetDomain() string { + return request.Domain +} + +func (request *baseRequest) SetDomain(host string) { + request.Domain = host +} + +func (request *baseRequest) GetPort() string { + return request.Port +} + +func (request *baseRequest) GetRegionId() string { + return request.RegionId +} + +func (request *baseRequest) GetHeaders() map[string]string { + return request.Headers +} + +func (request *baseRequest) SetContentType(contentType string) { + request.addHeaderParam("Content-Type", contentType) +} + +func (request *baseRequest) GetContentType() (contentType string, contains bool) { + contentType, contains = request.Headers["Content-Type"] + return +} + +func (request *baseRequest) SetStringToSign(stringToSign string) { + request.stringToSign = stringToSign +} + +func (request *baseRequest) GetStringToSign() string { + return request.stringToSign +} + +func defaultBaseRequest() (request *baseRequest) { + request = &baseRequest{ + Scheme: "", + AcceptFormat: "JSON", + Method: GET, + QueryParams: make(map[string]string), + Headers: map[string]string{ + "x-sdk-client": "golang/1.0.0", + "x-sdk-invoke-type": "normal", + "Accept-Encoding": "identity", + }, + FormParams: make(map[string]string), + } + return +} + +func InitParams(request AcsRequest) (err error) { + requestValue := reflect.ValueOf(request).Elem() + err = flatRepeatedList(requestValue, request, "", "") + return +} + +func flatRepeatedList(dataValue reflect.Value, request AcsRequest, position, prefix string) (err error) { + dataType := dataValue.Type() + for i := 0; i < dataType.NumField(); i++ { + field := dataType.Field(i) + name, containsNameTag := field.Tag.Lookup("name") + fieldPosition := position + if fieldPosition == "" { + fieldPosition, _ = field.Tag.Lookup("position") + } + typeTag, containsTypeTag := field.Tag.Lookup("type") + if containsNameTag { + if !containsTypeTag { + // simple param + key := prefix + name + value := dataValue.Field(i).String() + if dataValue.Field(i).Kind().String() == "map" { + byt, _ := json.Marshal(dataValue.Field(i).Interface()) + value = string(byt) + if value == "null" { + value = "" + } + } + err = addParam(request, fieldPosition, key, value) + if err != nil { + return + } + } else if typeTag == "Repeated" { + // repeated param + err = handleRepeatedParams(request, dataValue, prefix, name, fieldPosition, i) + if err != nil { + return + } + } else if typeTag == "Struct" { + err = handleStruct(request, dataValue, prefix, name, fieldPosition, i) + if err != nil { + return + } + } + } + } + return +} + +func handleRepeatedParams(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) { + repeatedFieldValue := dataValue.Field(index) + if repeatedFieldValue.Kind() != reflect.Slice { + // possible value: {"[]string", "*[]struct"}, we must call Elem() in the last condition + repeatedFieldValue = repeatedFieldValue.Elem() + } + if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() { + for m := 0; m < repeatedFieldValue.Len(); m++ { + elementValue := repeatedFieldValue.Index(m) + key := prefix + name + "." + strconv.Itoa(m+1) + if elementValue.Type().Kind().String() == "string" { + value := elementValue.String() + err = addParam(request, fieldPosition, key, value) + if err != nil { + return + } + } else { + err = flatRepeatedList(elementValue, request, fieldPosition, key+".") + if err != nil { + return + } + } + } + } + return nil +} + +func handleStruct(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) { + valueField := dataValue.Field(index) + if valueField.IsValid() && valueField.String() != "" { + valueFieldType := valueField.Type() + for m := 0; m < valueFieldType.NumField(); m++ { + fieldName := valueFieldType.Field(m).Name + elementValue := valueField.FieldByName(fieldName) + key := prefix + name + "." + fieldName + if elementValue.Type().String() == "[]string" { + if elementValue.IsNil() { + continue + } + for j := 0; j < elementValue.Len(); j++ { + err = addParam(request, fieldPosition, key+"."+strconv.Itoa(j+1), elementValue.Index(j).String()) + if err != nil { + return + } + } + } else { + if elementValue.Type().Kind().String() == "string" { + value := elementValue.String() + err = addParam(request, fieldPosition, key, value) + if err != nil { + return + } + } else if elementValue.Type().Kind().String() == "struct" { + err = flatRepeatedList(elementValue, request, fieldPosition, key+".") + if err != nil { + return + } + } else if !elementValue.IsNil() { + repeatedFieldValue := elementValue.Elem() + if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() { + for m := 0; m < repeatedFieldValue.Len(); m++ { + elementValue := repeatedFieldValue.Index(m) + err = flatRepeatedList(elementValue, request, fieldPosition, key+"."+strconv.Itoa(m+1)+".") + if err != nil { + return + } + } + } + } + } + } + } + return nil +} + +func addParam(request AcsRequest, position, name, value string) (err error) { + if len(value) > 0 { + switch position { + case Header: + request.addHeaderParam(name, value) + case Query: + request.addQueryParam(name, value) + case Path: + request.addPathParam(name, value) + case Body: + request.addFormParam(name, value) + default: + errMsg := fmt.Sprintf(errors.UnsupportedParamPositionErrorMessage, position) + err = errors.NewClientError(errors.UnsupportedParamPositionErrorCode, errMsg, nil) + } + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/common_request.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/common_request.go new file mode 100644 index 0000000..80c1700 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/common_request.go @@ -0,0 +1,108 @@ +package requests + +import ( + "bytes" + "fmt" + "io" + "sort" + "strings" +) + +type CommonRequest struct { + *baseRequest + + Version string + ApiName string + Product string + ServiceCode string + + // roa params + PathPattern string + PathParams map[string]string + + Ontology AcsRequest +} + +func NewCommonRequest() (request *CommonRequest) { + request = &CommonRequest{ + baseRequest: defaultBaseRequest(), + } + request.Headers["x-sdk-invoke-type"] = "common" + request.PathParams = make(map[string]string) + return +} + +func (request *CommonRequest) String() string { + request.TransToAcsRequest() + + resultBuilder := bytes.Buffer{} + + mapOutput := func(m map[string]string) { + if len(m) > 0 { + sortedKeys := make([]string, 0) + for k := range m { + sortedKeys = append(sortedKeys, k) + } + + // sort 'string' key in increasing order + sort.Strings(sortedKeys) + + for _, key := range sortedKeys { + resultBuilder.WriteString(key + ": " + m[key] + "\n") + } + } + } + + // Request Line + resultBuilder.WriteString(fmt.Sprintf("%s %s %s/1.1\n", request.Method, request.BuildQueries(), strings.ToUpper(request.Scheme))) + + // Headers + resultBuilder.WriteString("Host" + ": " + request.Domain + "\n") + mapOutput(request.Headers) + + resultBuilder.WriteString("\n") + // Body + if len(request.Content) > 0 { + resultBuilder.WriteString(string(request.Content) + "\n") + } else { + mapOutput(request.FormParams) + } + + return resultBuilder.String() +} + +func (request *CommonRequest) TransToAcsRequest() { + if len(request.PathPattern) > 0 { + roaRequest := &RoaRequest{} + roaRequest.initWithCommonRequest(request) + request.Ontology = roaRequest + } else { + rpcRequest := &RpcRequest{} + rpcRequest.baseRequest = request.baseRequest + rpcRequest.product = request.Product + rpcRequest.version = request.Version + rpcRequest.locationServiceCode = request.ServiceCode + rpcRequest.actionName = request.ApiName + request.Ontology = rpcRequest + } +} + +func (request *CommonRequest) BuildUrl() string { + return request.Ontology.BuildUrl() +} + +func (request *CommonRequest) BuildQueries() string { + return request.Ontology.BuildQueries() +} + +func (request *CommonRequest) GetBodyReader() io.Reader { + return request.Ontology.GetBodyReader() +} + +func (request *CommonRequest) GetStyle() string { + return request.Ontology.GetStyle() +} + +func (request *CommonRequest) addPathParam(key, value string) { + request.PathParams[key] = value +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/roa_request.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/roa_request.go new file mode 100644 index 0000000..70b856e --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/roa_request.go @@ -0,0 +1,152 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package requests + +import ( + "bytes" + "fmt" + "io" + "net/url" + "sort" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +type RoaRequest struct { + *baseRequest + pathPattern string + PathParams map[string]string +} + +func (*RoaRequest) GetStyle() string { + return ROA +} + +func (request *RoaRequest) GetBodyReader() io.Reader { + if request.FormParams != nil && len(request.FormParams) > 0 { + formString := utils.GetUrlFormedMap(request.FormParams) + return strings.NewReader(formString) + } else if len(request.Content) > 0 { + return bytes.NewReader(request.Content) + } else { + return nil + } +} + +// for sign method, need not url encoded +func (request *RoaRequest) BuildQueries() string { + return request.buildQueries() +} + +func (request *RoaRequest) buildPath() string { + path := request.pathPattern + for key, value := range request.PathParams { + path = strings.Replace(path, "["+key+"]", value, 1) + } + return path +} + +func (request *RoaRequest) buildQueries() string { + // replace path params with value + path := request.buildPath() + queryParams := request.QueryParams + // sort QueryParams by key + var queryKeys []string + for key := range queryParams { + queryKeys = append(queryKeys, key) + } + sort.Strings(queryKeys) + + // append urlBuilder + urlBuilder := bytes.Buffer{} + urlBuilder.WriteString(path) + if len(queryKeys) > 0 { + urlBuilder.WriteString("?") + } + for i := 0; i < len(queryKeys); i++ { + queryKey := queryKeys[i] + urlBuilder.WriteString(queryKey) + if value := queryParams[queryKey]; len(value) > 0 { + urlBuilder.WriteString("=") + urlBuilder.WriteString(value) + } + if i < len(queryKeys)-1 { + urlBuilder.WriteString("&") + } + } + result := urlBuilder.String() + result = popStandardUrlencode(result) + return result +} + +func (request *RoaRequest) buildQueryString() string { + queryParams := request.QueryParams + // sort QueryParams by key + q := url.Values{} + for key, value := range queryParams { + q.Add(key, value) + } + return q.Encode() +} + +func popStandardUrlencode(stringToSign string) (result string) { + result = strings.Replace(stringToSign, "+", "%20", -1) + result = strings.Replace(result, "*", "%2A", -1) + result = strings.Replace(result, "%7E", "~", -1) + return +} + +func (request *RoaRequest) BuildUrl() string { + // for network trans, need url encoded + scheme := strings.ToLower(request.Scheme) + domain := request.Domain + port := request.Port + path := request.buildPath() + url := fmt.Sprintf("%s://%s:%s%s", scheme, domain, port, path) + querystring := request.buildQueryString() + if len(querystring) > 0 { + url = fmt.Sprintf("%s?%s", url, querystring) + } + return url +} + +func (request *RoaRequest) addPathParam(key, value string) { + request.PathParams[key] = value +} + +func (request *RoaRequest) InitWithApiInfo(product, version, action, uriPattern, serviceCode, endpointType string) { + request.baseRequest = defaultBaseRequest() + request.PathParams = make(map[string]string) + request.Headers["x-acs-version"] = version + request.pathPattern = uriPattern + request.locationServiceCode = serviceCode + request.locationEndpointType = endpointType + request.product = product + //request.version = version + request.actionName = action +} + +func (request *RoaRequest) initWithCommonRequest(commonRequest *CommonRequest) { + request.baseRequest = commonRequest.baseRequest + request.PathParams = commonRequest.PathParams + request.product = commonRequest.Product + //request.version = commonRequest.Version + request.Headers["x-acs-version"] = commonRequest.Version + request.actionName = commonRequest.ApiName + request.pathPattern = commonRequest.PathPattern + request.locationServiceCode = commonRequest.ServiceCode + request.locationEndpointType = "" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/rpc_request.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/rpc_request.go new file mode 100644 index 0000000..01be6fd --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/rpc_request.go @@ -0,0 +1,79 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package requests + +import ( + "fmt" + "io" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +type RpcRequest struct { + *baseRequest +} + +func (request *RpcRequest) init() { + request.baseRequest = defaultBaseRequest() + request.Method = POST +} + +func (*RpcRequest) GetStyle() string { + return RPC +} + +func (request *RpcRequest) GetBodyReader() io.Reader { + if request.FormParams != nil && len(request.FormParams) > 0 { + formString := utils.GetUrlFormedMap(request.FormParams) + return strings.NewReader(formString) + } else { + return strings.NewReader("") + } +} + +func (request *RpcRequest) BuildQueries() string { + request.queries = "/?" + utils.GetUrlFormedMap(request.QueryParams) + return request.queries +} + +func (request *RpcRequest) BuildUrl() string { + url := fmt.Sprintf("%s://%s", strings.ToLower(request.Scheme), request.Domain) + if len(request.Port) > 0 { + url = fmt.Sprintf("%s:%s", url, request.Port) + } + return url + request.BuildQueries() +} + +func (request *RpcRequest) GetVersion() string { + return request.version +} + +func (request *RpcRequest) GetActionName() string { + return request.actionName +} + +func (request *RpcRequest) addPathParam(key, value string) { + panic("not support") +} + +func (request *RpcRequest) InitWithApiInfo(product, version, action, serviceCode, endpointType string) { + request.init() + request.product = product + request.version = version + request.actionName = action + request.locationServiceCode = serviceCode + request.locationEndpointType = endpointType +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/types.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/types.go new file mode 100644 index 0000000..28af63e --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/types.go @@ -0,0 +1,53 @@ +package requests + +import "strconv" + +type Integer string + +func NewInteger(integer int) Integer { + return Integer(strconv.Itoa(integer)) +} + +func (integer Integer) HasValue() bool { + return integer != "" +} + +func (integer Integer) GetValue() (int, error) { + return strconv.Atoi(string(integer)) +} + +func NewInteger64(integer int64) Integer { + return Integer(strconv.FormatInt(integer, 10)) +} + +func (integer Integer) GetValue64() (int64, error) { + return strconv.ParseInt(string(integer), 10, 0) +} + +type Boolean string + +func NewBoolean(bool bool) Boolean { + return Boolean(strconv.FormatBool(bool)) +} + +func (boolean Boolean) HasValue() bool { + return boolean != "" +} + +func (boolean Boolean) GetValue() (bool, error) { + return strconv.ParseBool(string(boolean)) +} + +type Float string + +func NewFloat(f float64) Float { + return Float(strconv.FormatFloat(f, 'f', 6, 64)) +} + +func (float Float) HasValue() bool { + return float != "" +} + +func (float Float) GetValue() (float64, error) { + return strconv.ParseFloat(string(float), 64) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/json_parser.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/json_parser.go new file mode 100644 index 0000000..36604fe --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/json_parser.go @@ -0,0 +1,328 @@ +package responses + +import ( + "encoding/json" + "io" + "math" + "strconv" + "strings" + "unsafe" + + jsoniter "github.com/json-iterator/go" +) + +const maxUint = ^uint(0) +const maxInt = int(maxUint >> 1) +const minInt = -maxInt - 1 + +var jsonParser jsoniter.API + +func init() { + registerBetterFuzzyDecoder() + jsonParser = jsoniter.Config{ + EscapeHTML: true, + SortMapKeys: true, + ValidateJsonRawMessage: true, + CaseSensitive: true, + }.Froze() +} + +func registerBetterFuzzyDecoder() { + jsoniter.RegisterTypeDecoder("string", &nullableFuzzyStringDecoder{}) + jsoniter.RegisterTypeDecoder("bool", &fuzzyBoolDecoder{}) + jsoniter.RegisterTypeDecoder("float32", &nullableFuzzyFloat32Decoder{}) + jsoniter.RegisterTypeDecoder("float64", &nullableFuzzyFloat64Decoder{}) + jsoniter.RegisterTypeDecoder("int", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(maxInt) || val < float64(minInt) { + iter.ReportError("fuzzy decode int", "exceed range") + return + } + *((*int)(ptr)) = int(val) + } else { + *((*int)(ptr)) = iter.ReadInt() + } + }}) + jsoniter.RegisterTypeDecoder("uint", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(maxUint) || val < 0 { + iter.ReportError("fuzzy decode uint", "exceed range") + return + } + *((*uint)(ptr)) = uint(val) + } else { + *((*uint)(ptr)) = iter.ReadUint() + } + }}) + jsoniter.RegisterTypeDecoder("int8", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxInt8) || val < float64(math.MinInt8) { + iter.ReportError("fuzzy decode int8", "exceed range") + return + } + *((*int8)(ptr)) = int8(val) + } else { + *((*int8)(ptr)) = iter.ReadInt8() + } + }}) + jsoniter.RegisterTypeDecoder("uint8", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxUint8) || val < 0 { + iter.ReportError("fuzzy decode uint8", "exceed range") + return + } + *((*uint8)(ptr)) = uint8(val) + } else { + *((*uint8)(ptr)) = iter.ReadUint8() + } + }}) + jsoniter.RegisterTypeDecoder("int16", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxInt16) || val < float64(math.MinInt16) { + iter.ReportError("fuzzy decode int16", "exceed range") + return + } + *((*int16)(ptr)) = int16(val) + } else { + *((*int16)(ptr)) = iter.ReadInt16() + } + }}) + jsoniter.RegisterTypeDecoder("uint16", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxUint16) || val < 0 { + iter.ReportError("fuzzy decode uint16", "exceed range") + return + } + *((*uint16)(ptr)) = uint16(val) + } else { + *((*uint16)(ptr)) = iter.ReadUint16() + } + }}) + jsoniter.RegisterTypeDecoder("int32", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxInt32) || val < float64(math.MinInt32) { + iter.ReportError("fuzzy decode int32", "exceed range") + return + } + *((*int32)(ptr)) = int32(val) + } else { + *((*int32)(ptr)) = iter.ReadInt32() + } + }}) + jsoniter.RegisterTypeDecoder("uint32", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxUint32) || val < 0 { + iter.ReportError("fuzzy decode uint32", "exceed range") + return + } + *((*uint32)(ptr)) = uint32(val) + } else { + *((*uint32)(ptr)) = iter.ReadUint32() + } + }}) + jsoniter.RegisterTypeDecoder("int64", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxInt64) || val < float64(math.MinInt64) { + iter.ReportError("fuzzy decode int64", "exceed range") + return + } + *((*int64)(ptr)) = int64(val) + } else { + *((*int64)(ptr)) = iter.ReadInt64() + } + }}) + jsoniter.RegisterTypeDecoder("uint64", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) { + if isFloat { + val := iter.ReadFloat64() + if val > float64(math.MaxUint64) || val < 0 { + iter.ReportError("fuzzy decode uint64", "exceed range") + return + } + *((*uint64)(ptr)) = uint64(val) + } else { + *((*uint64)(ptr)) = iter.ReadUint64() + } + }}) +} + +type nullableFuzzyStringDecoder struct { +} + +func (decoder *nullableFuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + switch valueType { + case jsoniter.NumberValue: + var number json.Number + iter.ReadVal(&number) + *((*string)(ptr)) = string(number) + case jsoniter.StringValue: + *((*string)(ptr)) = iter.ReadString() + case jsoniter.BoolValue: + *((*string)(ptr)) = strconv.FormatBool(iter.ReadBool()) + case jsoniter.NilValue: + iter.ReadNil() + *((*string)(ptr)) = "" + default: + iter.ReportError("fuzzyStringDecoder", "not number or string or bool") + } +} + +type fuzzyBoolDecoder struct { +} + +func (decoder *fuzzyBoolDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + switch valueType { + case jsoniter.BoolValue: + *((*bool)(ptr)) = iter.ReadBool() + case jsoniter.NumberValue: + var number json.Number + iter.ReadVal(&number) + num, err := number.Int64() + if err != nil { + iter.ReportError("fuzzyBoolDecoder", "get value from json.number failed") + } + if num == 0 { + *((*bool)(ptr)) = false + } else { + *((*bool)(ptr)) = true + } + case jsoniter.StringValue: + strValue := strings.ToLower(iter.ReadString()) + if strValue == "true" { + *((*bool)(ptr)) = true + } else if strValue == "false" || strValue == "" { + *((*bool)(ptr)) = false + } else { + iter.ReportError("fuzzyBoolDecoder", "unsupported bool value: "+strValue) + } + case jsoniter.NilValue: + iter.ReadNil() + *((*bool)(ptr)) = false + default: + iter.ReportError("fuzzyBoolDecoder", "not number or string or nil") + } +} + +type nullableFuzzyIntegerDecoder struct { + fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) +} + +func (decoder *nullableFuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + var str string + switch valueType { + case jsoniter.NumberValue: + var number json.Number + iter.ReadVal(&number) + str = string(number) + case jsoniter.StringValue: + str = iter.ReadString() + // support empty string + if str == "" { + str = "0" + } + case jsoniter.BoolValue: + if iter.ReadBool() { + str = "1" + } else { + str = "0" + } + case jsoniter.NilValue: + iter.ReadNil() + str = "0" + default: + iter.ReportError("fuzzyIntegerDecoder", "not number or string") + } + newIter := iter.Pool().BorrowIterator([]byte(str)) + defer iter.Pool().ReturnIterator(newIter) + isFloat := strings.IndexByte(str, '.') != -1 + decoder.fun(isFloat, ptr, newIter) + if newIter.Error != nil && newIter.Error != io.EOF { + iter.Error = newIter.Error + } +} + +type nullableFuzzyFloat32Decoder struct { +} + +func (decoder *nullableFuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + var str string + switch valueType { + case jsoniter.NumberValue: + *((*float32)(ptr)) = iter.ReadFloat32() + case jsoniter.StringValue: + str = iter.ReadString() + // support empty string + if str == "" { + *((*float32)(ptr)) = 0 + return + } + newIter := iter.Pool().BorrowIterator([]byte(str)) + defer iter.Pool().ReturnIterator(newIter) + *((*float32)(ptr)) = newIter.ReadFloat32() + if newIter.Error != nil && newIter.Error != io.EOF { + iter.Error = newIter.Error + } + case jsoniter.BoolValue: + // support bool to float32 + if iter.ReadBool() { + *((*float32)(ptr)) = 1 + } else { + *((*float32)(ptr)) = 0 + } + case jsoniter.NilValue: + iter.ReadNil() + *((*float32)(ptr)) = 0 + default: + iter.ReportError("nullableFuzzyFloat32Decoder", "not number or string") + } +} + +type nullableFuzzyFloat64Decoder struct { +} + +func (decoder *nullableFuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { + valueType := iter.WhatIsNext() + var str string + switch valueType { + case jsoniter.NumberValue: + *((*float64)(ptr)) = iter.ReadFloat64() + case jsoniter.StringValue: + str = iter.ReadString() + // support empty string + if str == "" { + *((*float64)(ptr)) = 0 + return + } + newIter := iter.Pool().BorrowIterator([]byte(str)) + defer iter.Pool().ReturnIterator(newIter) + *((*float64)(ptr)) = newIter.ReadFloat64() + if newIter.Error != nil && newIter.Error != io.EOF { + iter.Error = newIter.Error + } + case jsoniter.BoolValue: + // support bool to float64 + if iter.ReadBool() { + *((*float64)(ptr)) = 1 + } else { + *((*float64)(ptr)) = 0 + } + case jsoniter.NilValue: + // support empty string + iter.ReadNil() + *((*float64)(ptr)) = 0 + default: + iter.ReportError("nullableFuzzyFloat64Decoder", "not number or string") + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/response.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/response.go new file mode 100644 index 0000000..53a156b --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/response.go @@ -0,0 +1,144 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package responses + +import ( + "bytes" + "encoding/xml" + "fmt" + "io/ioutil" + "net/http" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" +) + +type AcsResponse interface { + IsSuccess() bool + GetHttpStatus() int + GetHttpHeaders() map[string][]string + GetHttpContentString() string + GetHttpContentBytes() []byte + GetOriginHttpResponse() *http.Response + parseFromHttpResponse(httpResponse *http.Response) error +} + +// Unmarshal object from http response body to target Response +func Unmarshal(response AcsResponse, httpResponse *http.Response, format string) (err error) { + err = response.parseFromHttpResponse(httpResponse) + if err != nil { + return + } + if !response.IsSuccess() { + err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), "") + return + } + + if _, isCommonResponse := response.(*CommonResponse); isCommonResponse { + // common response need not unmarshal + return + } + + if len(response.GetHttpContentBytes()) == 0 { + return + } + + if strings.ToUpper(format) == "JSON" { + err = jsonParser.Unmarshal(response.GetHttpContentBytes(), response) + if err != nil { + err = errors.NewClientError(errors.JsonUnmarshalErrorCode, errors.JsonUnmarshalErrorMessage, err) + } + } else if strings.ToUpper(format) == "XML" { + err = xml.Unmarshal(response.GetHttpContentBytes(), response) + } + return +} + +type BaseResponse struct { + httpStatus int + httpHeaders map[string][]string + httpContentString string + httpContentBytes []byte + originHttpResponse *http.Response +} + +func (baseResponse *BaseResponse) GetHttpStatus() int { + return baseResponse.httpStatus +} + +func (baseResponse *BaseResponse) GetHttpHeaders() map[string][]string { + return baseResponse.httpHeaders +} + +func (baseResponse *BaseResponse) GetHttpContentString() string { + return baseResponse.httpContentString +} + +func (baseResponse *BaseResponse) GetHttpContentBytes() []byte { + return baseResponse.httpContentBytes +} + +func (baseResponse *BaseResponse) GetOriginHttpResponse() *http.Response { + return baseResponse.originHttpResponse +} + +func (baseResponse *BaseResponse) IsSuccess() bool { + if baseResponse.GetHttpStatus() >= 200 && baseResponse.GetHttpStatus() < 300 { + return true + } + + return false +} + +func (baseResponse *BaseResponse) parseFromHttpResponse(httpResponse *http.Response) (err error) { + defer httpResponse.Body.Close() + body, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + baseResponse.httpStatus = httpResponse.StatusCode + baseResponse.httpHeaders = httpResponse.Header + baseResponse.httpContentBytes = body + baseResponse.httpContentString = string(body) + baseResponse.originHttpResponse = httpResponse + return +} + +func (baseResponse *BaseResponse) String() string { + resultBuilder := bytes.Buffer{} + // statusCode + // resultBuilder.WriteString("\n") + resultBuilder.WriteString(fmt.Sprintf("%s %s\n", baseResponse.originHttpResponse.Proto, baseResponse.originHttpResponse.Status)) + // httpHeaders + //resultBuilder.WriteString("Headers:\n") + for key, value := range baseResponse.httpHeaders { + resultBuilder.WriteString(key + ": " + strings.Join(value, ";") + "\n") + } + resultBuilder.WriteString("\n") + // content + //resultBuilder.WriteString("Content:\n") + resultBuilder.WriteString(baseResponse.httpContentString + "\n") + return resultBuilder.String() +} + +type CommonResponse struct { + *BaseResponse +} + +func NewCommonResponse() (response *CommonResponse) { + return &CommonResponse{ + BaseResponse: &BaseResponse{}, + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/debug.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/debug.go new file mode 100644 index 0000000..09440d2 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/debug.go @@ -0,0 +1,36 @@ +package utils + +import ( + "fmt" + "os" + "strings" +) + +type Debug func(format string, v ...interface{}) + +var hookGetEnv = func() string { + return os.Getenv("DEBUG") +} + +var hookPrint = func(input string) { + fmt.Println(input) +} + +func Init(flag string) Debug { + enable := false + + env := hookGetEnv() + parts := strings.Split(env, ",") + for _, part := range parts { + if part == flag { + enable = true + break + } + } + + return func(format string, v ...interface{}) { + if enable { + hookPrint(fmt.Sprintf(format, v...)) + } + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go new file mode 100644 index 0000000..f8a3ad3 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go @@ -0,0 +1,141 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "crypto/md5" + "crypto/rand" + "encoding/base64" + "encoding/hex" + "hash" + rand2 "math/rand" + "net/url" + "reflect" + "strconv" + "time" +) + +type UUID [16]byte + +const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +func GetUUID() (uuidHex string) { + uuid := NewUUID() + uuidHex = hex.EncodeToString(uuid[:]) + return +} + +func RandStringBytes(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = letterBytes[rand2.Intn(len(letterBytes))] + } + return string(b) +} + +func GetMD5Base64(bytes []byte) (base64Value string) { + md5Ctx := md5.New() + md5Ctx.Write(bytes) + md5Value := md5Ctx.Sum(nil) + base64Value = base64.StdEncoding.EncodeToString(md5Value) + return +} + +func GetTimeInFormatISO8601() (timeStr string) { + gmt := time.FixedZone("GMT", 0) + + return time.Now().In(gmt).Format("2006-01-02T15:04:05Z") +} + +func GetTimeInFormatRFC2616() (timeStr string) { + gmt := time.FixedZone("GMT", 0) + + return time.Now().In(gmt).Format("Mon, 02 Jan 2006 15:04:05 GMT") +} + +func GetUrlFormedMap(source map[string]string) (urlEncoded string) { + urlEncoder := url.Values{} + for key, value := range source { + urlEncoder.Add(key, value) + } + urlEncoded = urlEncoder.Encode() + return +} + +func InitStructWithDefaultTag(bean interface{}) { + configType := reflect.TypeOf(bean) + for i := 0; i < configType.Elem().NumField(); i++ { + field := configType.Elem().Field(i) + defaultValue := field.Tag.Get("default") + if defaultValue == "" { + continue + } + setter := reflect.ValueOf(bean).Elem().Field(i) + switch field.Type.String() { + case "int": + intValue, _ := strconv.ParseInt(defaultValue, 10, 64) + setter.SetInt(intValue) + case "time.Duration": + intValue, _ := strconv.ParseInt(defaultValue, 10, 64) + setter.SetInt(intValue) + case "string": + setter.SetString(defaultValue) + case "bool": + boolValue, _ := strconv.ParseBool(defaultValue) + setter.SetBool(boolValue) + } + } +} + +func NewUUID() UUID { + ns := UUID{} + safeRandom(ns[:]) + u := newFromHash(md5.New(), ns, RandStringBytes(16)) + u[6] = (u[6] & 0x0f) | (byte(2) << 4) + u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) + + return u +} + +func newFromHash(h hash.Hash, ns UUID, name string) UUID { + u := UUID{} + h.Write(ns[:]) + h.Write([]byte(name)) + copy(u[:], h.Sum(nil)) + + return u +} + +func safeRandom(dest []byte) { + if _, err := rand.Read(dest); err != nil { + panic(err) + } +} + +func (u UUID) String() string { + buf := make([]byte, 36) + + hex.Encode(buf[0:8], u[0:4]) + buf[8] = '-' + hex.Encode(buf[9:13], u[4:6]) + buf[13] = '-' + hex.Encode(buf[14:18], u[6:8]) + buf[18] = '-' + hex.Encode(buf[19:23], u[8:10]) + buf[23] = '-' + hex.Encode(buf[24:], u[10:]) + + return string(buf) +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_sign.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_sign.go new file mode 100644 index 0000000..6e9456c --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_sign.go @@ -0,0 +1,118 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// AddSmsSign invokes the dysmsapi.AddSmsSign API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/addsmssign.html +func (client *Client) AddSmsSign(request *AddSmsSignRequest) (response *AddSmsSignResponse, err error) { + response = CreateAddSmsSignResponse() + err = client.DoAction(request, response) + return +} + +// AddSmsSignWithChan invokes the dysmsapi.AddSmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/addsmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) AddSmsSignWithChan(request *AddSmsSignRequest) (<-chan *AddSmsSignResponse, <-chan error) { + responseChan := make(chan *AddSmsSignResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.AddSmsSign(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// AddSmsSignWithCallback invokes the dysmsapi.AddSmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/addsmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) AddSmsSignWithCallback(request *AddSmsSignRequest, callback func(response *AddSmsSignResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *AddSmsSignResponse + var err error + defer close(result) + response, err = client.AddSmsSign(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// AddSmsSignRequest is the request struct for api AddSmsSign +type AddSmsSignRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + Remark string `position:"Query" name:"Remark"` + SignName string `position:"Query" name:"SignName"` + SignFileList *[]AddSmsSignSignFileList `position:"Query" name:"SignFileList" type:"Repeated"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + SignSource requests.Integer `position:"Query" name:"SignSource"` +} + +// AddSmsSignSignFileList is a repeated param struct in AddSmsSignRequest +type AddSmsSignSignFileList struct { + FileContents string `name:"FileContents"` + FileSuffix string `name:"FileSuffix"` +} + +// AddSmsSignResponse is the response struct for api AddSmsSign +type AddSmsSignResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + SignName string `json:"SignName" xml:"SignName"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateAddSmsSignRequest creates a request to invoke AddSmsSign API +func CreateAddSmsSignRequest() (request *AddSmsSignRequest) { + request = &AddSmsSignRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "AddSmsSign", "dysms", "openAPI") + return +} + +// CreateAddSmsSignResponse creates a response to parse from AddSmsSign response +func CreateAddSmsSignResponse() (response *AddSmsSignResponse) { + response = &AddSmsSignResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_template.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_template.go new file mode 100644 index 0000000..bd4f804 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/add_sms_template.go @@ -0,0 +1,112 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// AddSmsTemplate invokes the dysmsapi.AddSmsTemplate API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/addsmstemplate.html +func (client *Client) AddSmsTemplate(request *AddSmsTemplateRequest) (response *AddSmsTemplateResponse, err error) { + response = CreateAddSmsTemplateResponse() + err = client.DoAction(request, response) + return +} + +// AddSmsTemplateWithChan invokes the dysmsapi.AddSmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/addsmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) AddSmsTemplateWithChan(request *AddSmsTemplateRequest) (<-chan *AddSmsTemplateResponse, <-chan error) { + responseChan := make(chan *AddSmsTemplateResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.AddSmsTemplate(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// AddSmsTemplateWithCallback invokes the dysmsapi.AddSmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/addsmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) AddSmsTemplateWithCallback(request *AddSmsTemplateRequest, callback func(response *AddSmsTemplateResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *AddSmsTemplateResponse + var err error + defer close(result) + response, err = client.AddSmsTemplate(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// AddSmsTemplateRequest is the request struct for api AddSmsTemplate +type AddSmsTemplateRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + Remark string `position:"Query" name:"Remark"` + TemplateType requests.Integer `position:"Query" name:"TemplateType"` + TemplateName string `position:"Query" name:"TemplateName"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + TemplateContent string `position:"Query" name:"TemplateContent"` +} + +// AddSmsTemplateResponse is the response struct for api AddSmsTemplate +type AddSmsTemplateResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + TemplateCode string `json:"TemplateCode" xml:"TemplateCode"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateAddSmsTemplateRequest creates a request to invoke AddSmsTemplate API +func CreateAddSmsTemplateRequest() (request *AddSmsTemplateRequest) { + request = &AddSmsTemplateRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "AddSmsTemplate", "dysms", "openAPI") + return +} + +// CreateAddSmsTemplateResponse creates a response to parse from AddSmsTemplate response +func CreateAddSmsTemplateResponse() (response *AddSmsTemplateResponse) { + response = &AddSmsTemplateResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/client.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/client.go new file mode 100644 index 0000000..c94d36c --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/client.go @@ -0,0 +1,129 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "reflect" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider" +) + +// Client is the sdk client struct, each func corresponds to an OpenAPI +type Client struct { + sdk.Client +} + +// SetClientProperty Set Property by Reflect +func SetClientProperty(client *Client, propertyName string, propertyValue interface{}) { + v := reflect.ValueOf(client).Elem() + if v.FieldByName(propertyName).IsValid() && v.FieldByName(propertyName).CanSet() { + v.FieldByName(propertyName).Set(reflect.ValueOf(propertyValue)) + } +} + +// SetEndpointDataToClient Set EndpointMap and ENdpointType +func SetEndpointDataToClient(client *Client) { + SetClientProperty(client, "EndpointMap", GetEndpointMap()) + SetClientProperty(client, "EndpointType", GetEndpointType()) +} + +// NewClient creates a sdk client with environment variables +func NewClient() (client *Client, err error) { + client = &Client{} + err = client.Init() + SetEndpointDataToClient(client) + return +} + +// NewClientWithProvider creates a sdk client with providers +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithProvider(regionId string, providers ...provider.Provider) (client *Client, err error) { + client = &Client{} + var pc provider.Provider + if len(providers) == 0 { + pc = provider.DefaultChain + } else { + pc = provider.NewProviderChain(providers) + } + err = client.InitWithProviderChain(regionId, pc) + SetEndpointDataToClient(client) + return +} + +// NewClientWithOptions creates a sdk client with regionId/sdkConfig/credential +// this is the common api to create a sdk client +func NewClientWithOptions(regionId string, config *sdk.Config, credential auth.Credential) (client *Client, err error) { + client = &Client{} + err = client.InitWithOptions(regionId, config, credential) + SetEndpointDataToClient(client) + return +} + +// NewClientWithAccessKey is a shortcut to create sdk client with accesskey +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithAccessKey(regionId, accessKeyId, accessKeySecret string) (client *Client, err error) { + client = &Client{} + err = client.InitWithAccessKey(regionId, accessKeyId, accessKeySecret) + SetEndpointDataToClient(client) + return +} + +// NewClientWithStsToken is a shortcut to create sdk client with sts token +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken string) (client *Client, err error) { + client = &Client{} + err = client.InitWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken) + SetEndpointDataToClient(client) + return +} + +// NewClientWithRamRoleArn is a shortcut to create sdk client with ram roleArn +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithRamRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) { + client = &Client{} + err = client.InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName) + SetEndpointDataToClient(client) + return +} + +// NewClientWithRamRoleArn is a shortcut to create sdk client with ram roleArn and policy +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithRamRoleArnAndPolicy(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string) (client *Client, err error) { + client = &Client{} + err = client.InitWithRamRoleArnAndPolicy(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy) + SetEndpointDataToClient(client) + return +} + +// NewClientWithEcsRamRole is a shortcut to create sdk client with ecs ram role +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithEcsRamRole(regionId string, roleName string) (client *Client, err error) { + client = &Client{} + err = client.InitWithEcsRamRole(regionId, roleName) + SetEndpointDataToClient(client) + return +} + +// NewClientWithRsaKeyPair is a shortcut to create sdk client with rsa key pair +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithRsaKeyPair(regionId string, publicKeyId, privateKey string, sessionExpiration int) (client *Client, err error) { + client = &Client{} + err = client.InitWithRsaKeyPair(regionId, publicKeyId, privateKey, sessionExpiration) + SetEndpointDataToClient(client) + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_sign.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_sign.go new file mode 100644 index 0000000..e9f85a5 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_sign.go @@ -0,0 +1,109 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// DeleteSmsSign invokes the dysmsapi.DeleteSmsSign API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/deletesmssign.html +func (client *Client) DeleteSmsSign(request *DeleteSmsSignRequest) (response *DeleteSmsSignResponse, err error) { + response = CreateDeleteSmsSignResponse() + err = client.DoAction(request, response) + return +} + +// DeleteSmsSignWithChan invokes the dysmsapi.DeleteSmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/deletesmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) DeleteSmsSignWithChan(request *DeleteSmsSignRequest) (<-chan *DeleteSmsSignResponse, <-chan error) { + responseChan := make(chan *DeleteSmsSignResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.DeleteSmsSign(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// DeleteSmsSignWithCallback invokes the dysmsapi.DeleteSmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/deletesmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) DeleteSmsSignWithCallback(request *DeleteSmsSignRequest, callback func(response *DeleteSmsSignResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *DeleteSmsSignResponse + var err error + defer close(result) + response, err = client.DeleteSmsSign(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// DeleteSmsSignRequest is the request struct for api DeleteSmsSign +type DeleteSmsSignRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + SignName string `position:"Query" name:"SignName"` +} + +// DeleteSmsSignResponse is the response struct for api DeleteSmsSign +type DeleteSmsSignResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + SignName string `json:"SignName" xml:"SignName"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateDeleteSmsSignRequest creates a request to invoke DeleteSmsSign API +func CreateDeleteSmsSignRequest() (request *DeleteSmsSignRequest) { + request = &DeleteSmsSignRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "DeleteSmsSign", "dysms", "openAPI") + return +} + +// CreateDeleteSmsSignResponse creates a response to parse from DeleteSmsSign response +func CreateDeleteSmsSignResponse() (response *DeleteSmsSignResponse) { + response = &DeleteSmsSignResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_template.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_template.go new file mode 100644 index 0000000..85f29f3 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/delete_sms_template.go @@ -0,0 +1,109 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// DeleteSmsTemplate invokes the dysmsapi.DeleteSmsTemplate API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/deletesmstemplate.html +func (client *Client) DeleteSmsTemplate(request *DeleteSmsTemplateRequest) (response *DeleteSmsTemplateResponse, err error) { + response = CreateDeleteSmsTemplateResponse() + err = client.DoAction(request, response) + return +} + +// DeleteSmsTemplateWithChan invokes the dysmsapi.DeleteSmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/deletesmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) DeleteSmsTemplateWithChan(request *DeleteSmsTemplateRequest) (<-chan *DeleteSmsTemplateResponse, <-chan error) { + responseChan := make(chan *DeleteSmsTemplateResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.DeleteSmsTemplate(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// DeleteSmsTemplateWithCallback invokes the dysmsapi.DeleteSmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/deletesmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) DeleteSmsTemplateWithCallback(request *DeleteSmsTemplateRequest, callback func(response *DeleteSmsTemplateResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *DeleteSmsTemplateResponse + var err error + defer close(result) + response, err = client.DeleteSmsTemplate(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// DeleteSmsTemplateRequest is the request struct for api DeleteSmsTemplate +type DeleteSmsTemplateRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + TemplateCode string `position:"Query" name:"TemplateCode"` +} + +// DeleteSmsTemplateResponse is the response struct for api DeleteSmsTemplate +type DeleteSmsTemplateResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + TemplateCode string `json:"TemplateCode" xml:"TemplateCode"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateDeleteSmsTemplateRequest creates a request to invoke DeleteSmsTemplate API +func CreateDeleteSmsTemplateRequest() (request *DeleteSmsTemplateRequest) { + request = &DeleteSmsTemplateRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "DeleteSmsTemplate", "dysms", "openAPI") + return +} + +// CreateDeleteSmsTemplateResponse creates a response to parse from DeleteSmsTemplate response +func CreateDeleteSmsTemplateResponse() (response *DeleteSmsTemplateResponse) { + response = &DeleteSmsTemplateResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/endpoint.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/endpoint.go new file mode 100644 index 0000000..6055524 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/endpoint.go @@ -0,0 +1,36 @@ +package dysmsapi + +// EndpointMap Endpoint Data +var EndpointMap map[string]string + +// EndpointType regional or central +var EndpointType = "central" + +// GetEndpointMap Get Endpoint Data Map +func GetEndpointMap() map[string]string { + if EndpointMap == nil { + EndpointMap = map[string]string{ + "rus-west-1-pop": "dysmsapi.ap-southeast-1.aliyuncs.com", + "cn-beijing": "dysmsapi-proxy.cn-beijing.aliyuncs.com", + "ap-south-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + "eu-west-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + "eu-west-1-oxs": "dysmsapi.ap-southeast-1.aliyuncs.com", + "ap-northeast-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + "me-east-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + "ap-southeast-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + "ap-southeast-2": "dysmsapi.ap-southeast-1.aliyuncs.com", + "ap-southeast-3": "dysmsapi.ap-southeast-1.aliyuncs.com", + "eu-central-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + "ap-southeast-5": "dysmsapi.ap-southeast-1.aliyuncs.com", + "us-east-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + "ap-northeast-2-pop": "dysmsapi.ap-southeast-1.aliyuncs.com", + "us-west-1": "dysmsapi.ap-southeast-1.aliyuncs.com", + } + } + return EndpointMap +} + +// GetEndpointType Get Endpoint Type Value +func GetEndpointType() string { + return EndpointType +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_sign.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_sign.go new file mode 100644 index 0000000..6380578 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_sign.go @@ -0,0 +1,118 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// ModifySmsSign invokes the dysmsapi.ModifySmsSign API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/modifysmssign.html +func (client *Client) ModifySmsSign(request *ModifySmsSignRequest) (response *ModifySmsSignResponse, err error) { + response = CreateModifySmsSignResponse() + err = client.DoAction(request, response) + return +} + +// ModifySmsSignWithChan invokes the dysmsapi.ModifySmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/modifysmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) ModifySmsSignWithChan(request *ModifySmsSignRequest) (<-chan *ModifySmsSignResponse, <-chan error) { + responseChan := make(chan *ModifySmsSignResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.ModifySmsSign(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// ModifySmsSignWithCallback invokes the dysmsapi.ModifySmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/modifysmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) ModifySmsSignWithCallback(request *ModifySmsSignRequest, callback func(response *ModifySmsSignResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *ModifySmsSignResponse + var err error + defer close(result) + response, err = client.ModifySmsSign(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// ModifySmsSignRequest is the request struct for api ModifySmsSign +type ModifySmsSignRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + Remark string `position:"Query" name:"Remark"` + SignName string `position:"Query" name:"SignName"` + SignFileList *[]ModifySmsSignSignFileList `position:"Query" name:"SignFileList" type:"Repeated"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + SignSource requests.Integer `position:"Query" name:"SignSource"` +} + +// ModifySmsSignSignFileList is a repeated param struct in ModifySmsSignRequest +type ModifySmsSignSignFileList struct { + FileContents string `name:"FileContents"` + FileSuffix string `name:"FileSuffix"` +} + +// ModifySmsSignResponse is the response struct for api ModifySmsSign +type ModifySmsSignResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + SignName string `json:"SignName" xml:"SignName"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateModifySmsSignRequest creates a request to invoke ModifySmsSign API +func CreateModifySmsSignRequest() (request *ModifySmsSignRequest) { + request = &ModifySmsSignRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "ModifySmsSign", "dysms", "openAPI") + return +} + +// CreateModifySmsSignResponse creates a response to parse from ModifySmsSign response +func CreateModifySmsSignResponse() (response *ModifySmsSignResponse) { + response = &ModifySmsSignResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_template.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_template.go new file mode 100644 index 0000000..fe76985 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/modify_sms_template.go @@ -0,0 +1,113 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// ModifySmsTemplate invokes the dysmsapi.ModifySmsTemplate API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/modifysmstemplate.html +func (client *Client) ModifySmsTemplate(request *ModifySmsTemplateRequest) (response *ModifySmsTemplateResponse, err error) { + response = CreateModifySmsTemplateResponse() + err = client.DoAction(request, response) + return +} + +// ModifySmsTemplateWithChan invokes the dysmsapi.ModifySmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/modifysmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) ModifySmsTemplateWithChan(request *ModifySmsTemplateRequest) (<-chan *ModifySmsTemplateResponse, <-chan error) { + responseChan := make(chan *ModifySmsTemplateResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.ModifySmsTemplate(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// ModifySmsTemplateWithCallback invokes the dysmsapi.ModifySmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/modifysmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) ModifySmsTemplateWithCallback(request *ModifySmsTemplateRequest, callback func(response *ModifySmsTemplateResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *ModifySmsTemplateResponse + var err error + defer close(result) + response, err = client.ModifySmsTemplate(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// ModifySmsTemplateRequest is the request struct for api ModifySmsTemplate +type ModifySmsTemplateRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + Remark string `position:"Query" name:"Remark"` + TemplateType requests.Integer `position:"Query" name:"TemplateType"` + TemplateName string `position:"Query" name:"TemplateName"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + TemplateContent string `position:"Query" name:"TemplateContent"` + TemplateCode string `position:"Query" name:"TemplateCode"` +} + +// ModifySmsTemplateResponse is the response struct for api ModifySmsTemplate +type ModifySmsTemplateResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + TemplateCode string `json:"TemplateCode" xml:"TemplateCode"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateModifySmsTemplateRequest creates a request to invoke ModifySmsTemplate API +func CreateModifySmsTemplateRequest() (request *ModifySmsTemplateRequest) { + request = &ModifySmsTemplateRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "ModifySmsTemplate", "dysms", "openAPI") + return +} + +// CreateModifySmsTemplateResponse creates a response to parse from ModifySmsTemplate response +func CreateModifySmsTemplateResponse() (response *ModifySmsTemplateResponse) { + response = &ModifySmsTemplateResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_send_details.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_send_details.go new file mode 100644 index 0000000..9194205 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_send_details.go @@ -0,0 +1,114 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// QuerySendDetails invokes the dysmsapi.QuerySendDetails API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysenddetails.html +func (client *Client) QuerySendDetails(request *QuerySendDetailsRequest) (response *QuerySendDetailsResponse, err error) { + response = CreateQuerySendDetailsResponse() + err = client.DoAction(request, response) + return +} + +// QuerySendDetailsWithChan invokes the dysmsapi.QuerySendDetails API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysenddetails.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) QuerySendDetailsWithChan(request *QuerySendDetailsRequest) (<-chan *QuerySendDetailsResponse, <-chan error) { + responseChan := make(chan *QuerySendDetailsResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.QuerySendDetails(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// QuerySendDetailsWithCallback invokes the dysmsapi.QuerySendDetails API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysenddetails.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) QuerySendDetailsWithCallback(request *QuerySendDetailsRequest, callback func(response *QuerySendDetailsResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *QuerySendDetailsResponse + var err error + defer close(result) + response, err = client.QuerySendDetails(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// QuerySendDetailsRequest is the request struct for api QuerySendDetails +type QuerySendDetailsRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + PhoneNumber string `position:"Query" name:"PhoneNumber"` + SendDate string `position:"Query" name:"SendDate"` + PageSize requests.Integer `position:"Query" name:"PageSize"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + CurrentPage requests.Integer `position:"Query" name:"CurrentPage"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + BizId string `position:"Query" name:"BizId"` +} + +// QuerySendDetailsResponse is the response struct for api QuerySendDetails +type QuerySendDetailsResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` + TotalCount string `json:"TotalCount" xml:"TotalCount"` + SmsSendDetailDTOs SmsSendDetailDTOs `json:"SmsSendDetailDTOs" xml:"SmsSendDetailDTOs"` +} + +// CreateQuerySendDetailsRequest creates a request to invoke QuerySendDetails API +func CreateQuerySendDetailsRequest() (request *QuerySendDetailsRequest) { + request = &QuerySendDetailsRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "QuerySendDetails", "dysms", "openAPI") + return +} + +// CreateQuerySendDetailsResponse creates a response to parse from QuerySendDetails response +func CreateQuerySendDetailsResponse() (response *QuerySendDetailsResponse) { + response = &QuerySendDetailsResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_sign.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_sign.go new file mode 100644 index 0000000..5077187 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_sign.go @@ -0,0 +1,112 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// QuerySmsSign invokes the dysmsapi.QuerySmsSign API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysmssign.html +func (client *Client) QuerySmsSign(request *QuerySmsSignRequest) (response *QuerySmsSignResponse, err error) { + response = CreateQuerySmsSignResponse() + err = client.DoAction(request, response) + return +} + +// QuerySmsSignWithChan invokes the dysmsapi.QuerySmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) QuerySmsSignWithChan(request *QuerySmsSignRequest) (<-chan *QuerySmsSignResponse, <-chan error) { + responseChan := make(chan *QuerySmsSignResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.QuerySmsSign(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// QuerySmsSignWithCallback invokes the dysmsapi.QuerySmsSign API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysmssign.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) QuerySmsSignWithCallback(request *QuerySmsSignRequest, callback func(response *QuerySmsSignResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *QuerySmsSignResponse + var err error + defer close(result) + response, err = client.QuerySmsSign(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// QuerySmsSignRequest is the request struct for api QuerySmsSign +type QuerySmsSignRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + SignName string `position:"Query" name:"SignName"` +} + +// QuerySmsSignResponse is the response struct for api QuerySmsSign +type QuerySmsSignResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` + SignStatus int `json:"SignStatus" xml:"SignStatus"` + Reason string `json:"Reason" xml:"Reason"` + SignName string `json:"SignName" xml:"SignName"` + CreateDate string `json:"CreateDate" xml:"CreateDate"` +} + +// CreateQuerySmsSignRequest creates a request to invoke QuerySmsSign API +func CreateQuerySmsSignRequest() (request *QuerySmsSignRequest) { + request = &QuerySmsSignRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "QuerySmsSign", "dysms", "openAPI") + return +} + +// CreateQuerySmsSignResponse creates a response to parse from QuerySmsSign response +func CreateQuerySmsSignResponse() (response *QuerySmsSignResponse) { + response = &QuerySmsSignResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_template.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_template.go new file mode 100644 index 0000000..cdc0b8f --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/query_sms_template.go @@ -0,0 +1,115 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// QuerySmsTemplate invokes the dysmsapi.QuerySmsTemplate API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysmstemplate.html +func (client *Client) QuerySmsTemplate(request *QuerySmsTemplateRequest) (response *QuerySmsTemplateResponse, err error) { + response = CreateQuerySmsTemplateResponse() + err = client.DoAction(request, response) + return +} + +// QuerySmsTemplateWithChan invokes the dysmsapi.QuerySmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) QuerySmsTemplateWithChan(request *QuerySmsTemplateRequest) (<-chan *QuerySmsTemplateResponse, <-chan error) { + responseChan := make(chan *QuerySmsTemplateResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.QuerySmsTemplate(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// QuerySmsTemplateWithCallback invokes the dysmsapi.QuerySmsTemplate API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/querysmstemplate.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) QuerySmsTemplateWithCallback(request *QuerySmsTemplateRequest, callback func(response *QuerySmsTemplateResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *QuerySmsTemplateResponse + var err error + defer close(result) + response, err = client.QuerySmsTemplate(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// QuerySmsTemplateRequest is the request struct for api QuerySmsTemplate +type QuerySmsTemplateRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + TemplateCode string `position:"Query" name:"TemplateCode"` +} + +// QuerySmsTemplateResponse is the response struct for api QuerySmsTemplate +type QuerySmsTemplateResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` + TemplateStatus int `json:"TemplateStatus" xml:"TemplateStatus"` + Reason string `json:"Reason" xml:"Reason"` + TemplateCode string `json:"TemplateCode" xml:"TemplateCode"` + TemplateType int `json:"TemplateType" xml:"TemplateType"` + TemplateName string `json:"TemplateName" xml:"TemplateName"` + TemplateContent string `json:"TemplateContent" xml:"TemplateContent"` + CreateDate string `json:"CreateDate" xml:"CreateDate"` +} + +// CreateQuerySmsTemplateRequest creates a request to invoke QuerySmsTemplate API +func CreateQuerySmsTemplateRequest() (request *QuerySmsTemplateRequest) { + request = &QuerySmsTemplateRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "QuerySmsTemplate", "dysms", "openAPI") + return +} + +// CreateQuerySmsTemplateResponse creates a response to parse from QuerySmsTemplate response +func CreateQuerySmsTemplateResponse() (response *QuerySmsTemplateResponse) { + response = &QuerySmsTemplateResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_batch_sms.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_batch_sms.go new file mode 100644 index 0000000..d1db5d4 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_batch_sms.go @@ -0,0 +1,113 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// SendBatchSms invokes the dysmsapi.SendBatchSms API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/sendbatchsms.html +func (client *Client) SendBatchSms(request *SendBatchSmsRequest) (response *SendBatchSmsResponse, err error) { + response = CreateSendBatchSmsResponse() + err = client.DoAction(request, response) + return +} + +// SendBatchSmsWithChan invokes the dysmsapi.SendBatchSms API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/sendbatchsms.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) SendBatchSmsWithChan(request *SendBatchSmsRequest) (<-chan *SendBatchSmsResponse, <-chan error) { + responseChan := make(chan *SendBatchSmsResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.SendBatchSms(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// SendBatchSmsWithCallback invokes the dysmsapi.SendBatchSms API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/sendbatchsms.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) SendBatchSmsWithCallback(request *SendBatchSmsRequest, callback func(response *SendBatchSmsResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *SendBatchSmsResponse + var err error + defer close(result) + response, err = client.SendBatchSms(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// SendBatchSmsRequest is the request struct for api SendBatchSms +type SendBatchSmsRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + TemplateParamJson string `position:"Query" name:"TemplateParamJson"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + SmsUpExtendCodeJson string `position:"Query" name:"SmsUpExtendCodeJson"` + SignNameJson string `position:"Query" name:"SignNameJson"` + TemplateCode string `position:"Query" name:"TemplateCode"` + PhoneNumberJson string `position:"Query" name:"PhoneNumberJson"` +} + +// SendBatchSmsResponse is the response struct for api SendBatchSms +type SendBatchSmsResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + BizId string `json:"BizId" xml:"BizId"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateSendBatchSmsRequest creates a request to invoke SendBatchSms API +func CreateSendBatchSmsRequest() (request *SendBatchSmsRequest) { + request = &SendBatchSmsRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "SendBatchSms", "dysms", "openAPI") + return +} + +// CreateSendBatchSmsResponse creates a response to parse from SendBatchSms response +func CreateSendBatchSmsResponse() (response *SendBatchSmsResponse) { + response = &SendBatchSmsResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_sms.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_sms.go new file mode 100644 index 0000000..96bdbcd --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/send_sms.go @@ -0,0 +1,114 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// SendSms invokes the dysmsapi.SendSms API synchronously +// api document: https://help.aliyun.com/api/dysmsapi/sendsms.html +func (client *Client) SendSms(request *SendSmsRequest) (response *SendSmsResponse, err error) { + response = CreateSendSmsResponse() + err = client.DoAction(request, response) + return +} + +// SendSmsWithChan invokes the dysmsapi.SendSms API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/sendsms.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) SendSmsWithChan(request *SendSmsRequest) (<-chan *SendSmsResponse, <-chan error) { + responseChan := make(chan *SendSmsResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.SendSms(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// SendSmsWithCallback invokes the dysmsapi.SendSms API asynchronously +// api document: https://help.aliyun.com/api/dysmsapi/sendsms.html +// asynchronous document: https://help.aliyun.com/document_detail/66220.html +func (client *Client) SendSmsWithCallback(request *SendSmsRequest, callback func(response *SendSmsResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *SendSmsResponse + var err error + defer close(result) + response, err = client.SendSms(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// SendSmsRequest is the request struct for api SendSms +type SendSmsRequest struct { + *requests.RpcRequest + ResourceOwnerId requests.Integer `position:"Query" name:"ResourceOwnerId"` + SmsUpExtendCode string `position:"Query" name:"SmsUpExtendCode"` + SignName string `position:"Query" name:"SignName"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + PhoneNumbers string `position:"Query" name:"PhoneNumbers"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + OutId string `position:"Query" name:"OutId"` + TemplateCode string `position:"Query" name:"TemplateCode"` + TemplateParam string `position:"Query" name:"TemplateParam"` +} + +// SendSmsResponse is the response struct for api SendSms +type SendSmsResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + BizId string `json:"BizId" xml:"BizId"` + Code string `json:"Code" xml:"Code"` + Message string `json:"Message" xml:"Message"` +} + +// CreateSendSmsRequest creates a request to invoke SendSms API +func CreateSendSmsRequest() (request *SendSmsRequest) { + request = &SendSmsRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Dysmsapi", "2017-05-25", "SendSms", "dysms", "openAPI") + return +} + +// CreateSendSmsResponse creates a response to parse from SendSms response +func CreateSendSmsResponse() (response *SendSmsResponse) { + response = &SendSmsResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dt_os.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dt_os.go new file mode 100644 index 0000000..aaa8996 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dt_os.go @@ -0,0 +1,21 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// SmsSendDetailDTOs is a nested struct in dysmsapi response +type SmsSendDetailDTOs struct { + SmsSendDetailDTO []SmsSendDetailDTO `json:"SmsSendDetailDTO" xml:"SmsSendDetailDTO"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dto.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dto.go new file mode 100644 index 0000000..1dacb3e --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi/struct_sms_send_detail_dto.go @@ -0,0 +1,28 @@ +package dysmsapi + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// SmsSendDetailDTO is a nested struct in dysmsapi response +type SmsSendDetailDTO struct { + PhoneNum string `json:"PhoneNum" xml:"PhoneNum"` + SendStatus int64 `json:"SendStatus" xml:"SendStatus"` + ErrCode string `json:"ErrCode" xml:"ErrCode"` + TemplateCode string `json:"TemplateCode" xml:"TemplateCode"` + Content string `json:"Content" xml:"Content"` + SendDate string `json:"SendDate" xml:"SendDate"` + ReceiveDate string `json:"ReceiveDate" xml:"ReceiveDate"` + OutId string `json:"OutId" xml:"OutId"` +} diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE index c836416..bc52e96 100644 --- a/vendor/github.com/davecgh/go-spew/LICENSE +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -2,7 +2,7 @@ ISC License Copyright (c) 2012-2016 Dave Collins -Permission to use, copy, modify, and distribute this software for any +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go index 8a4a658..7929947 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypass.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -16,7 +16,9 @@ // when the code is not running on Google App Engine, compiled by GopherJS, and // "-tags safe" is not added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build !js,!appengine,!safe,!disableunsafe +// Go versions prior to 1.4 are disabled because they use a different layout +// for interfaces which make the implementation of unsafeReflectValue more complex. +// +build !js,!appengine,!safe,!disableunsafe,go1.4 package spew @@ -34,80 +36,49 @@ const ( ptrSize = unsafe.Sizeof((*byte)(nil)) ) +type flag uintptr + var ( - // offsetPtr, offsetScalar, and offsetFlag are the offsets for the - // internal reflect.Value fields. These values are valid before golang - // commit ecccf07e7f9d which changed the format. The are also valid - // after commit 82f48826c6c7 which changed the format again to mirror - // the original format. Code in the init function updates these offsets - // as necessary. - offsetPtr = uintptr(ptrSize) - offsetScalar = uintptr(0) - offsetFlag = uintptr(ptrSize * 2) - - // flagKindWidth and flagKindShift indicate various bits that the - // reflect package uses internally to track kind information. - // - // flagRO indicates whether or not the value field of a reflect.Value is - // read-only. - // - // flagIndir indicates whether the value field of a reflect.Value is - // the actual data or a pointer to the data. - // - // These values are valid before golang commit 90a7c3c86944 which - // changed their positions. Code in the init function updates these - // flags as necessary. - flagKindWidth = uintptr(5) - flagKindShift = uintptr(flagKindWidth - 1) - flagRO = uintptr(1 << 0) - flagIndir = uintptr(1 << 1) + // flagRO indicates whether the value field of a reflect.Value + // is read-only. + flagRO flag + + // flagAddr indicates whether the address of the reflect.Value's + // value may be taken. + flagAddr flag ) -func init() { - // Older versions of reflect.Value stored small integers directly in the - // ptr field (which is named val in the older versions). Versions - // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named - // scalar for this purpose which unfortunately came before the flag - // field, so the offset of the flag field is different for those - // versions. - // - // This code constructs a new reflect.Value from a known small integer - // and checks if the size of the reflect.Value struct indicates it has - // the scalar field. When it does, the offsets are updated accordingly. - vv := reflect.ValueOf(0xf00) - if unsafe.Sizeof(vv) == (ptrSize * 4) { - offsetScalar = ptrSize * 2 - offsetFlag = ptrSize * 3 - } +// flagKindMask holds the bits that make up the kind +// part of the flags field. In all the supported versions, +// it is in the lower 5 bits. +const flagKindMask = flag(0x1f) - // Commit 90a7c3c86944 changed the flag positions such that the low - // order bits are the kind. This code extracts the kind from the flags - // field and ensures it's the correct type. When it's not, the flag - // order has been changed to the newer format, so the flags are updated - // accordingly. - upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) - upfv := *(*uintptr)(upf) - flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { - flagKindShift = 0 - flagRO = 1 << 5 - flagIndir = 1 << 6 - - // Commit adf9b30e5594 modified the flags to separate the - // flagRO flag into two bits which specifies whether or not the - // field is embedded. This causes flagIndir to move over a bit - // and means that flagRO is the combination of either of the - // original flagRO bit and the new bit. - // - // This code detects the change by extracting what used to be - // the indirect bit to ensure it's set. When it's not, the flag - // order has been changed to the newer format, so the flags are - // updated accordingly. - if upfv&flagIndir == 0 { - flagRO = 3 << 5 - flagIndir = 1 << 7 - } +// Different versions of Go have used different +// bit layouts for the flags type. This table +// records the known combinations. +var okFlags = []struct { + ro, addr flag +}{{ + // From Go 1.4 to 1.5 + ro: 1 << 5, + addr: 1 << 7, +}, { + // Up to Go tip. + ro: 1<<5 | 1<<6, + addr: 1 << 8, +}} + +var flagValOffset = func() uintptr { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") } + return field.Offset +}() + +// flagField returns a pointer to the flag field of a reflect.Value. +func flagField(v *reflect.Value) *flag { + return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) } // unsafeReflectValue converts the passed reflect.Value into a one that bypasses @@ -119,34 +90,56 @@ func init() { // This allows us to check for implementations of the Stringer and error // interfaces to be used for pretty printing ordinarily unaddressable and // inaccessible values such as unexported struct fields. -func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { - indirects := 1 - vt := v.Type() - upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) - rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) - if rvf&flagIndir != 0 { - vt = reflect.PtrTo(v.Type()) - indirects++ - } else if offsetScalar != 0 { - // The value is in the scalar field when it's not one of the - // reference types. - switch vt.Kind() { - case reflect.Uintptr: - case reflect.Chan: - case reflect.Func: - case reflect.Map: - case reflect.Ptr: - case reflect.UnsafePointer: - default: - upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + - offsetScalar) - } +func unsafeReflectValue(v reflect.Value) reflect.Value { + if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { + return v } + flagFieldPtr := flagField(&v) + *flagFieldPtr &^= flagRO + *flagFieldPtr |= flagAddr + return v +} - pv := reflect.NewAt(vt, upv) - rv = pv - for i := 0; i < indirects; i++ { - rv = rv.Elem() +// Sanity checks against future reflect package changes +// to the type or semantics of the Value.flag field. +func init() { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") + } + if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { + panic("reflect.Value flag field has changed kind") + } + type t0 int + var t struct { + A t0 + // t0 will have flagEmbedRO set. + t0 + // a will have flagStickyRO set + a t0 + } + vA := reflect.ValueOf(t).FieldByName("A") + va := reflect.ValueOf(t).FieldByName("a") + vt0 := reflect.ValueOf(t).FieldByName("t0") + + // Infer flagRO from the difference between the flags + // for the (otherwise identical) fields in t. + flagPublic := *flagField(&vA) + flagWithRO := *flagField(&va) | *flagField(&vt0) + flagRO = flagPublic ^ flagWithRO + + // Infer flagAddr from the difference between a value + // taken from a pointer and not. + vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") + flagNoPtr := *flagField(&vA) + flagPtr := *flagField(&vPtrA) + flagAddr = flagNoPtr ^ flagPtr + + // Check that the inferred flags tally with one of the known versions. + for _, f := range okFlags { + if flagRO == f.ro && flagAddr == f.addr { + return + } } - return rv + panic("reflect.Value read-only flag has changed semantics") } diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go index 1fe3cf3..205c28d 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -16,7 +16,7 @@ // when the code is running on Google App Engine, compiled by GopherJS, or // "-tags safe" is added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build js appengine safe disableunsafe +// +build js appengine safe disableunsafe !go1.4 package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go index 7c519ff..1be8ce9 100644 --- a/vendor/github.com/davecgh/go-spew/spew/common.go +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) { w.Write(closeParenBytes) } -// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' // prefix to Writer w. func printHexPtr(w io.Writer, p uintptr) { // Null pointer. diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go index df1d582..f78d89f 100644 --- a/vendor/github.com/davecgh/go-spew/spew/dump.go +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -35,16 +35,16 @@ var ( // cCharRE is a regular expression that matches a cgo char. // It is used to detect character arrays to hexdump them. - cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) // cUnsignedCharRE is a regular expression that matches a cgo unsigned // char. It is used to detect unsigned character arrays to hexdump // them. - cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) // cUint8tCharRE is a regular expression that matches a cgo uint8_t. // It is used to detect uint8_t arrays to hexdump them. - cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") + cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) ) // dumpState contains information about the state of a dump operation. @@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) { // Display dereferenced value. d.w.Write(openParenBytes) switch { - case nilFound == true: + case nilFound: d.w.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: d.w.Write(circularBytes) default: diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go index c49875b..b04edb7 100644 --- a/vendor/github.com/davecgh/go-spew/spew/format.go +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) { // Display dereferenced value. switch { - case nilFound == true: + case nilFound: f.fs.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: f.fs.Write(circularShortBytes) default: diff --git a/vendor/github.com/jmespath/go-jmespath/.gitignore b/vendor/github.com/jmespath/go-jmespath/.gitignore new file mode 100644 index 0000000..5091fb0 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/.gitignore @@ -0,0 +1,4 @@ +/jpgo +jmespath-fuzz.zip +cpu.out +go-jmespath.test diff --git a/vendor/github.com/jmespath/go-jmespath/.travis.yml b/vendor/github.com/jmespath/go-jmespath/.travis.yml new file mode 100644 index 0000000..1f98077 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/.travis.yml @@ -0,0 +1,9 @@ +language: go + +sudo: false + +go: + - 1.4 + +install: go get -v -t ./... +script: make test diff --git a/vendor/github.com/jmespath/go-jmespath/LICENSE b/vendor/github.com/jmespath/go-jmespath/LICENSE new file mode 100644 index 0000000..b03310a --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/LICENSE @@ -0,0 +1,13 @@ +Copyright 2015 James Saryerwinnie + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/jmespath/go-jmespath/Makefile b/vendor/github.com/jmespath/go-jmespath/Makefile new file mode 100644 index 0000000..a828d28 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/Makefile @@ -0,0 +1,44 @@ + +CMD = jpgo + +help: + @echo "Please use \`make ' where is one of" + @echo " test to run all the tests" + @echo " build to build the library and jp executable" + @echo " generate to run codegen" + + +generate: + go generate ./... + +build: + rm -f $(CMD) + go build ./... + rm -f cmd/$(CMD)/$(CMD) && cd cmd/$(CMD)/ && go build ./... + mv cmd/$(CMD)/$(CMD) . + +test: + go test -v ./... + +check: + go vet ./... + @echo "golint ./..." + @lint=`golint ./...`; \ + lint=`echo "$$lint" | grep -v "astnodetype_string.go" | grep -v "toktype_string.go"`; \ + echo "$$lint"; \ + if [ "$$lint" != "" ]; then exit 1; fi + +htmlc: + go test -coverprofile="/tmp/jpcov" && go tool cover -html="/tmp/jpcov" && unlink /tmp/jpcov + +buildfuzz: + go-fuzz-build github.com/jmespath/go-jmespath/fuzz + +fuzz: buildfuzz + go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/testdata + +bench: + go test -bench . -cpuprofile cpu.out + +pprof-cpu: + go tool pprof ./go-jmespath.test ./cpu.out diff --git a/vendor/github.com/jmespath/go-jmespath/README.md b/vendor/github.com/jmespath/go-jmespath/README.md new file mode 100644 index 0000000..187ef67 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/README.md @@ -0,0 +1,7 @@ +# go-jmespath - A JMESPath implementation in Go + +[![Build Status](https://img.shields.io/travis/jmespath/go-jmespath.svg)](https://travis-ci.org/jmespath/go-jmespath) + + + +See http://jmespath.org for more info. diff --git a/vendor/github.com/jmespath/go-jmespath/api.go b/vendor/github.com/jmespath/go-jmespath/api.go new file mode 100644 index 0000000..8e26ffe --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/api.go @@ -0,0 +1,49 @@ +package jmespath + +import "strconv" + +// JMESPath is the epresentation of a compiled JMES path query. A JMESPath is +// safe for concurrent use by multiple goroutines. +type JMESPath struct { + ast ASTNode + intr *treeInterpreter +} + +// Compile parses a JMESPath expression and returns, if successful, a JMESPath +// object that can be used to match against data. +func Compile(expression string) (*JMESPath, error) { + parser := NewParser() + ast, err := parser.Parse(expression) + if err != nil { + return nil, err + } + jmespath := &JMESPath{ast: ast, intr: newInterpreter()} + return jmespath, nil +} + +// MustCompile is like Compile but panics if the expression cannot be parsed. +// It simplifies safe initialization of global variables holding compiled +// JMESPaths. +func MustCompile(expression string) *JMESPath { + jmespath, err := Compile(expression) + if err != nil { + panic(`jmespath: Compile(` + strconv.Quote(expression) + `): ` + err.Error()) + } + return jmespath +} + +// Search evaluates a JMESPath expression against input data and returns the result. +func (jp *JMESPath) Search(data interface{}) (interface{}, error) { + return jp.intr.Execute(jp.ast, data) +} + +// Search evaluates a JMESPath expression against input data and returns the result. +func Search(expression string, data interface{}) (interface{}, error) { + intr := newInterpreter() + parser := NewParser() + ast, err := parser.Parse(expression) + if err != nil { + return nil, err + } + return intr.Execute(ast, data) +} diff --git a/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go b/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go new file mode 100644 index 0000000..1cd2d23 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go @@ -0,0 +1,16 @@ +// generated by stringer -type astNodeType; DO NOT EDIT + +package jmespath + +import "fmt" + +const _astNodeType_name = "ASTEmptyASTComparatorASTCurrentNodeASTExpRefASTFunctionExpressionASTFieldASTFilterProjectionASTFlattenASTIdentityASTIndexASTIndexExpressionASTKeyValPairASTLiteralASTMultiSelectHashASTMultiSelectListASTOrExpressionASTAndExpressionASTNotExpressionASTPipeASTProjectionASTSubexpressionASTSliceASTValueProjection" + +var _astNodeType_index = [...]uint16{0, 8, 21, 35, 44, 65, 73, 92, 102, 113, 121, 139, 152, 162, 180, 198, 213, 229, 245, 252, 265, 281, 289, 307} + +func (i astNodeType) String() string { + if i < 0 || i >= astNodeType(len(_astNodeType_index)-1) { + return fmt.Sprintf("astNodeType(%d)", i) + } + return _astNodeType_name[_astNodeType_index[i]:_astNodeType_index[i+1]] +} diff --git a/vendor/github.com/jmespath/go-jmespath/functions.go b/vendor/github.com/jmespath/go-jmespath/functions.go new file mode 100644 index 0000000..9b7cd89 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/functions.go @@ -0,0 +1,842 @@ +package jmespath + +import ( + "encoding/json" + "errors" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "unicode/utf8" +) + +type jpFunction func(arguments []interface{}) (interface{}, error) + +type jpType string + +const ( + jpUnknown jpType = "unknown" + jpNumber jpType = "number" + jpString jpType = "string" + jpArray jpType = "array" + jpObject jpType = "object" + jpArrayNumber jpType = "array[number]" + jpArrayString jpType = "array[string]" + jpExpref jpType = "expref" + jpAny jpType = "any" +) + +type functionEntry struct { + name string + arguments []argSpec + handler jpFunction + hasExpRef bool +} + +type argSpec struct { + types []jpType + variadic bool +} + +type byExprString struct { + intr *treeInterpreter + node ASTNode + items []interface{} + hasError bool +} + +func (a *byExprString) Len() int { + return len(a.items) +} +func (a *byExprString) Swap(i, j int) { + a.items[i], a.items[j] = a.items[j], a.items[i] +} +func (a *byExprString) Less(i, j int) bool { + first, err := a.intr.Execute(a.node, a.items[i]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + ith, ok := first.(string) + if !ok { + a.hasError = true + return true + } + second, err := a.intr.Execute(a.node, a.items[j]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + jth, ok := second.(string) + if !ok { + a.hasError = true + return true + } + return ith < jth +} + +type byExprFloat struct { + intr *treeInterpreter + node ASTNode + items []interface{} + hasError bool +} + +func (a *byExprFloat) Len() int { + return len(a.items) +} +func (a *byExprFloat) Swap(i, j int) { + a.items[i], a.items[j] = a.items[j], a.items[i] +} +func (a *byExprFloat) Less(i, j int) bool { + first, err := a.intr.Execute(a.node, a.items[i]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + ith, ok := first.(float64) + if !ok { + a.hasError = true + return true + } + second, err := a.intr.Execute(a.node, a.items[j]) + if err != nil { + a.hasError = true + // Return a dummy value. + return true + } + jth, ok := second.(float64) + if !ok { + a.hasError = true + return true + } + return ith < jth +} + +type functionCaller struct { + functionTable map[string]functionEntry +} + +func newFunctionCaller() *functionCaller { + caller := &functionCaller{} + caller.functionTable = map[string]functionEntry{ + "length": { + name: "length", + arguments: []argSpec{ + {types: []jpType{jpString, jpArray, jpObject}}, + }, + handler: jpfLength, + }, + "starts_with": { + name: "starts_with", + arguments: []argSpec{ + {types: []jpType{jpString}}, + {types: []jpType{jpString}}, + }, + handler: jpfStartsWith, + }, + "abs": { + name: "abs", + arguments: []argSpec{ + {types: []jpType{jpNumber}}, + }, + handler: jpfAbs, + }, + "avg": { + name: "avg", + arguments: []argSpec{ + {types: []jpType{jpArrayNumber}}, + }, + handler: jpfAvg, + }, + "ceil": { + name: "ceil", + arguments: []argSpec{ + {types: []jpType{jpNumber}}, + }, + handler: jpfCeil, + }, + "contains": { + name: "contains", + arguments: []argSpec{ + {types: []jpType{jpArray, jpString}}, + {types: []jpType{jpAny}}, + }, + handler: jpfContains, + }, + "ends_with": { + name: "ends_with", + arguments: []argSpec{ + {types: []jpType{jpString}}, + {types: []jpType{jpString}}, + }, + handler: jpfEndsWith, + }, + "floor": { + name: "floor", + arguments: []argSpec{ + {types: []jpType{jpNumber}}, + }, + handler: jpfFloor, + }, + "map": { + name: "amp", + arguments: []argSpec{ + {types: []jpType{jpExpref}}, + {types: []jpType{jpArray}}, + }, + handler: jpfMap, + hasExpRef: true, + }, + "max": { + name: "max", + arguments: []argSpec{ + {types: []jpType{jpArrayNumber, jpArrayString}}, + }, + handler: jpfMax, + }, + "merge": { + name: "merge", + arguments: []argSpec{ + {types: []jpType{jpObject}, variadic: true}, + }, + handler: jpfMerge, + }, + "max_by": { + name: "max_by", + arguments: []argSpec{ + {types: []jpType{jpArray}}, + {types: []jpType{jpExpref}}, + }, + handler: jpfMaxBy, + hasExpRef: true, + }, + "sum": { + name: "sum", + arguments: []argSpec{ + {types: []jpType{jpArrayNumber}}, + }, + handler: jpfSum, + }, + "min": { + name: "min", + arguments: []argSpec{ + {types: []jpType{jpArrayNumber, jpArrayString}}, + }, + handler: jpfMin, + }, + "min_by": { + name: "min_by", + arguments: []argSpec{ + {types: []jpType{jpArray}}, + {types: []jpType{jpExpref}}, + }, + handler: jpfMinBy, + hasExpRef: true, + }, + "type": { + name: "type", + arguments: []argSpec{ + {types: []jpType{jpAny}}, + }, + handler: jpfType, + }, + "keys": { + name: "keys", + arguments: []argSpec{ + {types: []jpType{jpObject}}, + }, + handler: jpfKeys, + }, + "values": { + name: "values", + arguments: []argSpec{ + {types: []jpType{jpObject}}, + }, + handler: jpfValues, + }, + "sort": { + name: "sort", + arguments: []argSpec{ + {types: []jpType{jpArrayString, jpArrayNumber}}, + }, + handler: jpfSort, + }, + "sort_by": { + name: "sort_by", + arguments: []argSpec{ + {types: []jpType{jpArray}}, + {types: []jpType{jpExpref}}, + }, + handler: jpfSortBy, + hasExpRef: true, + }, + "join": { + name: "join", + arguments: []argSpec{ + {types: []jpType{jpString}}, + {types: []jpType{jpArrayString}}, + }, + handler: jpfJoin, + }, + "reverse": { + name: "reverse", + arguments: []argSpec{ + {types: []jpType{jpArray, jpString}}, + }, + handler: jpfReverse, + }, + "to_array": { + name: "to_array", + arguments: []argSpec{ + {types: []jpType{jpAny}}, + }, + handler: jpfToArray, + }, + "to_string": { + name: "to_string", + arguments: []argSpec{ + {types: []jpType{jpAny}}, + }, + handler: jpfToString, + }, + "to_number": { + name: "to_number", + arguments: []argSpec{ + {types: []jpType{jpAny}}, + }, + handler: jpfToNumber, + }, + "not_null": { + name: "not_null", + arguments: []argSpec{ + {types: []jpType{jpAny}, variadic: true}, + }, + handler: jpfNotNull, + }, + } + return caller +} + +func (e *functionEntry) resolveArgs(arguments []interface{}) ([]interface{}, error) { + if len(e.arguments) == 0 { + return arguments, nil + } + if !e.arguments[len(e.arguments)-1].variadic { + if len(e.arguments) != len(arguments) { + return nil, errors.New("incorrect number of args") + } + for i, spec := range e.arguments { + userArg := arguments[i] + err := spec.typeCheck(userArg) + if err != nil { + return nil, err + } + } + return arguments, nil + } + if len(arguments) < len(e.arguments) { + return nil, errors.New("Invalid arity.") + } + return arguments, nil +} + +func (a *argSpec) typeCheck(arg interface{}) error { + for _, t := range a.types { + switch t { + case jpNumber: + if _, ok := arg.(float64); ok { + return nil + } + case jpString: + if _, ok := arg.(string); ok { + return nil + } + case jpArray: + if isSliceType(arg) { + return nil + } + case jpObject: + if _, ok := arg.(map[string]interface{}); ok { + return nil + } + case jpArrayNumber: + if _, ok := toArrayNum(arg); ok { + return nil + } + case jpArrayString: + if _, ok := toArrayStr(arg); ok { + return nil + } + case jpAny: + return nil + case jpExpref: + if _, ok := arg.(expRef); ok { + return nil + } + } + } + return fmt.Errorf("Invalid type for: %v, expected: %#v", arg, a.types) +} + +func (f *functionCaller) CallFunction(name string, arguments []interface{}, intr *treeInterpreter) (interface{}, error) { + entry, ok := f.functionTable[name] + if !ok { + return nil, errors.New("unknown function: " + name) + } + resolvedArgs, err := entry.resolveArgs(arguments) + if err != nil { + return nil, err + } + if entry.hasExpRef { + var extra []interface{} + extra = append(extra, intr) + resolvedArgs = append(extra, resolvedArgs...) + } + return entry.handler(resolvedArgs) +} + +func jpfAbs(arguments []interface{}) (interface{}, error) { + num := arguments[0].(float64) + return math.Abs(num), nil +} + +func jpfLength(arguments []interface{}) (interface{}, error) { + arg := arguments[0] + if c, ok := arg.(string); ok { + return float64(utf8.RuneCountInString(c)), nil + } else if isSliceType(arg) { + v := reflect.ValueOf(arg) + return float64(v.Len()), nil + } else if c, ok := arg.(map[string]interface{}); ok { + return float64(len(c)), nil + } + return nil, errors.New("could not compute length()") +} + +func jpfStartsWith(arguments []interface{}) (interface{}, error) { + search := arguments[0].(string) + prefix := arguments[1].(string) + return strings.HasPrefix(search, prefix), nil +} + +func jpfAvg(arguments []interface{}) (interface{}, error) { + // We've already type checked the value so we can safely use + // type assertions. + args := arguments[0].([]interface{}) + length := float64(len(args)) + numerator := 0.0 + for _, n := range args { + numerator += n.(float64) + } + return numerator / length, nil +} +func jpfCeil(arguments []interface{}) (interface{}, error) { + val := arguments[0].(float64) + return math.Ceil(val), nil +} +func jpfContains(arguments []interface{}) (interface{}, error) { + search := arguments[0] + el := arguments[1] + if searchStr, ok := search.(string); ok { + if elStr, ok := el.(string); ok { + return strings.Index(searchStr, elStr) != -1, nil + } + return false, nil + } + // Otherwise this is a generic contains for []interface{} + general := search.([]interface{}) + for _, item := range general { + if item == el { + return true, nil + } + } + return false, nil +} +func jpfEndsWith(arguments []interface{}) (interface{}, error) { + search := arguments[0].(string) + suffix := arguments[1].(string) + return strings.HasSuffix(search, suffix), nil +} +func jpfFloor(arguments []interface{}) (interface{}, error) { + val := arguments[0].(float64) + return math.Floor(val), nil +} +func jpfMap(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + exp := arguments[1].(expRef) + node := exp.ref + arr := arguments[2].([]interface{}) + mapped := make([]interface{}, 0, len(arr)) + for _, value := range arr { + current, err := intr.Execute(node, value) + if err != nil { + return nil, err + } + mapped = append(mapped, current) + } + return mapped, nil +} +func jpfMax(arguments []interface{}) (interface{}, error) { + if items, ok := toArrayNum(arguments[0]); ok { + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item > best { + best = item + } + } + return best, nil + } + // Otherwise we're dealing with a max() of strings. + items, _ := toArrayStr(arguments[0]) + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item > best { + best = item + } + } + return best, nil +} +func jpfMerge(arguments []interface{}) (interface{}, error) { + final := make(map[string]interface{}) + for _, m := range arguments { + mapped := m.(map[string]interface{}) + for key, value := range mapped { + final[key] = value + } + } + return final, nil +} +func jpfMaxBy(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + arr := arguments[1].([]interface{}) + exp := arguments[2].(expRef) + node := exp.ref + if len(arr) == 0 { + return nil, nil + } else if len(arr) == 1 { + return arr[0], nil + } + start, err := intr.Execute(node, arr[0]) + if err != nil { + return nil, err + } + switch t := start.(type) { + case float64: + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(float64) + if !ok { + return nil, errors.New("invalid type, must be number") + } + if current > bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + case string: + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(string) + if !ok { + return nil, errors.New("invalid type, must be string") + } + if current > bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + default: + return nil, errors.New("invalid type, must be number of string") + } +} +func jpfSum(arguments []interface{}) (interface{}, error) { + items, _ := toArrayNum(arguments[0]) + sum := 0.0 + for _, item := range items { + sum += item + } + return sum, nil +} + +func jpfMin(arguments []interface{}) (interface{}, error) { + if items, ok := toArrayNum(arguments[0]); ok { + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item < best { + best = item + } + } + return best, nil + } + items, _ := toArrayStr(arguments[0]) + if len(items) == 0 { + return nil, nil + } + if len(items) == 1 { + return items[0], nil + } + best := items[0] + for _, item := range items[1:] { + if item < best { + best = item + } + } + return best, nil +} + +func jpfMinBy(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + arr := arguments[1].([]interface{}) + exp := arguments[2].(expRef) + node := exp.ref + if len(arr) == 0 { + return nil, nil + } else if len(arr) == 1 { + return arr[0], nil + } + start, err := intr.Execute(node, arr[0]) + if err != nil { + return nil, err + } + if t, ok := start.(float64); ok { + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(float64) + if !ok { + return nil, errors.New("invalid type, must be number") + } + if current < bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + } else if t, ok := start.(string); ok { + bestVal := t + bestItem := arr[0] + for _, item := range arr[1:] { + result, err := intr.Execute(node, item) + if err != nil { + return nil, err + } + current, ok := result.(string) + if !ok { + return nil, errors.New("invalid type, must be string") + } + if current < bestVal { + bestVal = current + bestItem = item + } + } + return bestItem, nil + } else { + return nil, errors.New("invalid type, must be number of string") + } +} +func jpfType(arguments []interface{}) (interface{}, error) { + arg := arguments[0] + if _, ok := arg.(float64); ok { + return "number", nil + } + if _, ok := arg.(string); ok { + return "string", nil + } + if _, ok := arg.([]interface{}); ok { + return "array", nil + } + if _, ok := arg.(map[string]interface{}); ok { + return "object", nil + } + if arg == nil { + return "null", nil + } + if arg == true || arg == false { + return "boolean", nil + } + return nil, errors.New("unknown type") +} +func jpfKeys(arguments []interface{}) (interface{}, error) { + arg := arguments[0].(map[string]interface{}) + collected := make([]interface{}, 0, len(arg)) + for key := range arg { + collected = append(collected, key) + } + return collected, nil +} +func jpfValues(arguments []interface{}) (interface{}, error) { + arg := arguments[0].(map[string]interface{}) + collected := make([]interface{}, 0, len(arg)) + for _, value := range arg { + collected = append(collected, value) + } + return collected, nil +} +func jpfSort(arguments []interface{}) (interface{}, error) { + if items, ok := toArrayNum(arguments[0]); ok { + d := sort.Float64Slice(items) + sort.Stable(d) + final := make([]interface{}, len(d)) + for i, val := range d { + final[i] = val + } + return final, nil + } + // Otherwise we're dealing with sort()'ing strings. + items, _ := toArrayStr(arguments[0]) + d := sort.StringSlice(items) + sort.Stable(d) + final := make([]interface{}, len(d)) + for i, val := range d { + final[i] = val + } + return final, nil +} +func jpfSortBy(arguments []interface{}) (interface{}, error) { + intr := arguments[0].(*treeInterpreter) + arr := arguments[1].([]interface{}) + exp := arguments[2].(expRef) + node := exp.ref + if len(arr) == 0 { + return arr, nil + } else if len(arr) == 1 { + return arr, nil + } + start, err := intr.Execute(node, arr[0]) + if err != nil { + return nil, err + } + if _, ok := start.(float64); ok { + sortable := &byExprFloat{intr, node, arr, false} + sort.Stable(sortable) + if sortable.hasError { + return nil, errors.New("error in sort_by comparison") + } + return arr, nil + } else if _, ok := start.(string); ok { + sortable := &byExprString{intr, node, arr, false} + sort.Stable(sortable) + if sortable.hasError { + return nil, errors.New("error in sort_by comparison") + } + return arr, nil + } else { + return nil, errors.New("invalid type, must be number of string") + } +} +func jpfJoin(arguments []interface{}) (interface{}, error) { + sep := arguments[0].(string) + // We can't just do arguments[1].([]string), we have to + // manually convert each item to a string. + arrayStr := []string{} + for _, item := range arguments[1].([]interface{}) { + arrayStr = append(arrayStr, item.(string)) + } + return strings.Join(arrayStr, sep), nil +} +func jpfReverse(arguments []interface{}) (interface{}, error) { + if s, ok := arguments[0].(string); ok { + r := []rune(s) + for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { + r[i], r[j] = r[j], r[i] + } + return string(r), nil + } + items := arguments[0].([]interface{}) + length := len(items) + reversed := make([]interface{}, length) + for i, item := range items { + reversed[length-(i+1)] = item + } + return reversed, nil +} +func jpfToArray(arguments []interface{}) (interface{}, error) { + if _, ok := arguments[0].([]interface{}); ok { + return arguments[0], nil + } + return arguments[:1:1], nil +} +func jpfToString(arguments []interface{}) (interface{}, error) { + if v, ok := arguments[0].(string); ok { + return v, nil + } + result, err := json.Marshal(arguments[0]) + if err != nil { + return nil, err + } + return string(result), nil +} +func jpfToNumber(arguments []interface{}) (interface{}, error) { + arg := arguments[0] + if v, ok := arg.(float64); ok { + return v, nil + } + if v, ok := arg.(string); ok { + conv, err := strconv.ParseFloat(v, 64) + if err != nil { + return nil, nil + } + return conv, nil + } + if _, ok := arg.([]interface{}); ok { + return nil, nil + } + if _, ok := arg.(map[string]interface{}); ok { + return nil, nil + } + if arg == nil { + return nil, nil + } + if arg == true || arg == false { + return nil, nil + } + return nil, errors.New("unknown type") +} +func jpfNotNull(arguments []interface{}) (interface{}, error) { + for _, arg := range arguments { + if arg != nil { + return arg, nil + } + } + return nil, nil +} diff --git a/vendor/github.com/jmespath/go-jmespath/interpreter.go b/vendor/github.com/jmespath/go-jmespath/interpreter.go new file mode 100644 index 0000000..13c7460 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/interpreter.go @@ -0,0 +1,418 @@ +package jmespath + +import ( + "errors" + "reflect" + "unicode" + "unicode/utf8" +) + +/* This is a tree based interpreter. It walks the AST and directly + interprets the AST to search through a JSON document. +*/ + +type treeInterpreter struct { + fCall *functionCaller +} + +func newInterpreter() *treeInterpreter { + interpreter := treeInterpreter{} + interpreter.fCall = newFunctionCaller() + return &interpreter +} + +type expRef struct { + ref ASTNode +} + +// Execute takes an ASTNode and input data and interprets the AST directly. +// It will produce the result of applying the JMESPath expression associated +// with the ASTNode to the input data "value". +func (intr *treeInterpreter) Execute(node ASTNode, value interface{}) (interface{}, error) { + switch node.nodeType { + case ASTComparator: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + right, err := intr.Execute(node.children[1], value) + if err != nil { + return nil, err + } + switch node.value { + case tEQ: + return objsEqual(left, right), nil + case tNE: + return !objsEqual(left, right), nil + } + leftNum, ok := left.(float64) + if !ok { + return nil, nil + } + rightNum, ok := right.(float64) + if !ok { + return nil, nil + } + switch node.value { + case tGT: + return leftNum > rightNum, nil + case tGTE: + return leftNum >= rightNum, nil + case tLT: + return leftNum < rightNum, nil + case tLTE: + return leftNum <= rightNum, nil + } + case ASTExpRef: + return expRef{ref: node.children[0]}, nil + case ASTFunctionExpression: + resolvedArgs := []interface{}{} + for _, arg := range node.children { + current, err := intr.Execute(arg, value) + if err != nil { + return nil, err + } + resolvedArgs = append(resolvedArgs, current) + } + return intr.fCall.CallFunction(node.value.(string), resolvedArgs, intr) + case ASTField: + if m, ok := value.(map[string]interface{}); ok { + key := node.value.(string) + return m[key], nil + } + return intr.fieldFromStruct(node.value.(string), value) + case ASTFilterProjection: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, nil + } + sliceType, ok := left.([]interface{}) + if !ok { + if isSliceType(left) { + return intr.filterProjectionWithReflection(node, left) + } + return nil, nil + } + compareNode := node.children[2] + collected := []interface{}{} + for _, element := range sliceType { + result, err := intr.Execute(compareNode, element) + if err != nil { + return nil, err + } + if !isFalse(result) { + current, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + } + return collected, nil + case ASTFlatten: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, nil + } + sliceType, ok := left.([]interface{}) + if !ok { + // If we can't type convert to []interface{}, there's + // a chance this could still work via reflection if we're + // dealing with user provided types. + if isSliceType(left) { + return intr.flattenWithReflection(left) + } + return nil, nil + } + flattened := []interface{}{} + for _, element := range sliceType { + if elementSlice, ok := element.([]interface{}); ok { + flattened = append(flattened, elementSlice...) + } else if isSliceType(element) { + reflectFlat := []interface{}{} + v := reflect.ValueOf(element) + for i := 0; i < v.Len(); i++ { + reflectFlat = append(reflectFlat, v.Index(i).Interface()) + } + flattened = append(flattened, reflectFlat...) + } else { + flattened = append(flattened, element) + } + } + return flattened, nil + case ASTIdentity, ASTCurrentNode: + return value, nil + case ASTIndex: + if sliceType, ok := value.([]interface{}); ok { + index := node.value.(int) + if index < 0 { + index += len(sliceType) + } + if index < len(sliceType) && index >= 0 { + return sliceType[index], nil + } + return nil, nil + } + // Otherwise try via reflection. + rv := reflect.ValueOf(value) + if rv.Kind() == reflect.Slice { + index := node.value.(int) + if index < 0 { + index += rv.Len() + } + if index < rv.Len() && index >= 0 { + v := rv.Index(index) + return v.Interface(), nil + } + } + return nil, nil + case ASTKeyValPair: + return intr.Execute(node.children[0], value) + case ASTLiteral: + return node.value, nil + case ASTMultiSelectHash: + if value == nil { + return nil, nil + } + collected := make(map[string]interface{}) + for _, child := range node.children { + current, err := intr.Execute(child, value) + if err != nil { + return nil, err + } + key := child.value.(string) + collected[key] = current + } + return collected, nil + case ASTMultiSelectList: + if value == nil { + return nil, nil + } + collected := []interface{}{} + for _, child := range node.children { + current, err := intr.Execute(child, value) + if err != nil { + return nil, err + } + collected = append(collected, current) + } + return collected, nil + case ASTOrExpression: + matched, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + if isFalse(matched) { + matched, err = intr.Execute(node.children[1], value) + if err != nil { + return nil, err + } + } + return matched, nil + case ASTAndExpression: + matched, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + if isFalse(matched) { + return matched, nil + } + return intr.Execute(node.children[1], value) + case ASTNotExpression: + matched, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + if isFalse(matched) { + return true, nil + } + return false, nil + case ASTPipe: + result := value + var err error + for _, child := range node.children { + result, err = intr.Execute(child, result) + if err != nil { + return nil, err + } + } + return result, nil + case ASTProjection: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + sliceType, ok := left.([]interface{}) + if !ok { + if isSliceType(left) { + return intr.projectWithReflection(node, left) + } + return nil, nil + } + collected := []interface{}{} + var current interface{} + for _, element := range sliceType { + current, err = intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + return collected, nil + case ASTSubexpression, ASTIndexExpression: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, err + } + return intr.Execute(node.children[1], left) + case ASTSlice: + sliceType, ok := value.([]interface{}) + if !ok { + if isSliceType(value) { + return intr.sliceWithReflection(node, value) + } + return nil, nil + } + parts := node.value.([]*int) + sliceParams := make([]sliceParam, 3) + for i, part := range parts { + if part != nil { + sliceParams[i].Specified = true + sliceParams[i].N = *part + } + } + return slice(sliceType, sliceParams) + case ASTValueProjection: + left, err := intr.Execute(node.children[0], value) + if err != nil { + return nil, nil + } + mapType, ok := left.(map[string]interface{}) + if !ok { + return nil, nil + } + values := make([]interface{}, len(mapType)) + for _, value := range mapType { + values = append(values, value) + } + collected := []interface{}{} + for _, element := range values { + current, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + return collected, nil + } + return nil, errors.New("Unknown AST node: " + node.nodeType.String()) +} + +func (intr *treeInterpreter) fieldFromStruct(key string, value interface{}) (interface{}, error) { + rv := reflect.ValueOf(value) + first, n := utf8.DecodeRuneInString(key) + fieldName := string(unicode.ToUpper(first)) + key[n:] + if rv.Kind() == reflect.Struct { + v := rv.FieldByName(fieldName) + if !v.IsValid() { + return nil, nil + } + return v.Interface(), nil + } else if rv.Kind() == reflect.Ptr { + // Handle multiple levels of indirection? + if rv.IsNil() { + return nil, nil + } + rv = rv.Elem() + v := rv.FieldByName(fieldName) + if !v.IsValid() { + return nil, nil + } + return v.Interface(), nil + } + return nil, nil +} + +func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface{}, error) { + v := reflect.ValueOf(value) + flattened := []interface{}{} + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + if reflect.TypeOf(element).Kind() == reflect.Slice { + // Then insert the contents of the element + // slice into the flattened slice, + // i.e flattened = append(flattened, mySlice...) + elementV := reflect.ValueOf(element) + for j := 0; j < elementV.Len(); j++ { + flattened = append( + flattened, elementV.Index(j).Interface()) + } + } else { + flattened = append(flattened, element) + } + } + return flattened, nil +} + +func (intr *treeInterpreter) sliceWithReflection(node ASTNode, value interface{}) (interface{}, error) { + v := reflect.ValueOf(value) + parts := node.value.([]*int) + sliceParams := make([]sliceParam, 3) + for i, part := range parts { + if part != nil { + sliceParams[i].Specified = true + sliceParams[i].N = *part + } + } + final := []interface{}{} + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + final = append(final, element) + } + return slice(final, sliceParams) +} + +func (intr *treeInterpreter) filterProjectionWithReflection(node ASTNode, value interface{}) (interface{}, error) { + compareNode := node.children[2] + collected := []interface{}{} + v := reflect.ValueOf(value) + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + result, err := intr.Execute(compareNode, element) + if err != nil { + return nil, err + } + if !isFalse(result) { + current, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if current != nil { + collected = append(collected, current) + } + } + } + return collected, nil +} + +func (intr *treeInterpreter) projectWithReflection(node ASTNode, value interface{}) (interface{}, error) { + collected := []interface{}{} + v := reflect.ValueOf(value) + for i := 0; i < v.Len(); i++ { + element := v.Index(i).Interface() + result, err := intr.Execute(node.children[1], element) + if err != nil { + return nil, err + } + if result != nil { + collected = append(collected, result) + } + } + return collected, nil +} diff --git a/vendor/github.com/jmespath/go-jmespath/lexer.go b/vendor/github.com/jmespath/go-jmespath/lexer.go new file mode 100644 index 0000000..817900c --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/lexer.go @@ -0,0 +1,420 @@ +package jmespath + +import ( + "bytes" + "encoding/json" + "fmt" + "strconv" + "strings" + "unicode/utf8" +) + +type token struct { + tokenType tokType + value string + position int + length int +} + +type tokType int + +const eof = -1 + +// Lexer contains information about the expression being tokenized. +type Lexer struct { + expression string // The expression provided by the user. + currentPos int // The current position in the string. + lastWidth int // The width of the current rune. This + buf bytes.Buffer // Internal buffer used for building up values. +} + +// SyntaxError is the main error used whenever a lexing or parsing error occurs. +type SyntaxError struct { + msg string // Error message displayed to user + Expression string // Expression that generated a SyntaxError + Offset int // The location in the string where the error occurred +} + +func (e SyntaxError) Error() string { + // In the future, it would be good to underline the specific + // location where the error occurred. + return "SyntaxError: " + e.msg +} + +// HighlightLocation will show where the syntax error occurred. +// It will place a "^" character on a line below the expression +// at the point where the syntax error occurred. +func (e SyntaxError) HighlightLocation() string { + return e.Expression + "\n" + strings.Repeat(" ", e.Offset) + "^" +} + +//go:generate stringer -type=tokType +const ( + tUnknown tokType = iota + tStar + tDot + tFilter + tFlatten + tLparen + tRparen + tLbracket + tRbracket + tLbrace + tRbrace + tOr + tPipe + tNumber + tUnquotedIdentifier + tQuotedIdentifier + tComma + tColon + tLT + tLTE + tGT + tGTE + tEQ + tNE + tJSONLiteral + tStringLiteral + tCurrent + tExpref + tAnd + tNot + tEOF +) + +var basicTokens = map[rune]tokType{ + '.': tDot, + '*': tStar, + ',': tComma, + ':': tColon, + '{': tLbrace, + '}': tRbrace, + ']': tRbracket, // tLbracket not included because it could be "[]" + '(': tLparen, + ')': tRparen, + '@': tCurrent, +} + +// Bit mask for [a-zA-Z_] shifted down 64 bits to fit in a single uint64. +// When using this bitmask just be sure to shift the rune down 64 bits +// before checking against identifierStartBits. +const identifierStartBits uint64 = 576460745995190270 + +// Bit mask for [a-zA-Z0-9], 128 bits -> 2 uint64s. +var identifierTrailingBits = [2]uint64{287948901175001088, 576460745995190270} + +var whiteSpace = map[rune]bool{ + ' ': true, '\t': true, '\n': true, '\r': true, +} + +func (t token) String() string { + return fmt.Sprintf("Token{%+v, %s, %d, %d}", + t.tokenType, t.value, t.position, t.length) +} + +// NewLexer creates a new JMESPath lexer. +func NewLexer() *Lexer { + lexer := Lexer{} + return &lexer +} + +func (lexer *Lexer) next() rune { + if lexer.currentPos >= len(lexer.expression) { + lexer.lastWidth = 0 + return eof + } + r, w := utf8.DecodeRuneInString(lexer.expression[lexer.currentPos:]) + lexer.lastWidth = w + lexer.currentPos += w + return r +} + +func (lexer *Lexer) back() { + lexer.currentPos -= lexer.lastWidth +} + +func (lexer *Lexer) peek() rune { + t := lexer.next() + lexer.back() + return t +} + +// tokenize takes an expression and returns corresponding tokens. +func (lexer *Lexer) tokenize(expression string) ([]token, error) { + var tokens []token + lexer.expression = expression + lexer.currentPos = 0 + lexer.lastWidth = 0 +loop: + for { + r := lexer.next() + if identifierStartBits&(1<<(uint64(r)-64)) > 0 { + t := lexer.consumeUnquotedIdentifier() + tokens = append(tokens, t) + } else if val, ok := basicTokens[r]; ok { + // Basic single char token. + t := token{ + tokenType: val, + value: string(r), + position: lexer.currentPos - lexer.lastWidth, + length: 1, + } + tokens = append(tokens, t) + } else if r == '-' || (r >= '0' && r <= '9') { + t := lexer.consumeNumber() + tokens = append(tokens, t) + } else if r == '[' { + t := lexer.consumeLBracket() + tokens = append(tokens, t) + } else if r == '"' { + t, err := lexer.consumeQuotedIdentifier() + if err != nil { + return tokens, err + } + tokens = append(tokens, t) + } else if r == '\'' { + t, err := lexer.consumeRawStringLiteral() + if err != nil { + return tokens, err + } + tokens = append(tokens, t) + } else if r == '`' { + t, err := lexer.consumeLiteral() + if err != nil { + return tokens, err + } + tokens = append(tokens, t) + } else if r == '|' { + t := lexer.matchOrElse(r, '|', tOr, tPipe) + tokens = append(tokens, t) + } else if r == '<' { + t := lexer.matchOrElse(r, '=', tLTE, tLT) + tokens = append(tokens, t) + } else if r == '>' { + t := lexer.matchOrElse(r, '=', tGTE, tGT) + tokens = append(tokens, t) + } else if r == '!' { + t := lexer.matchOrElse(r, '=', tNE, tNot) + tokens = append(tokens, t) + } else if r == '=' { + t := lexer.matchOrElse(r, '=', tEQ, tUnknown) + tokens = append(tokens, t) + } else if r == '&' { + t := lexer.matchOrElse(r, '&', tAnd, tExpref) + tokens = append(tokens, t) + } else if r == eof { + break loop + } else if _, ok := whiteSpace[r]; ok { + // Ignore whitespace + } else { + return tokens, lexer.syntaxError(fmt.Sprintf("Unknown char: %s", strconv.QuoteRuneToASCII(r))) + } + } + tokens = append(tokens, token{tEOF, "", len(lexer.expression), 0}) + return tokens, nil +} + +// Consume characters until the ending rune "r" is reached. +// If the end of the expression is reached before seeing the +// terminating rune "r", then an error is returned. +// If no error occurs then the matching substring is returned. +// The returned string will not include the ending rune. +func (lexer *Lexer) consumeUntil(end rune) (string, error) { + start := lexer.currentPos + current := lexer.next() + for current != end && current != eof { + if current == '\\' && lexer.peek() != eof { + lexer.next() + } + current = lexer.next() + } + if lexer.lastWidth == 0 { + // Then we hit an EOF so we never reached the closing + // delimiter. + return "", SyntaxError{ + msg: "Unclosed delimiter: " + string(end), + Expression: lexer.expression, + Offset: len(lexer.expression), + } + } + return lexer.expression[start : lexer.currentPos-lexer.lastWidth], nil +} + +func (lexer *Lexer) consumeLiteral() (token, error) { + start := lexer.currentPos + value, err := lexer.consumeUntil('`') + if err != nil { + return token{}, err + } + value = strings.Replace(value, "\\`", "`", -1) + return token{ + tokenType: tJSONLiteral, + value: value, + position: start, + length: len(value), + }, nil +} + +func (lexer *Lexer) consumeRawStringLiteral() (token, error) { + start := lexer.currentPos + currentIndex := start + current := lexer.next() + for current != '\'' && lexer.peek() != eof { + if current == '\\' && lexer.peek() == '\'' { + chunk := lexer.expression[currentIndex : lexer.currentPos-1] + lexer.buf.WriteString(chunk) + lexer.buf.WriteString("'") + lexer.next() + currentIndex = lexer.currentPos + } + current = lexer.next() + } + if lexer.lastWidth == 0 { + // Then we hit an EOF so we never reached the closing + // delimiter. + return token{}, SyntaxError{ + msg: "Unclosed delimiter: '", + Expression: lexer.expression, + Offset: len(lexer.expression), + } + } + if currentIndex < lexer.currentPos { + lexer.buf.WriteString(lexer.expression[currentIndex : lexer.currentPos-1]) + } + value := lexer.buf.String() + // Reset the buffer so it can reused again. + lexer.buf.Reset() + return token{ + tokenType: tStringLiteral, + value: value, + position: start, + length: len(value), + }, nil +} + +func (lexer *Lexer) syntaxError(msg string) SyntaxError { + return SyntaxError{ + msg: msg, + Expression: lexer.expression, + Offset: lexer.currentPos - 1, + } +} + +// Checks for a two char token, otherwise matches a single character +// token. This is used whenever a two char token overlaps a single +// char token, e.g. "||" -> tPipe, "|" -> tOr. +func (lexer *Lexer) matchOrElse(first rune, second rune, matchedType tokType, singleCharType tokType) token { + start := lexer.currentPos - lexer.lastWidth + nextRune := lexer.next() + var t token + if nextRune == second { + t = token{ + tokenType: matchedType, + value: string(first) + string(second), + position: start, + length: 2, + } + } else { + lexer.back() + t = token{ + tokenType: singleCharType, + value: string(first), + position: start, + length: 1, + } + } + return t +} + +func (lexer *Lexer) consumeLBracket() token { + // There's three options here: + // 1. A filter expression "[?" + // 2. A flatten operator "[]" + // 3. A bare rbracket "[" + start := lexer.currentPos - lexer.lastWidth + nextRune := lexer.next() + var t token + if nextRune == '?' { + t = token{ + tokenType: tFilter, + value: "[?", + position: start, + length: 2, + } + } else if nextRune == ']' { + t = token{ + tokenType: tFlatten, + value: "[]", + position: start, + length: 2, + } + } else { + t = token{ + tokenType: tLbracket, + value: "[", + position: start, + length: 1, + } + lexer.back() + } + return t +} + +func (lexer *Lexer) consumeQuotedIdentifier() (token, error) { + start := lexer.currentPos + value, err := lexer.consumeUntil('"') + if err != nil { + return token{}, err + } + var decoded string + asJSON := []byte("\"" + value + "\"") + if err := json.Unmarshal([]byte(asJSON), &decoded); err != nil { + return token{}, err + } + return token{ + tokenType: tQuotedIdentifier, + value: decoded, + position: start - 1, + length: len(decoded), + }, nil +} + +func (lexer *Lexer) consumeUnquotedIdentifier() token { + // Consume runes until we reach the end of an unquoted + // identifier. + start := lexer.currentPos - lexer.lastWidth + for { + r := lexer.next() + if r < 0 || r > 128 || identifierTrailingBits[uint64(r)/64]&(1<<(uint64(r)%64)) == 0 { + lexer.back() + break + } + } + value := lexer.expression[start:lexer.currentPos] + return token{ + tokenType: tUnquotedIdentifier, + value: value, + position: start, + length: lexer.currentPos - start, + } +} + +func (lexer *Lexer) consumeNumber() token { + // Consume runes until we reach something that's not a number. + start := lexer.currentPos - lexer.lastWidth + for { + r := lexer.next() + if r < '0' || r > '9' { + lexer.back() + break + } + } + value := lexer.expression[start:lexer.currentPos] + return token{ + tokenType: tNumber, + value: value, + position: start, + length: lexer.currentPos - start, + } +} diff --git a/vendor/github.com/jmespath/go-jmespath/parser.go b/vendor/github.com/jmespath/go-jmespath/parser.go new file mode 100644 index 0000000..1240a17 --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/parser.go @@ -0,0 +1,603 @@ +package jmespath + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" +) + +type astNodeType int + +//go:generate stringer -type astNodeType +const ( + ASTEmpty astNodeType = iota + ASTComparator + ASTCurrentNode + ASTExpRef + ASTFunctionExpression + ASTField + ASTFilterProjection + ASTFlatten + ASTIdentity + ASTIndex + ASTIndexExpression + ASTKeyValPair + ASTLiteral + ASTMultiSelectHash + ASTMultiSelectList + ASTOrExpression + ASTAndExpression + ASTNotExpression + ASTPipe + ASTProjection + ASTSubexpression + ASTSlice + ASTValueProjection +) + +// ASTNode represents the abstract syntax tree of a JMESPath expression. +type ASTNode struct { + nodeType astNodeType + value interface{} + children []ASTNode +} + +func (node ASTNode) String() string { + return node.PrettyPrint(0) +} + +// PrettyPrint will pretty print the parsed AST. +// The AST is an implementation detail and this pretty print +// function is provided as a convenience method to help with +// debugging. You should not rely on its output as the internal +// structure of the AST may change at any time. +func (node ASTNode) PrettyPrint(indent int) string { + spaces := strings.Repeat(" ", indent) + output := fmt.Sprintf("%s%s {\n", spaces, node.nodeType) + nextIndent := indent + 2 + if node.value != nil { + if converted, ok := node.value.(fmt.Stringer); ok { + // Account for things like comparator nodes + // that are enums with a String() method. + output += fmt.Sprintf("%svalue: %s\n", strings.Repeat(" ", nextIndent), converted.String()) + } else { + output += fmt.Sprintf("%svalue: %#v\n", strings.Repeat(" ", nextIndent), node.value) + } + } + lastIndex := len(node.children) + if lastIndex > 0 { + output += fmt.Sprintf("%schildren: {\n", strings.Repeat(" ", nextIndent)) + childIndent := nextIndent + 2 + for _, elem := range node.children { + output += elem.PrettyPrint(childIndent) + } + } + output += fmt.Sprintf("%s}\n", spaces) + return output +} + +var bindingPowers = map[tokType]int{ + tEOF: 0, + tUnquotedIdentifier: 0, + tQuotedIdentifier: 0, + tRbracket: 0, + tRparen: 0, + tComma: 0, + tRbrace: 0, + tNumber: 0, + tCurrent: 0, + tExpref: 0, + tColon: 0, + tPipe: 1, + tOr: 2, + tAnd: 3, + tEQ: 5, + tLT: 5, + tLTE: 5, + tGT: 5, + tGTE: 5, + tNE: 5, + tFlatten: 9, + tStar: 20, + tFilter: 21, + tDot: 40, + tNot: 45, + tLbrace: 50, + tLbracket: 55, + tLparen: 60, +} + +// Parser holds state about the current expression being parsed. +type Parser struct { + expression string + tokens []token + index int +} + +// NewParser creates a new JMESPath parser. +func NewParser() *Parser { + p := Parser{} + return &p +} + +// Parse will compile a JMESPath expression. +func (p *Parser) Parse(expression string) (ASTNode, error) { + lexer := NewLexer() + p.expression = expression + p.index = 0 + tokens, err := lexer.tokenize(expression) + if err != nil { + return ASTNode{}, err + } + p.tokens = tokens + parsed, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if p.current() != tEOF { + return ASTNode{}, p.syntaxError(fmt.Sprintf( + "Unexpected token at the end of the expresssion: %s", p.current())) + } + return parsed, nil +} + +func (p *Parser) parseExpression(bindingPower int) (ASTNode, error) { + var err error + leftToken := p.lookaheadToken(0) + p.advance() + leftNode, err := p.nud(leftToken) + if err != nil { + return ASTNode{}, err + } + currentToken := p.current() + for bindingPower < bindingPowers[currentToken] { + p.advance() + leftNode, err = p.led(currentToken, leftNode) + if err != nil { + return ASTNode{}, err + } + currentToken = p.current() + } + return leftNode, nil +} + +func (p *Parser) parseIndexExpression() (ASTNode, error) { + if p.lookahead(0) == tColon || p.lookahead(1) == tColon { + return p.parseSliceExpression() + } + indexStr := p.lookaheadToken(0).value + parsedInt, err := strconv.Atoi(indexStr) + if err != nil { + return ASTNode{}, err + } + indexNode := ASTNode{nodeType: ASTIndex, value: parsedInt} + p.advance() + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + return indexNode, nil +} + +func (p *Parser) parseSliceExpression() (ASTNode, error) { + parts := []*int{nil, nil, nil} + index := 0 + current := p.current() + for current != tRbracket && index < 3 { + if current == tColon { + index++ + p.advance() + } else if current == tNumber { + parsedInt, err := strconv.Atoi(p.lookaheadToken(0).value) + if err != nil { + return ASTNode{}, err + } + parts[index] = &parsedInt + p.advance() + } else { + return ASTNode{}, p.syntaxError( + "Expected tColon or tNumber" + ", received: " + p.current().String()) + } + current = p.current() + } + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTSlice, + value: parts, + }, nil +} + +func (p *Parser) match(tokenType tokType) error { + if p.current() == tokenType { + p.advance() + return nil + } + return p.syntaxError("Expected " + tokenType.String() + ", received: " + p.current().String()) +} + +func (p *Parser) led(tokenType tokType, node ASTNode) (ASTNode, error) { + switch tokenType { + case tDot: + if p.current() != tStar { + right, err := p.parseDotRHS(bindingPowers[tDot]) + return ASTNode{ + nodeType: ASTSubexpression, + children: []ASTNode{node, right}, + }, err + } + p.advance() + right, err := p.parseProjectionRHS(bindingPowers[tDot]) + return ASTNode{ + nodeType: ASTValueProjection, + children: []ASTNode{node, right}, + }, err + case tPipe: + right, err := p.parseExpression(bindingPowers[tPipe]) + return ASTNode{nodeType: ASTPipe, children: []ASTNode{node, right}}, err + case tOr: + right, err := p.parseExpression(bindingPowers[tOr]) + return ASTNode{nodeType: ASTOrExpression, children: []ASTNode{node, right}}, err + case tAnd: + right, err := p.parseExpression(bindingPowers[tAnd]) + return ASTNode{nodeType: ASTAndExpression, children: []ASTNode{node, right}}, err + case tLparen: + name := node.value + var args []ASTNode + for p.current() != tRparen { + expression, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if p.current() == tComma { + if err := p.match(tComma); err != nil { + return ASTNode{}, err + } + } + args = append(args, expression) + } + if err := p.match(tRparen); err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTFunctionExpression, + value: name, + children: args, + }, nil + case tFilter: + return p.parseFilter(node) + case tFlatten: + left := ASTNode{nodeType: ASTFlatten, children: []ASTNode{node}} + right, err := p.parseProjectionRHS(bindingPowers[tFlatten]) + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{left, right}, + }, err + case tEQ, tNE, tGT, tGTE, tLT, tLTE: + right, err := p.parseExpression(bindingPowers[tokenType]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTComparator, + value: tokenType, + children: []ASTNode{node, right}, + }, nil + case tLbracket: + tokenType := p.current() + var right ASTNode + var err error + if tokenType == tNumber || tokenType == tColon { + right, err = p.parseIndexExpression() + if err != nil { + return ASTNode{}, err + } + return p.projectIfSlice(node, right) + } + // Otherwise this is a projection. + if err := p.match(tStar); err != nil { + return ASTNode{}, err + } + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + right, err = p.parseProjectionRHS(bindingPowers[tStar]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{node, right}, + }, nil + } + return ASTNode{}, p.syntaxError("Unexpected token: " + tokenType.String()) +} + +func (p *Parser) nud(token token) (ASTNode, error) { + switch token.tokenType { + case tJSONLiteral: + var parsed interface{} + err := json.Unmarshal([]byte(token.value), &parsed) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTLiteral, value: parsed}, nil + case tStringLiteral: + return ASTNode{nodeType: ASTLiteral, value: token.value}, nil + case tUnquotedIdentifier: + return ASTNode{ + nodeType: ASTField, + value: token.value, + }, nil + case tQuotedIdentifier: + node := ASTNode{nodeType: ASTField, value: token.value} + if p.current() == tLparen { + return ASTNode{}, p.syntaxErrorToken("Can't have quoted identifier as function name.", token) + } + return node, nil + case tStar: + left := ASTNode{nodeType: ASTIdentity} + var right ASTNode + var err error + if p.current() == tRbracket { + right = ASTNode{nodeType: ASTIdentity} + } else { + right, err = p.parseProjectionRHS(bindingPowers[tStar]) + } + return ASTNode{nodeType: ASTValueProjection, children: []ASTNode{left, right}}, err + case tFilter: + return p.parseFilter(ASTNode{nodeType: ASTIdentity}) + case tLbrace: + return p.parseMultiSelectHash() + case tFlatten: + left := ASTNode{ + nodeType: ASTFlatten, + children: []ASTNode{{nodeType: ASTIdentity}}, + } + right, err := p.parseProjectionRHS(bindingPowers[tFlatten]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTProjection, children: []ASTNode{left, right}}, nil + case tLbracket: + tokenType := p.current() + //var right ASTNode + if tokenType == tNumber || tokenType == tColon { + right, err := p.parseIndexExpression() + if err != nil { + return ASTNode{}, nil + } + return p.projectIfSlice(ASTNode{nodeType: ASTIdentity}, right) + } else if tokenType == tStar && p.lookahead(1) == tRbracket { + p.advance() + p.advance() + right, err := p.parseProjectionRHS(bindingPowers[tStar]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{{nodeType: ASTIdentity}, right}, + }, nil + } else { + return p.parseMultiSelectList() + } + case tCurrent: + return ASTNode{nodeType: ASTCurrentNode}, nil + case tExpref: + expression, err := p.parseExpression(bindingPowers[tExpref]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTExpRef, children: []ASTNode{expression}}, nil + case tNot: + expression, err := p.parseExpression(bindingPowers[tNot]) + if err != nil { + return ASTNode{}, err + } + return ASTNode{nodeType: ASTNotExpression, children: []ASTNode{expression}}, nil + case tLparen: + expression, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if err := p.match(tRparen); err != nil { + return ASTNode{}, err + } + return expression, nil + case tEOF: + return ASTNode{}, p.syntaxErrorToken("Incomplete expression", token) + } + + return ASTNode{}, p.syntaxErrorToken("Invalid token: "+token.tokenType.String(), token) +} + +func (p *Parser) parseMultiSelectList() (ASTNode, error) { + var expressions []ASTNode + for { + expression, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + expressions = append(expressions, expression) + if p.current() == tRbracket { + break + } + err = p.match(tComma) + if err != nil { + return ASTNode{}, err + } + } + err := p.match(tRbracket) + if err != nil { + return ASTNode{}, err + } + return ASTNode{ + nodeType: ASTMultiSelectList, + children: expressions, + }, nil +} + +func (p *Parser) parseMultiSelectHash() (ASTNode, error) { + var children []ASTNode + for { + keyToken := p.lookaheadToken(0) + if err := p.match(tUnquotedIdentifier); err != nil { + if err := p.match(tQuotedIdentifier); err != nil { + return ASTNode{}, p.syntaxError("Expected tQuotedIdentifier or tUnquotedIdentifier") + } + } + keyName := keyToken.value + err := p.match(tColon) + if err != nil { + return ASTNode{}, err + } + value, err := p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + node := ASTNode{ + nodeType: ASTKeyValPair, + value: keyName, + children: []ASTNode{value}, + } + children = append(children, node) + if p.current() == tComma { + err := p.match(tComma) + if err != nil { + return ASTNode{}, nil + } + } else if p.current() == tRbrace { + err := p.match(tRbrace) + if err != nil { + return ASTNode{}, nil + } + break + } + } + return ASTNode{ + nodeType: ASTMultiSelectHash, + children: children, + }, nil +} + +func (p *Parser) projectIfSlice(left ASTNode, right ASTNode) (ASTNode, error) { + indexExpr := ASTNode{ + nodeType: ASTIndexExpression, + children: []ASTNode{left, right}, + } + if right.nodeType == ASTSlice { + right, err := p.parseProjectionRHS(bindingPowers[tStar]) + return ASTNode{ + nodeType: ASTProjection, + children: []ASTNode{indexExpr, right}, + }, err + } + return indexExpr, nil +} +func (p *Parser) parseFilter(node ASTNode) (ASTNode, error) { + var right, condition ASTNode + var err error + condition, err = p.parseExpression(0) + if err != nil { + return ASTNode{}, err + } + if err := p.match(tRbracket); err != nil { + return ASTNode{}, err + } + if p.current() == tFlatten { + right = ASTNode{nodeType: ASTIdentity} + } else { + right, err = p.parseProjectionRHS(bindingPowers[tFilter]) + if err != nil { + return ASTNode{}, err + } + } + + return ASTNode{ + nodeType: ASTFilterProjection, + children: []ASTNode{node, right, condition}, + }, nil +} + +func (p *Parser) parseDotRHS(bindingPower int) (ASTNode, error) { + lookahead := p.current() + if tokensOneOf([]tokType{tQuotedIdentifier, tUnquotedIdentifier, tStar}, lookahead) { + return p.parseExpression(bindingPower) + } else if lookahead == tLbracket { + if err := p.match(tLbracket); err != nil { + return ASTNode{}, err + } + return p.parseMultiSelectList() + } else if lookahead == tLbrace { + if err := p.match(tLbrace); err != nil { + return ASTNode{}, err + } + return p.parseMultiSelectHash() + } + return ASTNode{}, p.syntaxError("Expected identifier, lbracket, or lbrace") +} + +func (p *Parser) parseProjectionRHS(bindingPower int) (ASTNode, error) { + current := p.current() + if bindingPowers[current] < 10 { + return ASTNode{nodeType: ASTIdentity}, nil + } else if current == tLbracket { + return p.parseExpression(bindingPower) + } else if current == tFilter { + return p.parseExpression(bindingPower) + } else if current == tDot { + err := p.match(tDot) + if err != nil { + return ASTNode{}, err + } + return p.parseDotRHS(bindingPower) + } else { + return ASTNode{}, p.syntaxError("Error") + } +} + +func (p *Parser) lookahead(number int) tokType { + return p.lookaheadToken(number).tokenType +} + +func (p *Parser) current() tokType { + return p.lookahead(0) +} + +func (p *Parser) lookaheadToken(number int) token { + return p.tokens[p.index+number] +} + +func (p *Parser) advance() { + p.index++ +} + +func tokensOneOf(elements []tokType, token tokType) bool { + for _, elem := range elements { + if elem == token { + return true + } + } + return false +} + +func (p *Parser) syntaxError(msg string) SyntaxError { + return SyntaxError{ + msg: msg, + Expression: p.expression, + Offset: p.lookaheadToken(0).position, + } +} + +// Create a SyntaxError based on the provided token. +// This differs from syntaxError() which creates a SyntaxError +// based on the current lookahead token. +func (p *Parser) syntaxErrorToken(msg string, t token) SyntaxError { + return SyntaxError{ + msg: msg, + Expression: p.expression, + Offset: t.position, + } +} diff --git a/vendor/github.com/jmespath/go-jmespath/toktype_string.go b/vendor/github.com/jmespath/go-jmespath/toktype_string.go new file mode 100644 index 0000000..dae79cb --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/toktype_string.go @@ -0,0 +1,16 @@ +// generated by stringer -type=tokType; DO NOT EDIT + +package jmespath + +import "fmt" + +const _tokType_name = "tUnknowntStartDottFiltertFlattentLparentRparentLbrackettRbrackettLbracetRbracetOrtPipetNumbertUnquotedIdentifiertQuotedIdentifiertCommatColontLTtLTEtGTtGTEtEQtNEtJSONLiteraltStringLiteraltCurrenttExpreftAndtNottEOF" + +var _tokType_index = [...]uint8{0, 8, 13, 17, 24, 32, 39, 46, 55, 64, 71, 78, 81, 86, 93, 112, 129, 135, 141, 144, 148, 151, 155, 158, 161, 173, 187, 195, 202, 206, 210, 214} + +func (i tokType) String() string { + if i < 0 || i >= tokType(len(_tokType_index)-1) { + return fmt.Sprintf("tokType(%d)", i) + } + return _tokType_name[_tokType_index[i]:_tokType_index[i+1]] +} diff --git a/vendor/github.com/jmespath/go-jmespath/util.go b/vendor/github.com/jmespath/go-jmespath/util.go new file mode 100644 index 0000000..ddc1b7d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/util.go @@ -0,0 +1,185 @@ +package jmespath + +import ( + "errors" + "reflect" +) + +// IsFalse determines if an object is false based on the JMESPath spec. +// JMESPath defines false values to be any of: +// - An empty string array, or hash. +// - The boolean value false. +// - nil +func isFalse(value interface{}) bool { + switch v := value.(type) { + case bool: + return !v + case []interface{}: + return len(v) == 0 + case map[string]interface{}: + return len(v) == 0 + case string: + return len(v) == 0 + case nil: + return true + } + // Try the reflection cases before returning false. + rv := reflect.ValueOf(value) + switch rv.Kind() { + case reflect.Struct: + // A struct type will never be false, even if + // all of its values are the zero type. + return false + case reflect.Slice, reflect.Map: + return rv.Len() == 0 + case reflect.Ptr: + if rv.IsNil() { + return true + } + // If it's a pointer type, we'll try to deref the pointer + // and evaluate the pointer value for isFalse. + element := rv.Elem() + return isFalse(element.Interface()) + } + return false +} + +// ObjsEqual is a generic object equality check. +// It will take two arbitrary objects and recursively determine +// if they are equal. +func objsEqual(left interface{}, right interface{}) bool { + return reflect.DeepEqual(left, right) +} + +// SliceParam refers to a single part of a slice. +// A slice consists of a start, a stop, and a step, similar to +// python slices. +type sliceParam struct { + N int + Specified bool +} + +// Slice supports [start:stop:step] style slicing that's supported in JMESPath. +func slice(slice []interface{}, parts []sliceParam) ([]interface{}, error) { + computed, err := computeSliceParams(len(slice), parts) + if err != nil { + return nil, err + } + start, stop, step := computed[0], computed[1], computed[2] + result := []interface{}{} + if step > 0 { + for i := start; i < stop; i += step { + result = append(result, slice[i]) + } + } else { + for i := start; i > stop; i += step { + result = append(result, slice[i]) + } + } + return result, nil +} + +func computeSliceParams(length int, parts []sliceParam) ([]int, error) { + var start, stop, step int + if !parts[2].Specified { + step = 1 + } else if parts[2].N == 0 { + return nil, errors.New("Invalid slice, step cannot be 0") + } else { + step = parts[2].N + } + var stepValueNegative bool + if step < 0 { + stepValueNegative = true + } else { + stepValueNegative = false + } + + if !parts[0].Specified { + if stepValueNegative { + start = length - 1 + } else { + start = 0 + } + } else { + start = capSlice(length, parts[0].N, step) + } + + if !parts[1].Specified { + if stepValueNegative { + stop = -1 + } else { + stop = length + } + } else { + stop = capSlice(length, parts[1].N, step) + } + return []int{start, stop, step}, nil +} + +func capSlice(length int, actual int, step int) int { + if actual < 0 { + actual += length + if actual < 0 { + if step < 0 { + actual = -1 + } else { + actual = 0 + } + } + } else if actual >= length { + if step < 0 { + actual = length - 1 + } else { + actual = length + } + } + return actual +} + +// ToArrayNum converts an empty interface type to a slice of float64. +// If any element in the array cannot be converted, then nil is returned +// along with a second value of false. +func toArrayNum(data interface{}) ([]float64, bool) { + // Is there a better way to do this with reflect? + if d, ok := data.([]interface{}); ok { + result := make([]float64, len(d)) + for i, el := range d { + item, ok := el.(float64) + if !ok { + return nil, false + } + result[i] = item + } + return result, true + } + return nil, false +} + +// ToArrayStr converts an empty interface type to a slice of strings. +// If any element in the array cannot be converted, then nil is returned +// along with a second value of false. If the input data could be entirely +// converted, then the converted data, along with a second value of true, +// will be returned. +func toArrayStr(data interface{}) ([]string, bool) { + // Is there a better way to do this with reflect? + if d, ok := data.([]interface{}); ok { + result := make([]string, len(d)) + for i, el := range d { + item, ok := el.(string) + if !ok { + return nil, false + } + result[i] = item + } + return result, true + } + return nil, false +} + +func isSliceType(v interface{}) bool { + if v == nil { + return false + } + return reflect.TypeOf(v).Kind() == reflect.Slice +} diff --git a/vendor/github.com/json-iterator/go/.codecov.yml b/vendor/github.com/json-iterator/go/.codecov.yml new file mode 100644 index 0000000..955dc0b --- /dev/null +++ b/vendor/github.com/json-iterator/go/.codecov.yml @@ -0,0 +1,3 @@ +ignore: + - "output_tests/.*" + diff --git a/vendor/github.com/json-iterator/go/.gitignore b/vendor/github.com/json-iterator/go/.gitignore new file mode 100644 index 0000000..1555653 --- /dev/null +++ b/vendor/github.com/json-iterator/go/.gitignore @@ -0,0 +1,4 @@ +/vendor +/bug_test.go +/coverage.txt +/.idea diff --git a/vendor/github.com/json-iterator/go/.travis.yml b/vendor/github.com/json-iterator/go/.travis.yml new file mode 100644 index 0000000..449e67c --- /dev/null +++ b/vendor/github.com/json-iterator/go/.travis.yml @@ -0,0 +1,14 @@ +language: go + +go: + - 1.8.x + - 1.x + +before_install: + - go get -t -v ./... + +script: + - ./test.sh + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/json-iterator/go/Gopkg.lock b/vendor/github.com/json-iterator/go/Gopkg.lock new file mode 100644 index 0000000..c8a9fbb --- /dev/null +++ b/vendor/github.com/json-iterator/go/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/modern-go/concurrent" + packages = ["."] + revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a" + version = "1.0.0" + +[[projects]] + name = "github.com/modern-go/reflect2" + packages = ["."] + revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" + version = "1.0.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ea54a775e5a354cb015502d2e7aa4b74230fc77e894f34a838b268c25ec8eeb8" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/json-iterator/go/Gopkg.toml b/vendor/github.com/json-iterator/go/Gopkg.toml new file mode 100644 index 0000000..313a0f8 --- /dev/null +++ b/vendor/github.com/json-iterator/go/Gopkg.toml @@ -0,0 +1,26 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + +ignored = ["github.com/davecgh/go-spew*","github.com/google/gofuzz*","github.com/stretchr/testify*"] + +[[constraint]] + name = "github.com/modern-go/reflect2" + version = "1.0.1" diff --git a/vendor/github.com/json-iterator/go/LICENSE b/vendor/github.com/json-iterator/go/LICENSE new file mode 100644 index 0000000..2cf4f5a --- /dev/null +++ b/vendor/github.com/json-iterator/go/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 json-iterator + +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. diff --git a/vendor/github.com/json-iterator/go/README.md b/vendor/github.com/json-iterator/go/README.md new file mode 100644 index 0000000..54d5afe --- /dev/null +++ b/vendor/github.com/json-iterator/go/README.md @@ -0,0 +1,91 @@ +[![Sourcegraph](https://sourcegraph.com/github.com/json-iterator/go/-/badge.svg)](https://sourcegraph.com/github.com/json-iterator/go?badge) +[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/json-iterator/go) +[![Build Status](https://travis-ci.org/json-iterator/go.svg?branch=master)](https://travis-ci.org/json-iterator/go) +[![codecov](https://codecov.io/gh/json-iterator/go/branch/master/graph/badge.svg)](https://codecov.io/gh/json-iterator/go) +[![rcard](https://goreportcard.com/badge/github.com/json-iterator/go)](https://goreportcard.com/report/github.com/json-iterator/go) +[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/json-iterator/go/master/LICENSE) +[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby) + +A high-performance 100% compatible drop-in replacement of "encoding/json" + +You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go) + +``` +Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com +``` + +# Benchmark + +![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png) + +Source code: https://github.com/json-iterator/go-benchmark/blob/master/src/github.com/json-iterator/go-benchmark/benchmark_medium_payload_test.go + +Raw Result (easyjson requires static code generation) + +| | ns/op | allocation bytes | allocation times | +| --- | --- | --- | --- | +| std decode | 35510 ns/op | 1960 B/op | 99 allocs/op | +| easyjson decode | 8499 ns/op | 160 B/op | 4 allocs/op | +| jsoniter decode | 5623 ns/op | 160 B/op | 3 allocs/op | +| std encode | 2213 ns/op | 712 B/op | 5 allocs/op | +| easyjson encode | 883 ns/op | 576 B/op | 3 allocs/op | +| jsoniter encode | 837 ns/op | 384 B/op | 4 allocs/op | + +Always benchmark with your own workload. +The result depends heavily on the data input. + +# Usage + +100% compatibility with standard lib + +Replace + +```go +import "encoding/json" +json.Marshal(&data) +``` + +with + +```go +import "github.com/json-iterator/go" + +var json = jsoniter.ConfigCompatibleWithStandardLibrary +json.Marshal(&data) +``` + +Replace + +```go +import "encoding/json" +json.Unmarshal(input, &data) +``` + +with + +```go +import "github.com/json-iterator/go" + +var json = jsoniter.ConfigCompatibleWithStandardLibrary +json.Unmarshal(input, &data) +``` + +[More documentation](http://jsoniter.com/migrate-from-go-std.html) + +# How to get + +``` +go get github.com/json-iterator/go +``` + +# Contribution Welcomed ! + +Contributors + +* [thockin](https://github.com/thockin) +* [mattn](https://github.com/mattn) +* [cch123](https://github.com/cch123) +* [Oleg Shaldybin](https://github.com/olegshaldybin) +* [Jason Toffaletti](https://github.com/toffaletti) + +Report issue or pull request, or email taowen@gmail.com, or [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby) diff --git a/vendor/github.com/json-iterator/go/adapter.go b/vendor/github.com/json-iterator/go/adapter.go new file mode 100644 index 0000000..e674d0f --- /dev/null +++ b/vendor/github.com/json-iterator/go/adapter.go @@ -0,0 +1,150 @@ +package jsoniter + +import ( + "bytes" + "io" +) + +// RawMessage to make replace json with jsoniter +type RawMessage []byte + +// Unmarshal adapts to json/encoding Unmarshal API +// +// Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. +// Refer to https://godoc.org/encoding/json#Unmarshal for more information +func Unmarshal(data []byte, v interface{}) error { + return ConfigDefault.Unmarshal(data, v) +} + +// UnmarshalFromString convenient method to read from string instead of []byte +func UnmarshalFromString(str string, v interface{}) error { + return ConfigDefault.UnmarshalFromString(str, v) +} + +// Get quick method to get value from deeply nested JSON structure +func Get(data []byte, path ...interface{}) Any { + return ConfigDefault.Get(data, path...) +} + +// Marshal adapts to json/encoding Marshal API +// +// Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API +// Refer to https://godoc.org/encoding/json#Marshal for more information +func Marshal(v interface{}) ([]byte, error) { + return ConfigDefault.Marshal(v) +} + +// MarshalIndent same as json.MarshalIndent. Prefix is not supported. +func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + return ConfigDefault.MarshalIndent(v, prefix, indent) +} + +// MarshalToString convenient method to write as string instead of []byte +func MarshalToString(v interface{}) (string, error) { + return ConfigDefault.MarshalToString(v) +} + +// NewDecoder adapts to json/stream NewDecoder API. +// +// NewDecoder returns a new decoder that reads from r. +// +// Instead of a json/encoding Decoder, an Decoder is returned +// Refer to https://godoc.org/encoding/json#NewDecoder for more information +func NewDecoder(reader io.Reader) *Decoder { + return ConfigDefault.NewDecoder(reader) +} + +// Decoder reads and decodes JSON values from an input stream. +// Decoder provides identical APIs with json/stream Decoder (Token() and UseNumber() are in progress) +type Decoder struct { + iter *Iterator +} + +// Decode decode JSON into interface{} +func (adapter *Decoder) Decode(obj interface{}) error { + if adapter.iter.head == adapter.iter.tail && adapter.iter.reader != nil { + if !adapter.iter.loadMore() { + return io.EOF + } + } + adapter.iter.ReadVal(obj) + err := adapter.iter.Error + if err == io.EOF { + return nil + } + return adapter.iter.Error +} + +// More is there more? +func (adapter *Decoder) More() bool { + iter := adapter.iter + if iter.Error != nil { + return false + } + c := iter.nextToken() + if c == 0 { + return false + } + iter.unreadByte() + return c != ']' && c != '}' +} + +// Buffered remaining buffer +func (adapter *Decoder) Buffered() io.Reader { + remaining := adapter.iter.buf[adapter.iter.head:adapter.iter.tail] + return bytes.NewReader(remaining) +} + +// UseNumber causes the Decoder to unmarshal a number into an interface{} as a +// Number instead of as a float64. +func (adapter *Decoder) UseNumber() { + cfg := adapter.iter.cfg.configBeforeFrozen + cfg.UseNumber = true + adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions) +} + +// DisallowUnknownFields causes the Decoder to return an error when the destination +// is a struct and the input contains object keys which do not match any +// non-ignored, exported fields in the destination. +func (adapter *Decoder) DisallowUnknownFields() { + cfg := adapter.iter.cfg.configBeforeFrozen + cfg.DisallowUnknownFields = true + adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions) +} + +// NewEncoder same as json.NewEncoder +func NewEncoder(writer io.Writer) *Encoder { + return ConfigDefault.NewEncoder(writer) +} + +// Encoder same as json.Encoder +type Encoder struct { + stream *Stream +} + +// Encode encode interface{} as JSON to io.Writer +func (adapter *Encoder) Encode(val interface{}) error { + adapter.stream.WriteVal(val) + adapter.stream.WriteRaw("\n") + adapter.stream.Flush() + return adapter.stream.Error +} + +// SetIndent set the indention. Prefix is not supported +func (adapter *Encoder) SetIndent(prefix, indent string) { + config := adapter.stream.cfg.configBeforeFrozen + config.IndentionStep = len(indent) + adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions) +} + +// SetEscapeHTML escape html by default, set to false to disable +func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) { + config := adapter.stream.cfg.configBeforeFrozen + config.EscapeHTML = escapeHTML + adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions) +} + +// Valid reports whether data is a valid JSON encoding. +func Valid(data []byte) bool { + return ConfigDefault.Valid(data) +} diff --git a/vendor/github.com/json-iterator/go/any.go b/vendor/github.com/json-iterator/go/any.go new file mode 100644 index 0000000..daecfed --- /dev/null +++ b/vendor/github.com/json-iterator/go/any.go @@ -0,0 +1,321 @@ +package jsoniter + +import ( + "errors" + "fmt" + "github.com/modern-go/reflect2" + "io" + "reflect" + "strconv" + "unsafe" +) + +// Any generic object representation. +// The lazy json implementation holds []byte and parse lazily. +type Any interface { + LastError() error + ValueType() ValueType + MustBeValid() Any + ToBool() bool + ToInt() int + ToInt32() int32 + ToInt64() int64 + ToUint() uint + ToUint32() uint32 + ToUint64() uint64 + ToFloat32() float32 + ToFloat64() float64 + ToString() string + ToVal(val interface{}) + Get(path ...interface{}) Any + Size() int + Keys() []string + GetInterface() interface{} + WriteTo(stream *Stream) +} + +type baseAny struct{} + +func (any *baseAny) Get(path ...interface{}) Any { + return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)} +} + +func (any *baseAny) Size() int { + return 0 +} + +func (any *baseAny) Keys() []string { + return []string{} +} + +func (any *baseAny) ToVal(obj interface{}) { + panic("not implemented") +} + +// WrapInt32 turn int32 into Any interface +func WrapInt32(val int32) Any { + return &int32Any{baseAny{}, val} +} + +// WrapInt64 turn int64 into Any interface +func WrapInt64(val int64) Any { + return &int64Any{baseAny{}, val} +} + +// WrapUint32 turn uint32 into Any interface +func WrapUint32(val uint32) Any { + return &uint32Any{baseAny{}, val} +} + +// WrapUint64 turn uint64 into Any interface +func WrapUint64(val uint64) Any { + return &uint64Any{baseAny{}, val} +} + +// WrapFloat64 turn float64 into Any interface +func WrapFloat64(val float64) Any { + return &floatAny{baseAny{}, val} +} + +// WrapString turn string into Any interface +func WrapString(val string) Any { + return &stringAny{baseAny{}, val} +} + +// Wrap turn a go object into Any interface +func Wrap(val interface{}) Any { + if val == nil { + return &nilAny{} + } + asAny, isAny := val.(Any) + if isAny { + return asAny + } + typ := reflect2.TypeOf(val) + switch typ.Kind() { + case reflect.Slice: + return wrapArray(val) + case reflect.Struct: + return wrapStruct(val) + case reflect.Map: + return wrapMap(val) + case reflect.String: + return WrapString(val.(string)) + case reflect.Int: + if strconv.IntSize == 32 { + return WrapInt32(int32(val.(int))) + } + return WrapInt64(int64(val.(int))) + case reflect.Int8: + return WrapInt32(int32(val.(int8))) + case reflect.Int16: + return WrapInt32(int32(val.(int16))) + case reflect.Int32: + return WrapInt32(val.(int32)) + case reflect.Int64: + return WrapInt64(val.(int64)) + case reflect.Uint: + if strconv.IntSize == 32 { + return WrapUint32(uint32(val.(uint))) + } + return WrapUint64(uint64(val.(uint))) + case reflect.Uintptr: + if ptrSize == 32 { + return WrapUint32(uint32(val.(uintptr))) + } + return WrapUint64(uint64(val.(uintptr))) + case reflect.Uint8: + return WrapUint32(uint32(val.(uint8))) + case reflect.Uint16: + return WrapUint32(uint32(val.(uint16))) + case reflect.Uint32: + return WrapUint32(uint32(val.(uint32))) + case reflect.Uint64: + return WrapUint64(val.(uint64)) + case reflect.Float32: + return WrapFloat64(float64(val.(float32))) + case reflect.Float64: + return WrapFloat64(val.(float64)) + case reflect.Bool: + if val.(bool) == true { + return &trueAny{} + } + return &falseAny{} + } + return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", typ)} +} + +// ReadAny read next JSON element as an Any object. It is a better json.RawMessage. +func (iter *Iterator) ReadAny() Any { + return iter.readAny() +} + +func (iter *Iterator) readAny() Any { + c := iter.nextToken() + switch c { + case '"': + iter.unreadByte() + return &stringAny{baseAny{}, iter.ReadString()} + case 'n': + iter.skipThreeBytes('u', 'l', 'l') // null + return &nilAny{} + case 't': + iter.skipThreeBytes('r', 'u', 'e') // true + return &trueAny{} + case 'f': + iter.skipFourBytes('a', 'l', 's', 'e') // false + return &falseAny{} + case '{': + return iter.readObjectAny() + case '[': + return iter.readArrayAny() + case '-': + return iter.readNumberAny(false) + case 0: + return &invalidAny{baseAny{}, errors.New("input is empty")} + default: + return iter.readNumberAny(true) + } +} + +func (iter *Iterator) readNumberAny(positive bool) Any { + iter.startCapture(iter.head - 1) + iter.skipNumber() + lazyBuf := iter.stopCapture() + return &numberLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} +} + +func (iter *Iterator) readObjectAny() Any { + iter.startCapture(iter.head - 1) + iter.skipObject() + lazyBuf := iter.stopCapture() + return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} +} + +func (iter *Iterator) readArrayAny() Any { + iter.startCapture(iter.head - 1) + iter.skipArray() + lazyBuf := iter.stopCapture() + return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} +} + +func locateObjectField(iter *Iterator, target string) []byte { + var found []byte + iter.ReadObjectCB(func(iter *Iterator, field string) bool { + if field == target { + found = iter.SkipAndReturnBytes() + return false + } + iter.Skip() + return true + }) + return found +} + +func locateArrayElement(iter *Iterator, target int) []byte { + var found []byte + n := 0 + iter.ReadArrayCB(func(iter *Iterator) bool { + if n == target { + found = iter.SkipAndReturnBytes() + return false + } + iter.Skip() + n++ + return true + }) + return found +} + +func locatePath(iter *Iterator, path []interface{}) Any { + for i, pathKeyObj := range path { + switch pathKey := pathKeyObj.(type) { + case string: + valueBytes := locateObjectField(iter, pathKey) + if valueBytes == nil { + return newInvalidAny(path[i:]) + } + iter.ResetBytes(valueBytes) + case int: + valueBytes := locateArrayElement(iter, pathKey) + if valueBytes == nil { + return newInvalidAny(path[i:]) + } + iter.ResetBytes(valueBytes) + case int32: + if '*' == pathKey { + return iter.readAny().Get(path[i:]...) + } + return newInvalidAny(path[i:]) + default: + return newInvalidAny(path[i:]) + } + } + if iter.Error != nil && iter.Error != io.EOF { + return &invalidAny{baseAny{}, iter.Error} + } + return iter.readAny() +} + +var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem() + +func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ == anyType { + return &directAnyCodec{} + } + if typ.Implements(anyType) { + return &anyCodec{ + valType: typ, + } + } + return nil +} + +func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ == anyType { + return &directAnyCodec{} + } + if typ.Implements(anyType) { + return &anyCodec{ + valType: typ, + } + } + return nil +} + +type anyCodec struct { + valType reflect2.Type +} + +func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + panic("not implemented") +} + +func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := codec.valType.UnsafeIndirect(ptr) + any := obj.(Any) + any.WriteTo(stream) +} + +func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool { + obj := codec.valType.UnsafeIndirect(ptr) + any := obj.(Any) + return any.Size() == 0 +} + +type directAnyCodec struct { +} + +func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *(*Any)(ptr) = iter.readAny() +} + +func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + any := *(*Any)(ptr) + any.WriteTo(stream) +} + +func (codec *directAnyCodec) IsEmpty(ptr unsafe.Pointer) bool { + any := *(*Any)(ptr) + return any.Size() == 0 +} diff --git a/vendor/github.com/json-iterator/go/any_array.go b/vendor/github.com/json-iterator/go/any_array.go new file mode 100644 index 0000000..0449e9a --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_array.go @@ -0,0 +1,278 @@ +package jsoniter + +import ( + "reflect" + "unsafe" +) + +type arrayLazyAny struct { + baseAny + cfg *frozenConfig + buf []byte + err error +} + +func (any *arrayLazyAny) ValueType() ValueType { + return ArrayValue +} + +func (any *arrayLazyAny) MustBeValid() Any { + return any +} + +func (any *arrayLazyAny) LastError() error { + return any.err +} + +func (any *arrayLazyAny) ToBool() bool { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.ReadArray() +} + +func (any *arrayLazyAny) ToInt() int { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToInt32() int32 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToInt64() int64 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToUint() uint { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToUint32() uint32 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToUint64() uint64 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToFloat32() float32 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToFloat64() float64 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToString() string { + return *(*string)(unsafe.Pointer(&any.buf)) +} + +func (any *arrayLazyAny) ToVal(val interface{}) { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadVal(val) +} + +func (any *arrayLazyAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case int: + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + valueBytes := locateArrayElement(iter, firstPath) + if valueBytes == nil { + return newInvalidAny(path) + } + iter.ResetBytes(valueBytes) + return locatePath(iter, path[1:]) + case int32: + if '*' == firstPath { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + arr := make([]Any, 0) + iter.ReadArrayCB(func(iter *Iterator) bool { + found := iter.readAny().Get(path[1:]...) + if found.ValueType() != InvalidValue { + arr = append(arr, found) + } + return true + }) + return wrapArray(arr) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *arrayLazyAny) Size() int { + size := 0 + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadArrayCB(func(iter *Iterator) bool { + size++ + iter.Skip() + return true + }) + return size +} + +func (any *arrayLazyAny) WriteTo(stream *Stream) { + stream.Write(any.buf) +} + +func (any *arrayLazyAny) GetInterface() interface{} { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.Read() +} + +type arrayAny struct { + baseAny + val reflect.Value +} + +func wrapArray(val interface{}) *arrayAny { + return &arrayAny{baseAny{}, reflect.ValueOf(val)} +} + +func (any *arrayAny) ValueType() ValueType { + return ArrayValue +} + +func (any *arrayAny) MustBeValid() Any { + return any +} + +func (any *arrayAny) LastError() error { + return nil +} + +func (any *arrayAny) ToBool() bool { + return any.val.Len() != 0 +} + +func (any *arrayAny) ToInt() int { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToInt32() int32 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToInt64() int64 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToUint() uint { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToUint32() uint32 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToUint64() uint64 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToFloat32() float32 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToFloat64() float64 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToString() string { + str, _ := MarshalToString(any.val.Interface()) + return str +} + +func (any *arrayAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case int: + if firstPath < 0 || firstPath >= any.val.Len() { + return newInvalidAny(path) + } + return Wrap(any.val.Index(firstPath).Interface()) + case int32: + if '*' == firstPath { + mappedAll := make([]Any, 0) + for i := 0; i < any.val.Len(); i++ { + mapped := Wrap(any.val.Index(i).Interface()).Get(path[1:]...) + if mapped.ValueType() != InvalidValue { + mappedAll = append(mappedAll, mapped) + } + } + return wrapArray(mappedAll) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *arrayAny) Size() int { + return any.val.Len() +} + +func (any *arrayAny) WriteTo(stream *Stream) { + stream.WriteVal(any.val) +} + +func (any *arrayAny) GetInterface() interface{} { + return any.val.Interface() +} diff --git a/vendor/github.com/json-iterator/go/any_bool.go b/vendor/github.com/json-iterator/go/any_bool.go new file mode 100644 index 0000000..9452324 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_bool.go @@ -0,0 +1,137 @@ +package jsoniter + +type trueAny struct { + baseAny +} + +func (any *trueAny) LastError() error { + return nil +} + +func (any *trueAny) ToBool() bool { + return true +} + +func (any *trueAny) ToInt() int { + return 1 +} + +func (any *trueAny) ToInt32() int32 { + return 1 +} + +func (any *trueAny) ToInt64() int64 { + return 1 +} + +func (any *trueAny) ToUint() uint { + return 1 +} + +func (any *trueAny) ToUint32() uint32 { + return 1 +} + +func (any *trueAny) ToUint64() uint64 { + return 1 +} + +func (any *trueAny) ToFloat32() float32 { + return 1 +} + +func (any *trueAny) ToFloat64() float64 { + return 1 +} + +func (any *trueAny) ToString() string { + return "true" +} + +func (any *trueAny) WriteTo(stream *Stream) { + stream.WriteTrue() +} + +func (any *trueAny) Parse() *Iterator { + return nil +} + +func (any *trueAny) GetInterface() interface{} { + return true +} + +func (any *trueAny) ValueType() ValueType { + return BoolValue +} + +func (any *trueAny) MustBeValid() Any { + return any +} + +type falseAny struct { + baseAny +} + +func (any *falseAny) LastError() error { + return nil +} + +func (any *falseAny) ToBool() bool { + return false +} + +func (any *falseAny) ToInt() int { + return 0 +} + +func (any *falseAny) ToInt32() int32 { + return 0 +} + +func (any *falseAny) ToInt64() int64 { + return 0 +} + +func (any *falseAny) ToUint() uint { + return 0 +} + +func (any *falseAny) ToUint32() uint32 { + return 0 +} + +func (any *falseAny) ToUint64() uint64 { + return 0 +} + +func (any *falseAny) ToFloat32() float32 { + return 0 +} + +func (any *falseAny) ToFloat64() float64 { + return 0 +} + +func (any *falseAny) ToString() string { + return "false" +} + +func (any *falseAny) WriteTo(stream *Stream) { + stream.WriteFalse() +} + +func (any *falseAny) Parse() *Iterator { + return nil +} + +func (any *falseAny) GetInterface() interface{} { + return false +} + +func (any *falseAny) ValueType() ValueType { + return BoolValue +} + +func (any *falseAny) MustBeValid() Any { + return any +} diff --git a/vendor/github.com/json-iterator/go/any_float.go b/vendor/github.com/json-iterator/go/any_float.go new file mode 100644 index 0000000..35fdb09 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_float.go @@ -0,0 +1,83 @@ +package jsoniter + +import ( + "strconv" +) + +type floatAny struct { + baseAny + val float64 +} + +func (any *floatAny) Parse() *Iterator { + return nil +} + +func (any *floatAny) ValueType() ValueType { + return NumberValue +} + +func (any *floatAny) MustBeValid() Any { + return any +} + +func (any *floatAny) LastError() error { + return nil +} + +func (any *floatAny) ToBool() bool { + return any.ToFloat64() != 0 +} + +func (any *floatAny) ToInt() int { + return int(any.val) +} + +func (any *floatAny) ToInt32() int32 { + return int32(any.val) +} + +func (any *floatAny) ToInt64() int64 { + return int64(any.val) +} + +func (any *floatAny) ToUint() uint { + if any.val > 0 { + return uint(any.val) + } + return 0 +} + +func (any *floatAny) ToUint32() uint32 { + if any.val > 0 { + return uint32(any.val) + } + return 0 +} + +func (any *floatAny) ToUint64() uint64 { + if any.val > 0 { + return uint64(any.val) + } + return 0 +} + +func (any *floatAny) ToFloat32() float32 { + return float32(any.val) +} + +func (any *floatAny) ToFloat64() float64 { + return any.val +} + +func (any *floatAny) ToString() string { + return strconv.FormatFloat(any.val, 'E', -1, 64) +} + +func (any *floatAny) WriteTo(stream *Stream) { + stream.WriteFloat64(any.val) +} + +func (any *floatAny) GetInterface() interface{} { + return any.val +} diff --git a/vendor/github.com/json-iterator/go/any_int32.go b/vendor/github.com/json-iterator/go/any_int32.go new file mode 100644 index 0000000..1b56f39 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_int32.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type int32Any struct { + baseAny + val int32 +} + +func (any *int32Any) LastError() error { + return nil +} + +func (any *int32Any) ValueType() ValueType { + return NumberValue +} + +func (any *int32Any) MustBeValid() Any { + return any +} + +func (any *int32Any) ToBool() bool { + return any.val != 0 +} + +func (any *int32Any) ToInt() int { + return int(any.val) +} + +func (any *int32Any) ToInt32() int32 { + return any.val +} + +func (any *int32Any) ToInt64() int64 { + return int64(any.val) +} + +func (any *int32Any) ToUint() uint { + return uint(any.val) +} + +func (any *int32Any) ToUint32() uint32 { + return uint32(any.val) +} + +func (any *int32Any) ToUint64() uint64 { + return uint64(any.val) +} + +func (any *int32Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *int32Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *int32Any) ToString() string { + return strconv.FormatInt(int64(any.val), 10) +} + +func (any *int32Any) WriteTo(stream *Stream) { + stream.WriteInt32(any.val) +} + +func (any *int32Any) Parse() *Iterator { + return nil +} + +func (any *int32Any) GetInterface() interface{} { + return any.val +} diff --git a/vendor/github.com/json-iterator/go/any_int64.go b/vendor/github.com/json-iterator/go/any_int64.go new file mode 100644 index 0000000..c440d72 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_int64.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type int64Any struct { + baseAny + val int64 +} + +func (any *int64Any) LastError() error { + return nil +} + +func (any *int64Any) ValueType() ValueType { + return NumberValue +} + +func (any *int64Any) MustBeValid() Any { + return any +} + +func (any *int64Any) ToBool() bool { + return any.val != 0 +} + +func (any *int64Any) ToInt() int { + return int(any.val) +} + +func (any *int64Any) ToInt32() int32 { + return int32(any.val) +} + +func (any *int64Any) ToInt64() int64 { + return any.val +} + +func (any *int64Any) ToUint() uint { + return uint(any.val) +} + +func (any *int64Any) ToUint32() uint32 { + return uint32(any.val) +} + +func (any *int64Any) ToUint64() uint64 { + return uint64(any.val) +} + +func (any *int64Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *int64Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *int64Any) ToString() string { + return strconv.FormatInt(any.val, 10) +} + +func (any *int64Any) WriteTo(stream *Stream) { + stream.WriteInt64(any.val) +} + +func (any *int64Any) Parse() *Iterator { + return nil +} + +func (any *int64Any) GetInterface() interface{} { + return any.val +} diff --git a/vendor/github.com/json-iterator/go/any_invalid.go b/vendor/github.com/json-iterator/go/any_invalid.go new file mode 100644 index 0000000..1d859ea --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_invalid.go @@ -0,0 +1,82 @@ +package jsoniter + +import "fmt" + +type invalidAny struct { + baseAny + err error +} + +func newInvalidAny(path []interface{}) *invalidAny { + return &invalidAny{baseAny{}, fmt.Errorf("%v not found", path)} +} + +func (any *invalidAny) LastError() error { + return any.err +} + +func (any *invalidAny) ValueType() ValueType { + return InvalidValue +} + +func (any *invalidAny) MustBeValid() Any { + panic(any.err) +} + +func (any *invalidAny) ToBool() bool { + return false +} + +func (any *invalidAny) ToInt() int { + return 0 +} + +func (any *invalidAny) ToInt32() int32 { + return 0 +} + +func (any *invalidAny) ToInt64() int64 { + return 0 +} + +func (any *invalidAny) ToUint() uint { + return 0 +} + +func (any *invalidAny) ToUint32() uint32 { + return 0 +} + +func (any *invalidAny) ToUint64() uint64 { + return 0 +} + +func (any *invalidAny) ToFloat32() float32 { + return 0 +} + +func (any *invalidAny) ToFloat64() float64 { + return 0 +} + +func (any *invalidAny) ToString() string { + return "" +} + +func (any *invalidAny) WriteTo(stream *Stream) { +} + +func (any *invalidAny) Get(path ...interface{}) Any { + if any.err == nil { + return &invalidAny{baseAny{}, fmt.Errorf("get %v from invalid", path)} + } + return &invalidAny{baseAny{}, fmt.Errorf("%v, get %v from invalid", any.err, path)} +} + +func (any *invalidAny) Parse() *Iterator { + return nil +} + +func (any *invalidAny) GetInterface() interface{} { + return nil +} diff --git a/vendor/github.com/json-iterator/go/any_nil.go b/vendor/github.com/json-iterator/go/any_nil.go new file mode 100644 index 0000000..d04cb54 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_nil.go @@ -0,0 +1,69 @@ +package jsoniter + +type nilAny struct { + baseAny +} + +func (any *nilAny) LastError() error { + return nil +} + +func (any *nilAny) ValueType() ValueType { + return NilValue +} + +func (any *nilAny) MustBeValid() Any { + return any +} + +func (any *nilAny) ToBool() bool { + return false +} + +func (any *nilAny) ToInt() int { + return 0 +} + +func (any *nilAny) ToInt32() int32 { + return 0 +} + +func (any *nilAny) ToInt64() int64 { + return 0 +} + +func (any *nilAny) ToUint() uint { + return 0 +} + +func (any *nilAny) ToUint32() uint32 { + return 0 +} + +func (any *nilAny) ToUint64() uint64 { + return 0 +} + +func (any *nilAny) ToFloat32() float32 { + return 0 +} + +func (any *nilAny) ToFloat64() float64 { + return 0 +} + +func (any *nilAny) ToString() string { + return "" +} + +func (any *nilAny) WriteTo(stream *Stream) { + stream.WriteNil() +} + +func (any *nilAny) Parse() *Iterator { + return nil +} + +func (any *nilAny) GetInterface() interface{} { + return nil +} diff --git a/vendor/github.com/json-iterator/go/any_number.go b/vendor/github.com/json-iterator/go/any_number.go new file mode 100644 index 0000000..9d1e901 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_number.go @@ -0,0 +1,123 @@ +package jsoniter + +import ( + "io" + "unsafe" +) + +type numberLazyAny struct { + baseAny + cfg *frozenConfig + buf []byte + err error +} + +func (any *numberLazyAny) ValueType() ValueType { + return NumberValue +} + +func (any *numberLazyAny) MustBeValid() Any { + return any +} + +func (any *numberLazyAny) LastError() error { + return any.err +} + +func (any *numberLazyAny) ToBool() bool { + return any.ToFloat64() != 0 +} + +func (any *numberLazyAny) ToInt() int { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadInt() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToInt32() int32 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadInt32() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToInt64() int64 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadInt64() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToUint() uint { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadUint() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToUint32() uint32 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadUint32() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToUint64() uint64 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadUint64() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToFloat32() float32 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadFloat32() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToFloat64() float64 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadFloat64() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToString() string { + return *(*string)(unsafe.Pointer(&any.buf)) +} + +func (any *numberLazyAny) WriteTo(stream *Stream) { + stream.Write(any.buf) +} + +func (any *numberLazyAny) GetInterface() interface{} { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.Read() +} diff --git a/vendor/github.com/json-iterator/go/any_object.go b/vendor/github.com/json-iterator/go/any_object.go new file mode 100644 index 0000000..c44ef5c --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_object.go @@ -0,0 +1,374 @@ +package jsoniter + +import ( + "reflect" + "unsafe" +) + +type objectLazyAny struct { + baseAny + cfg *frozenConfig + buf []byte + err error +} + +func (any *objectLazyAny) ValueType() ValueType { + return ObjectValue +} + +func (any *objectLazyAny) MustBeValid() Any { + return any +} + +func (any *objectLazyAny) LastError() error { + return any.err +} + +func (any *objectLazyAny) ToBool() bool { + return true +} + +func (any *objectLazyAny) ToInt() int { + return 0 +} + +func (any *objectLazyAny) ToInt32() int32 { + return 0 +} + +func (any *objectLazyAny) ToInt64() int64 { + return 0 +} + +func (any *objectLazyAny) ToUint() uint { + return 0 +} + +func (any *objectLazyAny) ToUint32() uint32 { + return 0 +} + +func (any *objectLazyAny) ToUint64() uint64 { + return 0 +} + +func (any *objectLazyAny) ToFloat32() float32 { + return 0 +} + +func (any *objectLazyAny) ToFloat64() float64 { + return 0 +} + +func (any *objectLazyAny) ToString() string { + return *(*string)(unsafe.Pointer(&any.buf)) +} + +func (any *objectLazyAny) ToVal(obj interface{}) { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadVal(obj) +} + +func (any *objectLazyAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case string: + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + valueBytes := locateObjectField(iter, firstPath) + if valueBytes == nil { + return newInvalidAny(path) + } + iter.ResetBytes(valueBytes) + return locatePath(iter, path[1:]) + case int32: + if '*' == firstPath { + mappedAll := map[string]Any{} + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadMapCB(func(iter *Iterator, field string) bool { + mapped := locatePath(iter, path[1:]) + if mapped.ValueType() != InvalidValue { + mappedAll[field] = mapped + } + return true + }) + return wrapMap(mappedAll) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *objectLazyAny) Keys() []string { + keys := []string{} + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadMapCB(func(iter *Iterator, field string) bool { + iter.Skip() + keys = append(keys, field) + return true + }) + return keys +} + +func (any *objectLazyAny) Size() int { + size := 0 + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadObjectCB(func(iter *Iterator, field string) bool { + iter.Skip() + size++ + return true + }) + return size +} + +func (any *objectLazyAny) WriteTo(stream *Stream) { + stream.Write(any.buf) +} + +func (any *objectLazyAny) GetInterface() interface{} { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.Read() +} + +type objectAny struct { + baseAny + err error + val reflect.Value +} + +func wrapStruct(val interface{}) *objectAny { + return &objectAny{baseAny{}, nil, reflect.ValueOf(val)} +} + +func (any *objectAny) ValueType() ValueType { + return ObjectValue +} + +func (any *objectAny) MustBeValid() Any { + return any +} + +func (any *objectAny) Parse() *Iterator { + return nil +} + +func (any *objectAny) LastError() error { + return any.err +} + +func (any *objectAny) ToBool() bool { + return any.val.NumField() != 0 +} + +func (any *objectAny) ToInt() int { + return 0 +} + +func (any *objectAny) ToInt32() int32 { + return 0 +} + +func (any *objectAny) ToInt64() int64 { + return 0 +} + +func (any *objectAny) ToUint() uint { + return 0 +} + +func (any *objectAny) ToUint32() uint32 { + return 0 +} + +func (any *objectAny) ToUint64() uint64 { + return 0 +} + +func (any *objectAny) ToFloat32() float32 { + return 0 +} + +func (any *objectAny) ToFloat64() float64 { + return 0 +} + +func (any *objectAny) ToString() string { + str, err := MarshalToString(any.val.Interface()) + any.err = err + return str +} + +func (any *objectAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case string: + field := any.val.FieldByName(firstPath) + if !field.IsValid() { + return newInvalidAny(path) + } + return Wrap(field.Interface()) + case int32: + if '*' == firstPath { + mappedAll := map[string]Any{} + for i := 0; i < any.val.NumField(); i++ { + field := any.val.Field(i) + if field.CanInterface() { + mapped := Wrap(field.Interface()).Get(path[1:]...) + if mapped.ValueType() != InvalidValue { + mappedAll[any.val.Type().Field(i).Name] = mapped + } + } + } + return wrapMap(mappedAll) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *objectAny) Keys() []string { + keys := make([]string, 0, any.val.NumField()) + for i := 0; i < any.val.NumField(); i++ { + keys = append(keys, any.val.Type().Field(i).Name) + } + return keys +} + +func (any *objectAny) Size() int { + return any.val.NumField() +} + +func (any *objectAny) WriteTo(stream *Stream) { + stream.WriteVal(any.val) +} + +func (any *objectAny) GetInterface() interface{} { + return any.val.Interface() +} + +type mapAny struct { + baseAny + err error + val reflect.Value +} + +func wrapMap(val interface{}) *mapAny { + return &mapAny{baseAny{}, nil, reflect.ValueOf(val)} +} + +func (any *mapAny) ValueType() ValueType { + return ObjectValue +} + +func (any *mapAny) MustBeValid() Any { + return any +} + +func (any *mapAny) Parse() *Iterator { + return nil +} + +func (any *mapAny) LastError() error { + return any.err +} + +func (any *mapAny) ToBool() bool { + return true +} + +func (any *mapAny) ToInt() int { + return 0 +} + +func (any *mapAny) ToInt32() int32 { + return 0 +} + +func (any *mapAny) ToInt64() int64 { + return 0 +} + +func (any *mapAny) ToUint() uint { + return 0 +} + +func (any *mapAny) ToUint32() uint32 { + return 0 +} + +func (any *mapAny) ToUint64() uint64 { + return 0 +} + +func (any *mapAny) ToFloat32() float32 { + return 0 +} + +func (any *mapAny) ToFloat64() float64 { + return 0 +} + +func (any *mapAny) ToString() string { + str, err := MarshalToString(any.val.Interface()) + any.err = err + return str +} + +func (any *mapAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case int32: + if '*' == firstPath { + mappedAll := map[string]Any{} + for _, key := range any.val.MapKeys() { + keyAsStr := key.String() + element := Wrap(any.val.MapIndex(key).Interface()) + mapped := element.Get(path[1:]...) + if mapped.ValueType() != InvalidValue { + mappedAll[keyAsStr] = mapped + } + } + return wrapMap(mappedAll) + } + return newInvalidAny(path) + default: + value := any.val.MapIndex(reflect.ValueOf(firstPath)) + if !value.IsValid() { + return newInvalidAny(path) + } + return Wrap(value.Interface()) + } +} + +func (any *mapAny) Keys() []string { + keys := make([]string, 0, any.val.Len()) + for _, key := range any.val.MapKeys() { + keys = append(keys, key.String()) + } + return keys +} + +func (any *mapAny) Size() int { + return any.val.Len() +} + +func (any *mapAny) WriteTo(stream *Stream) { + stream.WriteVal(any.val) +} + +func (any *mapAny) GetInterface() interface{} { + return any.val.Interface() +} diff --git a/vendor/github.com/json-iterator/go/any_str.go b/vendor/github.com/json-iterator/go/any_str.go new file mode 100644 index 0000000..a4b93c7 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_str.go @@ -0,0 +1,166 @@ +package jsoniter + +import ( + "fmt" + "strconv" +) + +type stringAny struct { + baseAny + val string +} + +func (any *stringAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)} +} + +func (any *stringAny) Parse() *Iterator { + return nil +} + +func (any *stringAny) ValueType() ValueType { + return StringValue +} + +func (any *stringAny) MustBeValid() Any { + return any +} + +func (any *stringAny) LastError() error { + return nil +} + +func (any *stringAny) ToBool() bool { + str := any.ToString() + if str == "0" { + return false + } + for _, c := range str { + switch c { + case ' ', '\n', '\r', '\t': + default: + return true + } + } + return false +} + +func (any *stringAny) ToInt() int { + return int(any.ToInt64()) + +} + +func (any *stringAny) ToInt32() int32 { + return int32(any.ToInt64()) +} + +func (any *stringAny) ToInt64() int64 { + if any.val == "" { + return 0 + } + + flag := 1 + startPos := 0 + endPos := 0 + if any.val[0] == '+' || any.val[0] == '-' { + startPos = 1 + } + + if any.val[0] == '-' { + flag = -1 + } + + for i := startPos; i < len(any.val); i++ { + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + break + } + } + parsed, _ := strconv.ParseInt(any.val[startPos:endPos], 10, 64) + return int64(flag) * parsed +} + +func (any *stringAny) ToUint() uint { + return uint(any.ToUint64()) +} + +func (any *stringAny) ToUint32() uint32 { + return uint32(any.ToUint64()) +} + +func (any *stringAny) ToUint64() uint64 { + if any.val == "" { + return 0 + } + + startPos := 0 + endPos := 0 + + if any.val[0] == '-' { + return 0 + } + if any.val[0] == '+' { + startPos = 1 + } + + for i := startPos; i < len(any.val); i++ { + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + break + } + } + parsed, _ := strconv.ParseUint(any.val[startPos:endPos], 10, 64) + return parsed +} + +func (any *stringAny) ToFloat32() float32 { + return float32(any.ToFloat64()) +} + +func (any *stringAny) ToFloat64() float64 { + if len(any.val) == 0 { + return 0 + } + + // first char invalid + if any.val[0] != '+' && any.val[0] != '-' && (any.val[0] > '9' || any.val[0] < '0') { + return 0 + } + + // extract valid num expression from string + // eg 123true => 123, -12.12xxa => -12.12 + endPos := 1 + for i := 1; i < len(any.val); i++ { + if any.val[i] == '.' || any.val[i] == 'e' || any.val[i] == 'E' || any.val[i] == '+' || any.val[i] == '-' { + endPos = i + 1 + continue + } + + // end position is the first char which is not digit + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + endPos = i + break + } + } + parsed, _ := strconv.ParseFloat(any.val[:endPos], 64) + return parsed +} + +func (any *stringAny) ToString() string { + return any.val +} + +func (any *stringAny) WriteTo(stream *Stream) { + stream.WriteString(any.val) +} + +func (any *stringAny) GetInterface() interface{} { + return any.val +} diff --git a/vendor/github.com/json-iterator/go/any_uint32.go b/vendor/github.com/json-iterator/go/any_uint32.go new file mode 100644 index 0000000..656bbd3 --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_uint32.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type uint32Any struct { + baseAny + val uint32 +} + +func (any *uint32Any) LastError() error { + return nil +} + +func (any *uint32Any) ValueType() ValueType { + return NumberValue +} + +func (any *uint32Any) MustBeValid() Any { + return any +} + +func (any *uint32Any) ToBool() bool { + return any.val != 0 +} + +func (any *uint32Any) ToInt() int { + return int(any.val) +} + +func (any *uint32Any) ToInt32() int32 { + return int32(any.val) +} + +func (any *uint32Any) ToInt64() int64 { + return int64(any.val) +} + +func (any *uint32Any) ToUint() uint { + return uint(any.val) +} + +func (any *uint32Any) ToUint32() uint32 { + return any.val +} + +func (any *uint32Any) ToUint64() uint64 { + return uint64(any.val) +} + +func (any *uint32Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *uint32Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *uint32Any) ToString() string { + return strconv.FormatInt(int64(any.val), 10) +} + +func (any *uint32Any) WriteTo(stream *Stream) { + stream.WriteUint32(any.val) +} + +func (any *uint32Any) Parse() *Iterator { + return nil +} + +func (any *uint32Any) GetInterface() interface{} { + return any.val +} diff --git a/vendor/github.com/json-iterator/go/any_uint64.go b/vendor/github.com/json-iterator/go/any_uint64.go new file mode 100644 index 0000000..7df2fce --- /dev/null +++ b/vendor/github.com/json-iterator/go/any_uint64.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type uint64Any struct { + baseAny + val uint64 +} + +func (any *uint64Any) LastError() error { + return nil +} + +func (any *uint64Any) ValueType() ValueType { + return NumberValue +} + +func (any *uint64Any) MustBeValid() Any { + return any +} + +func (any *uint64Any) ToBool() bool { + return any.val != 0 +} + +func (any *uint64Any) ToInt() int { + return int(any.val) +} + +func (any *uint64Any) ToInt32() int32 { + return int32(any.val) +} + +func (any *uint64Any) ToInt64() int64 { + return int64(any.val) +} + +func (any *uint64Any) ToUint() uint { + return uint(any.val) +} + +func (any *uint64Any) ToUint32() uint32 { + return uint32(any.val) +} + +func (any *uint64Any) ToUint64() uint64 { + return any.val +} + +func (any *uint64Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *uint64Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *uint64Any) ToString() string { + return strconv.FormatUint(any.val, 10) +} + +func (any *uint64Any) WriteTo(stream *Stream) { + stream.WriteUint64(any.val) +} + +func (any *uint64Any) Parse() *Iterator { + return nil +} + +func (any *uint64Any) GetInterface() interface{} { + return any.val +} diff --git a/vendor/github.com/json-iterator/go/build.sh b/vendor/github.com/json-iterator/go/build.sh new file mode 100644 index 0000000..b45ef68 --- /dev/null +++ b/vendor/github.com/json-iterator/go/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e +set -x + +if [ ! -d /tmp/build-golang/src/github.com/json-iterator ]; then + mkdir -p /tmp/build-golang/src/github.com/json-iterator + ln -s $PWD /tmp/build-golang/src/github.com/json-iterator/go +fi +export GOPATH=/tmp/build-golang +go get -u github.com/golang/dep/cmd/dep +cd /tmp/build-golang/src/github.com/json-iterator/go +exec $GOPATH/bin/dep ensure -update diff --git a/vendor/github.com/json-iterator/go/config.go b/vendor/github.com/json-iterator/go/config.go new file mode 100644 index 0000000..8c58fcb --- /dev/null +++ b/vendor/github.com/json-iterator/go/config.go @@ -0,0 +1,375 @@ +package jsoniter + +import ( + "encoding/json" + "io" + "reflect" + "sync" + "unsafe" + + "github.com/modern-go/concurrent" + "github.com/modern-go/reflect2" +) + +// Config customize how the API should behave. +// The API is created from Config by Froze. +type Config struct { + IndentionStep int + MarshalFloatWith6Digits bool + EscapeHTML bool + SortMapKeys bool + UseNumber bool + DisallowUnknownFields bool + TagKey string + OnlyTaggedField bool + ValidateJsonRawMessage bool + ObjectFieldMustBeSimpleString bool + CaseSensitive bool +} + +// API the public interface of this package. +// Primary Marshal and Unmarshal. +type API interface { + IteratorPool + StreamPool + MarshalToString(v interface{}) (string, error) + Marshal(v interface{}) ([]byte, error) + MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) + UnmarshalFromString(str string, v interface{}) error + Unmarshal(data []byte, v interface{}) error + Get(data []byte, path ...interface{}) Any + NewEncoder(writer io.Writer) *Encoder + NewDecoder(reader io.Reader) *Decoder + Valid(data []byte) bool + RegisterExtension(extension Extension) + DecoderOf(typ reflect2.Type) ValDecoder + EncoderOf(typ reflect2.Type) ValEncoder +} + +// ConfigDefault the default API +var ConfigDefault = Config{ + EscapeHTML: true, +}.Froze() + +// ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior +var ConfigCompatibleWithStandardLibrary = Config{ + EscapeHTML: true, + SortMapKeys: true, + ValidateJsonRawMessage: true, +}.Froze() + +// ConfigFastest marshals float with only 6 digits precision +var ConfigFastest = Config{ + EscapeHTML: false, + MarshalFloatWith6Digits: true, // will lose precession + ObjectFieldMustBeSimpleString: true, // do not unescape object field +}.Froze() + +type frozenConfig struct { + configBeforeFrozen Config + sortMapKeys bool + indentionStep int + objectFieldMustBeSimpleString bool + onlyTaggedField bool + disallowUnknownFields bool + decoderCache *concurrent.Map + encoderCache *concurrent.Map + encoderExtension Extension + decoderExtension Extension + extraExtensions []Extension + streamPool *sync.Pool + iteratorPool *sync.Pool + caseSensitive bool +} + +func (cfg *frozenConfig) initCache() { + cfg.decoderCache = concurrent.NewMap() + cfg.encoderCache = concurrent.NewMap() +} + +func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) { + cfg.decoderCache.Store(cacheKey, decoder) +} + +func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) { + cfg.encoderCache.Store(cacheKey, encoder) +} + +func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder { + decoder, found := cfg.decoderCache.Load(cacheKey) + if found { + return decoder.(ValDecoder) + } + return nil +} + +func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder { + encoder, found := cfg.encoderCache.Load(cacheKey) + if found { + return encoder.(ValEncoder) + } + return nil +} + +var cfgCache = concurrent.NewMap() + +func getFrozenConfigFromCache(cfg Config) *frozenConfig { + obj, found := cfgCache.Load(cfg) + if found { + return obj.(*frozenConfig) + } + return nil +} + +func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) { + cfgCache.Store(cfg, frozenConfig) +} + +// Froze forge API from config +func (cfg Config) Froze() API { + api := &frozenConfig{ + sortMapKeys: cfg.SortMapKeys, + indentionStep: cfg.IndentionStep, + objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString, + onlyTaggedField: cfg.OnlyTaggedField, + disallowUnknownFields: cfg.DisallowUnknownFields, + caseSensitive: cfg.CaseSensitive, + } + api.streamPool = &sync.Pool{ + New: func() interface{} { + return NewStream(api, nil, 512) + }, + } + api.iteratorPool = &sync.Pool{ + New: func() interface{} { + return NewIterator(api) + }, + } + api.initCache() + encoderExtension := EncoderExtension{} + decoderExtension := DecoderExtension{} + if cfg.MarshalFloatWith6Digits { + api.marshalFloatWith6Digits(encoderExtension) + } + if cfg.EscapeHTML { + api.escapeHTML(encoderExtension) + } + if cfg.UseNumber { + api.useNumber(decoderExtension) + } + if cfg.ValidateJsonRawMessage { + api.validateJsonRawMessage(encoderExtension) + } + api.encoderExtension = encoderExtension + api.decoderExtension = decoderExtension + api.configBeforeFrozen = cfg + return api +} + +func (cfg Config) frozeWithCacheReuse(extraExtensions []Extension) *frozenConfig { + api := getFrozenConfigFromCache(cfg) + if api != nil { + return api + } + api = cfg.Froze().(*frozenConfig) + for _, extension := range extraExtensions { + api.RegisterExtension(extension) + } + addFrozenConfigToCache(cfg, api) + return api +} + +func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) { + encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) { + rawMessage := *(*json.RawMessage)(ptr) + iter := cfg.BorrowIterator([]byte(rawMessage)) + iter.Read() + if iter.Error != nil { + stream.WriteRaw("null") + } else { + cfg.ReturnIterator(iter) + stream.WriteRaw(string(rawMessage)) + } + }, func(ptr unsafe.Pointer) bool { + return len(*((*json.RawMessage)(ptr))) == 0 + }} + extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder + extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder +} + +func (cfg *frozenConfig) useNumber(extension DecoderExtension) { + extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) { + exitingValue := *((*interface{})(ptr)) + if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr { + iter.ReadVal(exitingValue) + return + } + if iter.WhatIsNext() == NumberValue { + *((*interface{})(ptr)) = json.Number(iter.readNumberAsString()) + } else { + *((*interface{})(ptr)) = iter.Read() + } + }} +} +func (cfg *frozenConfig) getTagKey() string { + tagKey := cfg.configBeforeFrozen.TagKey + if tagKey == "" { + return "json" + } + return tagKey +} + +func (cfg *frozenConfig) RegisterExtension(extension Extension) { + cfg.extraExtensions = append(cfg.extraExtensions, extension) + copied := cfg.configBeforeFrozen + cfg.configBeforeFrozen = copied +} + +type lossyFloat32Encoder struct { +} + +func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat32Lossy(*((*float32)(ptr))) +} + +func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float32)(ptr)) == 0 +} + +type lossyFloat64Encoder struct { +} + +func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat64Lossy(*((*float64)(ptr))) +} + +func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float64)(ptr)) == 0 +} + +// EnableLossyFloatMarshalling keeps 10**(-6) precision +// for float variables for better performance. +func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) { + // for better performance + extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{} + extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{} +} + +type htmlEscapedStringEncoder struct { +} + +func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + str := *((*string)(ptr)) + stream.WriteStringWithHTMLEscaped(str) +} + +func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*string)(ptr)) == "" +} + +func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) { + encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{} +} + +func (cfg *frozenConfig) cleanDecoders() { + typeDecoders = map[string]ValDecoder{} + fieldDecoders = map[string]ValDecoder{} + *cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) +} + +func (cfg *frozenConfig) cleanEncoders() { + typeEncoders = map[string]ValEncoder{} + fieldEncoders = map[string]ValEncoder{} + *cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) +} + +func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) { + stream := cfg.BorrowStream(nil) + defer cfg.ReturnStream(stream) + stream.WriteVal(v) + if stream.Error != nil { + return "", stream.Error + } + return string(stream.Buffer()), nil +} + +func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) { + stream := cfg.BorrowStream(nil) + defer cfg.ReturnStream(stream) + stream.WriteVal(v) + if stream.Error != nil { + return nil, stream.Error + } + result := stream.Buffer() + copied := make([]byte, len(result)) + copy(copied, result) + return copied, nil +} + +func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + if prefix != "" { + panic("prefix is not supported") + } + for _, r := range indent { + if r != ' ' { + panic("indent can only be space") + } + } + newCfg := cfg.configBeforeFrozen + newCfg.IndentionStep = len(indent) + return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v) +} + +func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error { + data := []byte(str) + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + iter.ReadVal(v) + c := iter.nextToken() + if c == 0 { + if iter.Error == io.EOF { + return nil + } + return iter.Error + } + iter.ReportError("Unmarshal", "there are bytes left after unmarshal") + return iter.Error +} + +func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any { + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + return locatePath(iter, path) +} + +func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error { + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + iter.ReadVal(v) + c := iter.nextToken() + if c == 0 { + if iter.Error == io.EOF { + return nil + } + return iter.Error + } + iter.ReportError("Unmarshal", "there are bytes left after unmarshal") + return iter.Error +} + +func (cfg *frozenConfig) NewEncoder(writer io.Writer) *Encoder { + stream := NewStream(cfg, writer, 512) + return &Encoder{stream} +} + +func (cfg *frozenConfig) NewDecoder(reader io.Reader) *Decoder { + iter := Parse(cfg, reader, 512) + return &Decoder{iter} +} + +func (cfg *frozenConfig) Valid(data []byte) bool { + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + iter.Skip() + return iter.Error == nil +} diff --git a/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md b/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md new file mode 100644 index 0000000..3095662 --- /dev/null +++ b/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md @@ -0,0 +1,7 @@ +| json type \ dest type | bool | int | uint | float |string| +| --- | --- | --- | --- |--|--| +| number | positive => true
negative => true
zero => false| 23.2 => 23
-32.1 => -32| 12.1 => 12
-12.1 => 0|as normal|same as origin| +| string | empty string => false
string "0" => false
other strings => true | "123.32" => 123
"-123.4" => -123
"123.23xxxw" => 123
"abcde12" => 0
"-32.1" => -32| 13.2 => 13
-1.1 => 0 |12.1 => 12.1
-12.3 => -12.3
12.4xxa => 12.4
+1.1e2 =>110 |same as origin| +| bool | true => true
false => false| true => 1
false => 0 | true => 1
false => 0 |true => 1
false => 0|true => "true"
false => "false"| +| object | true | 0 | 0 |0|originnal json| +| array | empty array => false
nonempty array => true| [] => 0
[1,2] => 1 | [] => 0
[1,2] => 1 |[] => 0
[1,2] => 1|original json| \ No newline at end of file diff --git a/vendor/github.com/json-iterator/go/iter.go b/vendor/github.com/json-iterator/go/iter.go new file mode 100644 index 0000000..95ae54f --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter.go @@ -0,0 +1,322 @@ +package jsoniter + +import ( + "encoding/json" + "fmt" + "io" +) + +// ValueType the type for JSON element +type ValueType int + +const ( + // InvalidValue invalid JSON element + InvalidValue ValueType = iota + // StringValue JSON element "string" + StringValue + // NumberValue JSON element 100 or 0.10 + NumberValue + // NilValue JSON element null + NilValue + // BoolValue JSON element true or false + BoolValue + // ArrayValue JSON element [] + ArrayValue + // ObjectValue JSON element {} + ObjectValue +) + +var hexDigits []byte +var valueTypes []ValueType + +func init() { + hexDigits = make([]byte, 256) + for i := 0; i < len(hexDigits); i++ { + hexDigits[i] = 255 + } + for i := '0'; i <= '9'; i++ { + hexDigits[i] = byte(i - '0') + } + for i := 'a'; i <= 'f'; i++ { + hexDigits[i] = byte((i - 'a') + 10) + } + for i := 'A'; i <= 'F'; i++ { + hexDigits[i] = byte((i - 'A') + 10) + } + valueTypes = make([]ValueType, 256) + for i := 0; i < len(valueTypes); i++ { + valueTypes[i] = InvalidValue + } + valueTypes['"'] = StringValue + valueTypes['-'] = NumberValue + valueTypes['0'] = NumberValue + valueTypes['1'] = NumberValue + valueTypes['2'] = NumberValue + valueTypes['3'] = NumberValue + valueTypes['4'] = NumberValue + valueTypes['5'] = NumberValue + valueTypes['6'] = NumberValue + valueTypes['7'] = NumberValue + valueTypes['8'] = NumberValue + valueTypes['9'] = NumberValue + valueTypes['t'] = BoolValue + valueTypes['f'] = BoolValue + valueTypes['n'] = NilValue + valueTypes['['] = ArrayValue + valueTypes['{'] = ObjectValue +} + +// Iterator is a io.Reader like object, with JSON specific read functions. +// Error is not returned as return value, but stored as Error member on this iterator instance. +type Iterator struct { + cfg *frozenConfig + reader io.Reader + buf []byte + head int + tail int + captureStartedAt int + captured []byte + Error error + Attachment interface{} // open for customized decoder +} + +// NewIterator creates an empty Iterator instance +func NewIterator(cfg API) *Iterator { + return &Iterator{ + cfg: cfg.(*frozenConfig), + reader: nil, + buf: nil, + head: 0, + tail: 0, + } +} + +// Parse creates an Iterator instance from io.Reader +func Parse(cfg API, reader io.Reader, bufSize int) *Iterator { + return &Iterator{ + cfg: cfg.(*frozenConfig), + reader: reader, + buf: make([]byte, bufSize), + head: 0, + tail: 0, + } +} + +// ParseBytes creates an Iterator instance from byte array +func ParseBytes(cfg API, input []byte) *Iterator { + return &Iterator{ + cfg: cfg.(*frozenConfig), + reader: nil, + buf: input, + head: 0, + tail: len(input), + } +} + +// ParseString creates an Iterator instance from string +func ParseString(cfg API, input string) *Iterator { + return ParseBytes(cfg, []byte(input)) +} + +// Pool returns a pool can provide more iterator with same configuration +func (iter *Iterator) Pool() IteratorPool { + return iter.cfg +} + +// Reset reuse iterator instance by specifying another reader +func (iter *Iterator) Reset(reader io.Reader) *Iterator { + iter.reader = reader + iter.head = 0 + iter.tail = 0 + return iter +} + +// ResetBytes reuse iterator instance by specifying another byte array as input +func (iter *Iterator) ResetBytes(input []byte) *Iterator { + iter.reader = nil + iter.buf = input + iter.head = 0 + iter.tail = len(input) + return iter +} + +// WhatIsNext gets ValueType of relatively next json element +func (iter *Iterator) WhatIsNext() ValueType { + valueType := valueTypes[iter.nextToken()] + iter.unreadByte() + return valueType +} + +func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case ' ', '\n', '\t', '\r': + continue + } + iter.head = i + return false + } + return true +} + +func (iter *Iterator) isObjectEnd() bool { + c := iter.nextToken() + if c == ',' { + return false + } + if c == '}' { + return true + } + iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c})) + return true +} + +func (iter *Iterator) nextToken() byte { + // a variation of skip whitespaces, returning the next non-whitespace token + for { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case ' ', '\n', '\t', '\r': + continue + } + iter.head = i + 1 + return c + } + if !iter.loadMore() { + return 0 + } + } +} + +// ReportError record a error in iterator instance with current position. +func (iter *Iterator) ReportError(operation string, msg string) { + if iter.Error != nil { + if iter.Error != io.EOF { + return + } + } + peekStart := iter.head - 10 + if peekStart < 0 { + peekStart = 0 + } + peekEnd := iter.head + 10 + if peekEnd > iter.tail { + peekEnd = iter.tail + } + parsing := string(iter.buf[peekStart:peekEnd]) + contextStart := iter.head - 50 + if contextStart < 0 { + contextStart = 0 + } + contextEnd := iter.head + 50 + if contextEnd > iter.tail { + contextEnd = iter.tail + } + context := string(iter.buf[contextStart:contextEnd]) + iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...", + operation, msg, iter.head-peekStart, parsing, context) +} + +// CurrentBuffer gets current buffer as string for debugging purpose +func (iter *Iterator) CurrentBuffer() string { + peekStart := iter.head - 10 + if peekStart < 0 { + peekStart = 0 + } + return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head, + string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) +} + +func (iter *Iterator) readByte() (ret byte) { + if iter.head == iter.tail { + if iter.loadMore() { + ret = iter.buf[iter.head] + iter.head++ + return ret + } + return 0 + } + ret = iter.buf[iter.head] + iter.head++ + return ret +} + +func (iter *Iterator) loadMore() bool { + if iter.reader == nil { + if iter.Error == nil { + iter.head = iter.tail + iter.Error = io.EOF + } + return false + } + if iter.captured != nil { + iter.captured = append(iter.captured, + iter.buf[iter.captureStartedAt:iter.tail]...) + iter.captureStartedAt = 0 + } + for { + n, err := iter.reader.Read(iter.buf) + if n == 0 { + if err != nil { + if iter.Error == nil { + iter.Error = err + } + return false + } + } else { + iter.head = 0 + iter.tail = n + return true + } + } +} + +func (iter *Iterator) unreadByte() { + if iter.Error != nil { + return + } + iter.head-- + return +} + +// Read read the next JSON element as generic interface{}. +func (iter *Iterator) Read() interface{} { + valueType := iter.WhatIsNext() + switch valueType { + case StringValue: + return iter.ReadString() + case NumberValue: + if iter.cfg.configBeforeFrozen.UseNumber { + return json.Number(iter.readNumberAsString()) + } + return iter.ReadFloat64() + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + return nil + case BoolValue: + return iter.ReadBool() + case ArrayValue: + arr := []interface{}{} + iter.ReadArrayCB(func(iter *Iterator) bool { + var elem interface{} + iter.ReadVal(&elem) + arr = append(arr, elem) + return true + }) + return arr + case ObjectValue: + obj := map[string]interface{}{} + iter.ReadMapCB(func(Iter *Iterator, field string) bool { + var elem interface{} + iter.ReadVal(&elem) + obj[field] = elem + return true + }) + return obj + default: + iter.ReportError("Read", fmt.Sprintf("unexpected value type: %v", valueType)) + return nil + } +} diff --git a/vendor/github.com/json-iterator/go/iter_array.go b/vendor/github.com/json-iterator/go/iter_array.go new file mode 100644 index 0000000..6188cb4 --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_array.go @@ -0,0 +1,58 @@ +package jsoniter + +// ReadArray read array element, tells if the array has more element to read. +func (iter *Iterator) ReadArray() (ret bool) { + c := iter.nextToken() + switch c { + case 'n': + iter.skipThreeBytes('u', 'l', 'l') + return false // null + case '[': + c = iter.nextToken() + if c != ']' { + iter.unreadByte() + return true + } + return false + case ']': + return false + case ',': + return true + default: + iter.ReportError("ReadArray", "expect [ or , or ] or n, but found "+string([]byte{c})) + return + } +} + +// ReadArrayCB read array with callback +func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) { + c := iter.nextToken() + if c == '[' { + c = iter.nextToken() + if c != ']' { + iter.unreadByte() + if !callback(iter) { + return false + } + c = iter.nextToken() + for c == ',' { + if !callback(iter) { + return false + } + c = iter.nextToken() + } + if c != ']' { + iter.ReportError("ReadArrayCB", "expect ] in the end, but found "+string([]byte{c})) + return false + } + return true + } + return true + } + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return true // null + } + iter.ReportError("ReadArrayCB", "expect [ or n, but found "+string([]byte{c})) + return false +} diff --git a/vendor/github.com/json-iterator/go/iter_float.go b/vendor/github.com/json-iterator/go/iter_float.go new file mode 100644 index 0000000..4f883c0 --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_float.go @@ -0,0 +1,347 @@ +package jsoniter + +import ( + "encoding/json" + "io" + "math/big" + "strconv" + "strings" + "unsafe" +) + +var floatDigits []int8 + +const invalidCharForNumber = int8(-1) +const endOfNumber = int8(-2) +const dotInNumber = int8(-3) + +func init() { + floatDigits = make([]int8, 256) + for i := 0; i < len(floatDigits); i++ { + floatDigits[i] = invalidCharForNumber + } + for i := int8('0'); i <= int8('9'); i++ { + floatDigits[i] = i - int8('0') + } + floatDigits[','] = endOfNumber + floatDigits[']'] = endOfNumber + floatDigits['}'] = endOfNumber + floatDigits[' '] = endOfNumber + floatDigits['\t'] = endOfNumber + floatDigits['\n'] = endOfNumber + floatDigits['.'] = dotInNumber +} + +// ReadBigFloat read big.Float +func (iter *Iterator) ReadBigFloat() (ret *big.Float) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return nil + } + prec := 64 + if len(str) > prec { + prec = len(str) + } + val, _, err := big.ParseFloat(str, 10, uint(prec), big.ToZero) + if err != nil { + iter.Error = err + return nil + } + return val +} + +// ReadBigInt read big.Int +func (iter *Iterator) ReadBigInt() (ret *big.Int) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return nil + } + ret = big.NewInt(0) + var success bool + ret, success = ret.SetString(str, 10) + if !success { + iter.ReportError("ReadBigInt", "invalid big int") + return nil + } + return ret +} + +//ReadFloat32 read float32 +func (iter *Iterator) ReadFloat32() (ret float32) { + c := iter.nextToken() + if c == '-' { + return -iter.readPositiveFloat32() + } + iter.unreadByte() + return iter.readPositiveFloat32() +} + +func (iter *Iterator) readPositiveFloat32() (ret float32) { + value := uint64(0) + c := byte(' ') + i := iter.head + // first char + if i == iter.tail { + return iter.readFloat32SlowPath() + } + c = iter.buf[i] + i++ + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat32SlowPath() + case endOfNumber: + iter.ReportError("readFloat32", "empty number") + return + case dotInNumber: + iter.ReportError("readFloat32", "leading dot is invalid") + return + case 0: + if i == iter.tail { + return iter.readFloat32SlowPath() + } + c = iter.buf[i] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + iter.ReportError("readFloat32", "leading zero is invalid") + return + } + } + value = uint64(ind) + // chars before dot +non_decimal_loop: + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat32SlowPath() + case endOfNumber: + iter.head = i + return float32(value) + case dotInNumber: + break non_decimal_loop + } + if value > uint64SafeToMultiple10 { + return iter.readFloat32SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind; + } + // chars after dot + if c == '.' { + i++ + decimalPlaces := 0 + if i == iter.tail { + return iter.readFloat32SlowPath() + } + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case endOfNumber: + if decimalPlaces > 0 && decimalPlaces < len(pow10) { + iter.head = i + return float32(float64(value) / float64(pow10[decimalPlaces])) + } + // too many decimal places + return iter.readFloat32SlowPath() + case invalidCharForNumber: + fallthrough + case dotInNumber: + return iter.readFloat32SlowPath() + } + decimalPlaces++ + if value > uint64SafeToMultiple10 { + return iter.readFloat32SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) + } + } + return iter.readFloat32SlowPath() +} + +func (iter *Iterator) readNumberAsString() (ret string) { + strBuf := [16]byte{} + str := strBuf[0:0] +load_loop: + for { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case '+', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + str = append(str, c) + continue + default: + iter.head = i + break load_loop + } + } + if !iter.loadMore() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + return + } + if len(str) == 0 { + iter.ReportError("readNumberAsString", "invalid number") + } + return *(*string)(unsafe.Pointer(&str)) +} + +func (iter *Iterator) readFloat32SlowPath() (ret float32) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return + } + errMsg := validateFloat(str) + if errMsg != "" { + iter.ReportError("readFloat32SlowPath", errMsg) + return + } + val, err := strconv.ParseFloat(str, 32) + if err != nil { + iter.Error = err + return + } + return float32(val) +} + +// ReadFloat64 read float64 +func (iter *Iterator) ReadFloat64() (ret float64) { + c := iter.nextToken() + if c == '-' { + return -iter.readPositiveFloat64() + } + iter.unreadByte() + return iter.readPositiveFloat64() +} + +func (iter *Iterator) readPositiveFloat64() (ret float64) { + value := uint64(0) + c := byte(' ') + i := iter.head + // first char + if i == iter.tail { + return iter.readFloat64SlowPath() + } + c = iter.buf[i] + i++ + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat64SlowPath() + case endOfNumber: + iter.ReportError("readFloat64", "empty number") + return + case dotInNumber: + iter.ReportError("readFloat64", "leading dot is invalid") + return + case 0: + if i == iter.tail { + return iter.readFloat64SlowPath() + } + c = iter.buf[i] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + iter.ReportError("readFloat64", "leading zero is invalid") + return + } + } + value = uint64(ind) + // chars before dot +non_decimal_loop: + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat64SlowPath() + case endOfNumber: + iter.head = i + return float64(value) + case dotInNumber: + break non_decimal_loop + } + if value > uint64SafeToMultiple10 { + return iter.readFloat64SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind; + } + // chars after dot + if c == '.' { + i++ + decimalPlaces := 0 + if i == iter.tail { + return iter.readFloat64SlowPath() + } + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case endOfNumber: + if decimalPlaces > 0 && decimalPlaces < len(pow10) { + iter.head = i + return float64(value) / float64(pow10[decimalPlaces]) + } + // too many decimal places + return iter.readFloat64SlowPath() + case invalidCharForNumber: + fallthrough + case dotInNumber: + return iter.readFloat64SlowPath() + } + decimalPlaces++ + if value > uint64SafeToMultiple10 { + return iter.readFloat64SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) + } + } + return iter.readFloat64SlowPath() +} + +func (iter *Iterator) readFloat64SlowPath() (ret float64) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return + } + errMsg := validateFloat(str) + if errMsg != "" { + iter.ReportError("readFloat64SlowPath", errMsg) + return + } + val, err := strconv.ParseFloat(str, 64) + if err != nil { + iter.Error = err + return + } + return val +} + +func validateFloat(str string) string { + // strconv.ParseFloat is not validating `1.` or `1.e1` + if len(str) == 0 { + return "empty number" + } + if str[0] == '-' { + return "-- is not valid" + } + dotPos := strings.IndexByte(str, '.') + if dotPos != -1 { + if dotPos == len(str)-1 { + return "dot can not be last character" + } + switch str[dotPos+1] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + default: + return "missing digit after dot" + } + } + return "" +} + +// ReadNumber read json.Number +func (iter *Iterator) ReadNumber() (ret json.Number) { + return json.Number(iter.readNumberAsString()) +} diff --git a/vendor/github.com/json-iterator/go/iter_int.go b/vendor/github.com/json-iterator/go/iter_int.go new file mode 100644 index 0000000..2142320 --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_int.go @@ -0,0 +1,345 @@ +package jsoniter + +import ( + "math" + "strconv" +) + +var intDigits []int8 + +const uint32SafeToMultiply10 = uint32(0xffffffff)/10 - 1 +const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1 + +func init() { + intDigits = make([]int8, 256) + for i := 0; i < len(intDigits); i++ { + intDigits[i] = invalidCharForNumber + } + for i := int8('0'); i <= int8('9'); i++ { + intDigits[i] = i - int8('0') + } +} + +// ReadUint read uint +func (iter *Iterator) ReadUint() uint { + if strconv.IntSize == 32 { + return uint(iter.ReadUint32()) + } + return uint(iter.ReadUint64()) +} + +// ReadInt read int +func (iter *Iterator) ReadInt() int { + if strconv.IntSize == 32 { + return int(iter.ReadInt32()) + } + return int(iter.ReadInt64()) +} + +// ReadInt8 read int8 +func (iter *Iterator) ReadInt8() (ret int8) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint32(iter.readByte()) + if val > math.MaxInt8+1 { + iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return -int8(val) + } + val := iter.readUint32(c) + if val > math.MaxInt8 { + iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return int8(val) +} + +// ReadUint8 read uint8 +func (iter *Iterator) ReadUint8() (ret uint8) { + val := iter.readUint32(iter.nextToken()) + if val > math.MaxUint8 { + iter.ReportError("ReadUint8", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return uint8(val) +} + +// ReadInt16 read int16 +func (iter *Iterator) ReadInt16() (ret int16) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint32(iter.readByte()) + if val > math.MaxInt16+1 { + iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return -int16(val) + } + val := iter.readUint32(c) + if val > math.MaxInt16 { + iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return int16(val) +} + +// ReadUint16 read uint16 +func (iter *Iterator) ReadUint16() (ret uint16) { + val := iter.readUint32(iter.nextToken()) + if val > math.MaxUint16 { + iter.ReportError("ReadUint16", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return uint16(val) +} + +// ReadInt32 read int32 +func (iter *Iterator) ReadInt32() (ret int32) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint32(iter.readByte()) + if val > math.MaxInt32+1 { + iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return -int32(val) + } + val := iter.readUint32(c) + if val > math.MaxInt32 { + iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return int32(val) +} + +// ReadUint32 read uint32 +func (iter *Iterator) ReadUint32() (ret uint32) { + return iter.readUint32(iter.nextToken()) +} + +func (iter *Iterator) readUint32(c byte) (ret uint32) { + ind := intDigits[c] + if ind == 0 { + iter.assertInteger() + return 0 // single zero + } + if ind == invalidCharForNumber { + iter.ReportError("readUint32", "unexpected character: "+string([]byte{byte(ind)})) + return + } + value := uint32(ind) + if iter.tail-iter.head > 10 { + i := iter.head + ind2 := intDigits[iter.buf[i]] + if ind2 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + i++ + ind3 := intDigits[iter.buf[i]] + if ind3 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10 + uint32(ind2) + } + //iter.head = i + 1 + //value = value * 100 + uint32(ind2) * 10 + uint32(ind3) + i++ + ind4 := intDigits[iter.buf[i]] + if ind4 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100 + uint32(ind2)*10 + uint32(ind3) + } + i++ + ind5 := intDigits[iter.buf[i]] + if ind5 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000 + uint32(ind2)*100 + uint32(ind3)*10 + uint32(ind4) + } + i++ + ind6 := intDigits[iter.buf[i]] + if ind6 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10000 + uint32(ind2)*1000 + uint32(ind3)*100 + uint32(ind4)*10 + uint32(ind5) + } + i++ + ind7 := intDigits[iter.buf[i]] + if ind7 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100000 + uint32(ind2)*10000 + uint32(ind3)*1000 + uint32(ind4)*100 + uint32(ind5)*10 + uint32(ind6) + } + i++ + ind8 := intDigits[iter.buf[i]] + if ind8 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000000 + uint32(ind2)*100000 + uint32(ind3)*10000 + uint32(ind4)*1000 + uint32(ind5)*100 + uint32(ind6)*10 + uint32(ind7) + } + i++ + ind9 := intDigits[iter.buf[i]] + value = value*10000000 + uint32(ind2)*1000000 + uint32(ind3)*100000 + uint32(ind4)*10000 + uint32(ind5)*1000 + uint32(ind6)*100 + uint32(ind7)*10 + uint32(ind8) + iter.head = i + if ind9 == invalidCharForNumber { + iter.assertInteger() + return value + } + } + for { + for i := iter.head; i < iter.tail; i++ { + ind = intDigits[iter.buf[i]] + if ind == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + if value > uint32SafeToMultiply10 { + value2 := (value << 3) + (value << 1) + uint32(ind) + if value2 < value { + iter.ReportError("readUint32", "overflow") + return + } + value = value2 + continue + } + value = (value << 3) + (value << 1) + uint32(ind) + } + if !iter.loadMore() { + iter.assertInteger() + return value + } + } +} + +// ReadInt64 read int64 +func (iter *Iterator) ReadInt64() (ret int64) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint64(iter.readByte()) + if val > math.MaxInt64+1 { + iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) + return + } + return -int64(val) + } + val := iter.readUint64(c) + if val > math.MaxInt64 { + iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) + return + } + return int64(val) +} + +// ReadUint64 read uint64 +func (iter *Iterator) ReadUint64() uint64 { + return iter.readUint64(iter.nextToken()) +} + +func (iter *Iterator) readUint64(c byte) (ret uint64) { + ind := intDigits[c] + if ind == 0 { + iter.assertInteger() + return 0 // single zero + } + if ind == invalidCharForNumber { + iter.ReportError("readUint64", "unexpected character: "+string([]byte{byte(ind)})) + return + } + value := uint64(ind) + if iter.tail-iter.head > 10 { + i := iter.head + ind2 := intDigits[iter.buf[i]] + if ind2 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + i++ + ind3 := intDigits[iter.buf[i]] + if ind3 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10 + uint64(ind2) + } + //iter.head = i + 1 + //value = value * 100 + uint32(ind2) * 10 + uint32(ind3) + i++ + ind4 := intDigits[iter.buf[i]] + if ind4 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100 + uint64(ind2)*10 + uint64(ind3) + } + i++ + ind5 := intDigits[iter.buf[i]] + if ind5 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000 + uint64(ind2)*100 + uint64(ind3)*10 + uint64(ind4) + } + i++ + ind6 := intDigits[iter.buf[i]] + if ind6 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10000 + uint64(ind2)*1000 + uint64(ind3)*100 + uint64(ind4)*10 + uint64(ind5) + } + i++ + ind7 := intDigits[iter.buf[i]] + if ind7 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100000 + uint64(ind2)*10000 + uint64(ind3)*1000 + uint64(ind4)*100 + uint64(ind5)*10 + uint64(ind6) + } + i++ + ind8 := intDigits[iter.buf[i]] + if ind8 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000000 + uint64(ind2)*100000 + uint64(ind3)*10000 + uint64(ind4)*1000 + uint64(ind5)*100 + uint64(ind6)*10 + uint64(ind7) + } + i++ + ind9 := intDigits[iter.buf[i]] + value = value*10000000 + uint64(ind2)*1000000 + uint64(ind3)*100000 + uint64(ind4)*10000 + uint64(ind5)*1000 + uint64(ind6)*100 + uint64(ind7)*10 + uint64(ind8) + iter.head = i + if ind9 == invalidCharForNumber { + iter.assertInteger() + return value + } + } + for { + for i := iter.head; i < iter.tail; i++ { + ind = intDigits[iter.buf[i]] + if ind == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + if value > uint64SafeToMultiple10 { + value2 := (value << 3) + (value << 1) + uint64(ind) + if value2 < value { + iter.ReportError("readUint64", "overflow") + return + } + value = value2 + continue + } + value = (value << 3) + (value << 1) + uint64(ind) + } + if !iter.loadMore() { + iter.assertInteger() + return value + } + } +} + +func (iter *Iterator) assertInteger() { + if iter.head < len(iter.buf) && iter.buf[iter.head] == '.' { + iter.ReportError("assertInteger", "can not decode float as int") + } +} diff --git a/vendor/github.com/json-iterator/go/iter_object.go b/vendor/github.com/json-iterator/go/iter_object.go new file mode 100644 index 0000000..1c57576 --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_object.go @@ -0,0 +1,251 @@ +package jsoniter + +import ( + "fmt" + "strings" +) + +// ReadObject read one field from object. +// If object ended, returns empty string. +// Otherwise, returns the field name. +func (iter *Iterator) ReadObject() (ret string) { + c := iter.nextToken() + switch c { + case 'n': + iter.skipThreeBytes('u', 'l', 'l') + return "" // null + case '{': + c = iter.nextToken() + if c == '"' { + iter.unreadByte() + field := iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + return field + } + if c == '}' { + return "" // end of object + } + iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c})) + return + case ',': + field := iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + return field + case '}': + return "" // end of object + default: + iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c}))) + return + } +} + +// CaseInsensitive +func (iter *Iterator) readFieldHash() int64 { + hash := int64(0x811c9dc5) + c := iter.nextToken() + if c != '"' { + iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c})) + return 0 + } + for { + for i := iter.head; i < iter.tail; i++ { + // require ascii string and no escape + b := iter.buf[i] + if b == '\\' { + iter.head = i + for _, b := range iter.readStringSlowPath() { + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { + b += 'a' - 'A' + } + hash ^= int64(b) + hash *= 0x1000193 + } + c = iter.nextToken() + if c != ':' { + iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c})) + return 0 + } + return hash + } + if b == '"' { + iter.head = i + 1 + c = iter.nextToken() + if c != ':' { + iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c})) + return 0 + } + return hash + } + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { + b += 'a' - 'A' + } + hash ^= int64(b) + hash *= 0x1000193 + } + if !iter.loadMore() { + iter.ReportError("readFieldHash", `incomplete field name`) + return 0 + } + } +} + +func calcHash(str string, caseSensitive bool) int64 { + if !caseSensitive { + str = strings.ToLower(str) + } + hash := int64(0x811c9dc5) + for _, b := range []byte(str) { + hash ^= int64(b) + hash *= 0x1000193 + } + return int64(hash) +} + +// ReadObjectCB read object with callback, the key is ascii only and field name not copied +func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { + c := iter.nextToken() + var field string + if c == '{' { + c = iter.nextToken() + if c == '"' { + iter.unreadByte() + field = iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + for c == ',' { + field = iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + } + if c != '}' { + iter.ReportError("ReadObjectCB", `object not ended with }`) + return false + } + return true + } + if c == '}' { + return true + } + iter.ReportError("ReadObjectCB", `expect " after }, but found `+string([]byte{c})) + return false + } + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return true // null + } + iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c})) + return false +} + +// ReadMapCB read map with callback, the key can be any string +func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool { + c := iter.nextToken() + if c == '{' { + c = iter.nextToken() + if c == '"' { + iter.unreadByte() + field := iter.ReadString() + if iter.nextToken() != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return false + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + for c == ',' { + field = iter.ReadString() + if iter.nextToken() != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return false + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + } + if c != '}' { + iter.ReportError("ReadMapCB", `object not ended with }`) + return false + } + return true + } + if c == '}' { + return true + } + iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c})) + return false + } + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return true // null + } + iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c})) + return false +} + +func (iter *Iterator) readObjectStart() bool { + c := iter.nextToken() + if c == '{' { + c = iter.nextToken() + if c == '}' { + return false + } + iter.unreadByte() + return true + } else if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return false + } + iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c})) + return false +} + +func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) { + str := iter.ReadStringAsSlice() + if iter.skipWhitespacesWithoutLoadMore() { + if ret == nil { + ret = make([]byte, len(str)) + copy(ret, str) + } + if !iter.loadMore() { + return + } + } + if iter.buf[iter.head] != ':' { + iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]})) + return + } + iter.head++ + if iter.skipWhitespacesWithoutLoadMore() { + if ret == nil { + ret = make([]byte, len(str)) + copy(ret, str) + } + if !iter.loadMore() { + return + } + } + if ret == nil { + return str + } + return ret +} diff --git a/vendor/github.com/json-iterator/go/iter_skip.go b/vendor/github.com/json-iterator/go/iter_skip.go new file mode 100644 index 0000000..f58beb9 --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_skip.go @@ -0,0 +1,129 @@ +package jsoniter + +import "fmt" + +// ReadNil reads a json object as nil and +// returns whether it's a nil or not +func (iter *Iterator) ReadNil() (ret bool) { + c := iter.nextToken() + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') // null + return true + } + iter.unreadByte() + return false +} + +// ReadBool reads a json object as BoolValue +func (iter *Iterator) ReadBool() (ret bool) { + c := iter.nextToken() + if c == 't' { + iter.skipThreeBytes('r', 'u', 'e') + return true + } + if c == 'f' { + iter.skipFourBytes('a', 'l', 's', 'e') + return false + } + iter.ReportError("ReadBool", "expect t or f, but found "+string([]byte{c})) + return +} + +// SkipAndReturnBytes skip next JSON element, and return its content as []byte. +// The []byte can be kept, it is a copy of data. +func (iter *Iterator) SkipAndReturnBytes() []byte { + iter.startCapture(iter.head) + iter.Skip() + return iter.stopCapture() +} + +type captureBuffer struct { + startedAt int + captured []byte +} + +func (iter *Iterator) startCapture(captureStartedAt int) { + if iter.captured != nil { + panic("already in capture mode") + } + iter.captureStartedAt = captureStartedAt + iter.captured = make([]byte, 0, 32) +} + +func (iter *Iterator) stopCapture() []byte { + if iter.captured == nil { + panic("not in capture mode") + } + captured := iter.captured + remaining := iter.buf[iter.captureStartedAt:iter.head] + iter.captureStartedAt = -1 + iter.captured = nil + if len(captured) == 0 { + copied := make([]byte, len(remaining)) + copy(copied, remaining) + return copied + } + captured = append(captured, remaining...) + return captured +} + +// Skip skips a json object and positions to relatively the next json object +func (iter *Iterator) Skip() { + c := iter.nextToken() + switch c { + case '"': + iter.skipString() + case 'n': + iter.skipThreeBytes('u', 'l', 'l') // null + case 't': + iter.skipThreeBytes('r', 'u', 'e') // true + case 'f': + iter.skipFourBytes('a', 'l', 's', 'e') // false + case '0': + iter.unreadByte() + iter.ReadFloat32() + case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': + iter.skipNumber() + case '[': + iter.skipArray() + case '{': + iter.skipObject() + default: + iter.ReportError("Skip", fmt.Sprintf("do not know how to skip: %v", c)) + return + } +} + +func (iter *Iterator) skipFourBytes(b1, b2, b3, b4 byte) { + if iter.readByte() != b1 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } + if iter.readByte() != b2 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } + if iter.readByte() != b3 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } + if iter.readByte() != b4 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } +} + +func (iter *Iterator) skipThreeBytes(b1, b2, b3 byte) { + if iter.readByte() != b1 { + iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) + return + } + if iter.readByte() != b2 { + iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) + return + } + if iter.readByte() != b3 { + iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) + return + } +} diff --git a/vendor/github.com/json-iterator/go/iter_skip_sloppy.go b/vendor/github.com/json-iterator/go/iter_skip_sloppy.go new file mode 100644 index 0000000..8fcdc3b --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_skip_sloppy.go @@ -0,0 +1,144 @@ +//+build jsoniter_sloppy + +package jsoniter + +// sloppy but faster implementation, do not validate the input json + +func (iter *Iterator) skipNumber() { + for { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case ' ', '\n', '\r', '\t', ',', '}', ']': + iter.head = i + return + } + } + if !iter.loadMore() { + return + } + } +} + +func (iter *Iterator) skipArray() { + level := 1 + for { + for i := iter.head; i < iter.tail; i++ { + switch iter.buf[i] { + case '"': // If inside string, skip it + iter.head = i + 1 + iter.skipString() + i = iter.head - 1 // it will be i++ soon + case '[': // If open symbol, increase level + level++ + case ']': // If close symbol, increase level + level-- + + // If we have returned to the original level, we're done + if level == 0 { + iter.head = i + 1 + return + } + } + } + if !iter.loadMore() { + iter.ReportError("skipObject", "incomplete array") + return + } + } +} + +func (iter *Iterator) skipObject() { + level := 1 + for { + for i := iter.head; i < iter.tail; i++ { + switch iter.buf[i] { + case '"': // If inside string, skip it + iter.head = i + 1 + iter.skipString() + i = iter.head - 1 // it will be i++ soon + case '{': // If open symbol, increase level + level++ + case '}': // If close symbol, increase level + level-- + + // If we have returned to the original level, we're done + if level == 0 { + iter.head = i + 1 + return + } + } + } + if !iter.loadMore() { + iter.ReportError("skipObject", "incomplete object") + return + } + } +} + +func (iter *Iterator) skipString() { + for { + end, escaped := iter.findStringEnd() + if end == -1 { + if !iter.loadMore() { + iter.ReportError("skipString", "incomplete string") + return + } + if escaped { + iter.head = 1 // skip the first char as last char read is \ + } + } else { + iter.head = end + return + } + } +} + +// adapted from: https://github.com/buger/jsonparser/blob/master/parser.go +// Tries to find the end of string +// Support if string contains escaped quote symbols. +func (iter *Iterator) findStringEnd() (int, bool) { + escaped := false + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + if c == '"' { + if !escaped { + return i + 1, false + } + j := i - 1 + for { + if j < iter.head || iter.buf[j] != '\\' { + // even number of backslashes + // either end of buffer, or " found + return i + 1, true + } + j-- + if j < iter.head || iter.buf[j] != '\\' { + // odd number of backslashes + // it is \" or \\\" + break + } + j-- + } + } else if c == '\\' { + escaped = true + } + } + j := iter.tail - 1 + for { + if j < iter.head || iter.buf[j] != '\\' { + // even number of backslashes + // either end of buffer, or " found + return -1, false // do not end with \ + } + j-- + if j < iter.head || iter.buf[j] != '\\' { + // odd number of backslashes + // it is \" or \\\" + break + } + j-- + + } + return -1, true // end with \ +} diff --git a/vendor/github.com/json-iterator/go/iter_skip_strict.go b/vendor/github.com/json-iterator/go/iter_skip_strict.go new file mode 100644 index 0000000..f67bc2e --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_skip_strict.go @@ -0,0 +1,89 @@ +//+build !jsoniter_sloppy + +package jsoniter + +import "fmt" + +func (iter *Iterator) skipNumber() { + if !iter.trySkipNumber() { + iter.unreadByte() + iter.ReadFloat32() + } +} + +func (iter *Iterator) trySkipNumber() bool { + dotFound := false + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + case '.': + if dotFound { + iter.ReportError("validateNumber", `more than one dot found in number`) + return true // already failed + } + if i+1 == iter.tail { + return false + } + c = iter.buf[i+1] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + default: + iter.ReportError("validateNumber", `missing digit after dot`) + return true // already failed + } + dotFound = true + default: + switch c { + case ',', ']', '}', ' ', '\t', '\n', '\r': + if iter.head == i { + return false // if - without following digits + } + iter.head = i + return true // must be valid + } + return false // may be invalid + } + } + return false +} + +func (iter *Iterator) skipString() { + if !iter.trySkipString() { + iter.unreadByte() + iter.ReadString() + } +} + +func (iter *Iterator) trySkipString() bool { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + if c == '"' { + iter.head = i + 1 + return true // valid + } else if c == '\\' { + return false + } else if c < ' ' { + iter.ReportError("trySkipString", + fmt.Sprintf(`invalid control character found: %d`, c)) + return true // already failed + } + } + return false +} + +func (iter *Iterator) skipObject() { + iter.unreadByte() + iter.ReadObjectCB(func(iter *Iterator, field string) bool { + iter.Skip() + return true + }) +} + +func (iter *Iterator) skipArray() { + iter.unreadByte() + iter.ReadArrayCB(func(iter *Iterator) bool { + iter.Skip() + return true + }) +} diff --git a/vendor/github.com/json-iterator/go/iter_str.go b/vendor/github.com/json-iterator/go/iter_str.go new file mode 100644 index 0000000..adc487e --- /dev/null +++ b/vendor/github.com/json-iterator/go/iter_str.go @@ -0,0 +1,215 @@ +package jsoniter + +import ( + "fmt" + "unicode/utf16" +) + +// ReadString read string from iterator +func (iter *Iterator) ReadString() (ret string) { + c := iter.nextToken() + if c == '"' { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + if c == '"' { + ret = string(iter.buf[iter.head:i]) + iter.head = i + 1 + return ret + } else if c == '\\' { + break + } else if c < ' ' { + iter.ReportError("ReadString", + fmt.Sprintf(`invalid control character found: %d`, c)) + return + } + } + return iter.readStringSlowPath() + } else if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return "" + } + iter.ReportError("ReadString", `expects " or n, but found `+string([]byte{c})) + return +} + +func (iter *Iterator) readStringSlowPath() (ret string) { + var str []byte + var c byte + for iter.Error == nil { + c = iter.readByte() + if c == '"' { + return string(str) + } + if c == '\\' { + c = iter.readByte() + str = iter.readEscapedChar(c, str) + } else { + str = append(str, c) + } + } + iter.ReportError("readStringSlowPath", "unexpected end of input") + return +} + +func (iter *Iterator) readEscapedChar(c byte, str []byte) []byte { + switch c { + case 'u': + r := iter.readU4() + if utf16.IsSurrogate(r) { + c = iter.readByte() + if iter.Error != nil { + return nil + } + if c != '\\' { + iter.unreadByte() + str = appendRune(str, r) + return str + } + c = iter.readByte() + if iter.Error != nil { + return nil + } + if c != 'u' { + str = appendRune(str, r) + return iter.readEscapedChar(c, str) + } + r2 := iter.readU4() + if iter.Error != nil { + return nil + } + combined := utf16.DecodeRune(r, r2) + if combined == '\uFFFD' { + str = appendRune(str, r) + str = appendRune(str, r2) + } else { + str = appendRune(str, combined) + } + } else { + str = appendRune(str, r) + } + case '"': + str = append(str, '"') + case '\\': + str = append(str, '\\') + case '/': + str = append(str, '/') + case 'b': + str = append(str, '\b') + case 'f': + str = append(str, '\f') + case 'n': + str = append(str, '\n') + case 'r': + str = append(str, '\r') + case 't': + str = append(str, '\t') + default: + iter.ReportError("readEscapedChar", + `invalid escape char after \`) + return nil + } + return str +} + +// ReadStringAsSlice read string from iterator without copying into string form. +// The []byte can not be kept, as it will change after next iterator call. +func (iter *Iterator) ReadStringAsSlice() (ret []byte) { + c := iter.nextToken() + if c == '"' { + for i := iter.head; i < iter.tail; i++ { + // require ascii string and no escape + // for: field name, base64, number + if iter.buf[i] == '"' { + // fast path: reuse the underlying buffer + ret = iter.buf[iter.head:i] + iter.head = i + 1 + return ret + } + } + readLen := iter.tail - iter.head + copied := make([]byte, readLen, readLen*2) + copy(copied, iter.buf[iter.head:iter.tail]) + iter.head = iter.tail + for iter.Error == nil { + c := iter.readByte() + if c == '"' { + return copied + } + copied = append(copied, c) + } + return copied + } + iter.ReportError("ReadStringAsSlice", `expects " or n, but found `+string([]byte{c})) + return +} + +func (iter *Iterator) readU4() (ret rune) { + for i := 0; i < 4; i++ { + c := iter.readByte() + if iter.Error != nil { + return + } + if c >= '0' && c <= '9' { + ret = ret*16 + rune(c-'0') + } else if c >= 'a' && c <= 'f' { + ret = ret*16 + rune(c-'a'+10) + } else if c >= 'A' && c <= 'F' { + ret = ret*16 + rune(c-'A'+10) + } else { + iter.ReportError("readU4", "expects 0~9 or a~f, but found "+string([]byte{c})) + return + } + } + return ret +} + +const ( + t1 = 0x00 // 0000 0000 + tx = 0x80 // 1000 0000 + t2 = 0xC0 // 1100 0000 + t3 = 0xE0 // 1110 0000 + t4 = 0xF0 // 1111 0000 + t5 = 0xF8 // 1111 1000 + + maskx = 0x3F // 0011 1111 + mask2 = 0x1F // 0001 1111 + mask3 = 0x0F // 0000 1111 + mask4 = 0x07 // 0000 0111 + + rune1Max = 1<<7 - 1 + rune2Max = 1<<11 - 1 + rune3Max = 1<<16 - 1 + + surrogateMin = 0xD800 + surrogateMax = 0xDFFF + + maxRune = '\U0010FFFF' // Maximum valid Unicode code point. + runeError = '\uFFFD' // the "error" Rune or "Unicode replacement character" +) + +func appendRune(p []byte, r rune) []byte { + // Negative values are erroneous. Making it unsigned addresses the problem. + switch i := uint32(r); { + case i <= rune1Max: + p = append(p, byte(r)) + return p + case i <= rune2Max: + p = append(p, t2|byte(r>>6)) + p = append(p, tx|byte(r)&maskx) + return p + case i > maxRune, surrogateMin <= i && i <= surrogateMax: + r = runeError + fallthrough + case i <= rune3Max: + p = append(p, t3|byte(r>>12)) + p = append(p, tx|byte(r>>6)&maskx) + p = append(p, tx|byte(r)&maskx) + return p + default: + p = append(p, t4|byte(r>>18)) + p = append(p, tx|byte(r>>12)&maskx) + p = append(p, tx|byte(r>>6)&maskx) + p = append(p, tx|byte(r)&maskx) + return p + } +} diff --git a/vendor/github.com/json-iterator/go/jsoniter.go b/vendor/github.com/json-iterator/go/jsoniter.go new file mode 100644 index 0000000..c2934f9 --- /dev/null +++ b/vendor/github.com/json-iterator/go/jsoniter.go @@ -0,0 +1,18 @@ +// Package jsoniter implements encoding and decoding of JSON as defined in +// RFC 4627 and provides interfaces with identical syntax of standard lib encoding/json. +// Converting from encoding/json to jsoniter is no more than replacing the package with jsoniter +// and variable type declarations (if any). +// jsoniter interfaces gives 100% compatibility with code using standard lib. +// +// "JSON and Go" +// (https://golang.org/doc/articles/json_and_go.html) +// gives a description of how Marshal/Unmarshal operate +// between arbitrary or predefined json objects and bytes, +// and it applies to jsoniter.Marshal/Unmarshal as well. +// +// Besides, jsoniter.Iterator provides a different set of interfaces +// iterating given bytes/string/reader +// and yielding parsed elements one by one. +// This set of interfaces reads input as required and gives +// better performance. +package jsoniter diff --git a/vendor/github.com/json-iterator/go/pool.go b/vendor/github.com/json-iterator/go/pool.go new file mode 100644 index 0000000..e2389b5 --- /dev/null +++ b/vendor/github.com/json-iterator/go/pool.go @@ -0,0 +1,42 @@ +package jsoniter + +import ( + "io" +) + +// IteratorPool a thread safe pool of iterators with same configuration +type IteratorPool interface { + BorrowIterator(data []byte) *Iterator + ReturnIterator(iter *Iterator) +} + +// StreamPool a thread safe pool of streams with same configuration +type StreamPool interface { + BorrowStream(writer io.Writer) *Stream + ReturnStream(stream *Stream) +} + +func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream { + stream := cfg.streamPool.Get().(*Stream) + stream.Reset(writer) + return stream +} + +func (cfg *frozenConfig) ReturnStream(stream *Stream) { + stream.out = nil + stream.Error = nil + stream.Attachment = nil + cfg.streamPool.Put(stream) +} + +func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator { + iter := cfg.iteratorPool.Get().(*Iterator) + iter.ResetBytes(data) + return iter +} + +func (cfg *frozenConfig) ReturnIterator(iter *Iterator) { + iter.Error = nil + iter.Attachment = nil + cfg.iteratorPool.Put(iter) +} diff --git a/vendor/github.com/json-iterator/go/reflect.go b/vendor/github.com/json-iterator/go/reflect.go new file mode 100644 index 0000000..4459e20 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect.go @@ -0,0 +1,332 @@ +package jsoniter + +import ( + "fmt" + "reflect" + "unsafe" + + "github.com/modern-go/reflect2" +) + +// ValDecoder is an internal type registered to cache as needed. +// Don't confuse jsoniter.ValDecoder with json.Decoder. +// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link). +// +// Reflection on type to create decoders, which is then cached +// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions +// 1. create instance of new value, for example *int will need a int to be allocated +// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New +// 3. assignment to map, both key and value will be reflect.Value +// For a simple struct binding, it will be reflect.Value free and allocation free +type ValDecoder interface { + Decode(ptr unsafe.Pointer, iter *Iterator) +} + +// ValEncoder is an internal type registered to cache as needed. +// Don't confuse jsoniter.ValEncoder with json.Encoder. +// For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link). +type ValEncoder interface { + IsEmpty(ptr unsafe.Pointer) bool + Encode(ptr unsafe.Pointer, stream *Stream) +} + +type checkIsEmpty interface { + IsEmpty(ptr unsafe.Pointer) bool +} + +type ctx struct { + *frozenConfig + prefix string + encoders map[reflect2.Type]ValEncoder + decoders map[reflect2.Type]ValDecoder +} + +func (b *ctx) caseSensitive() bool { + if b.frozenConfig == nil { + // default is case-insensitive + return false + } + return b.frozenConfig.caseSensitive +} + +func (b *ctx) append(prefix string) *ctx { + return &ctx{ + frozenConfig: b.frozenConfig, + prefix: b.prefix + " " + prefix, + encoders: b.encoders, + decoders: b.decoders, + } +} + +// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal +func (iter *Iterator) ReadVal(obj interface{}) { + cacheKey := reflect2.RTypeOf(obj) + decoder := iter.cfg.getDecoderFromCache(cacheKey) + if decoder == nil { + typ := reflect2.TypeOf(obj) + if typ.Kind() != reflect.Ptr { + iter.ReportError("ReadVal", "can only unmarshal into pointer") + return + } + decoder = iter.cfg.DecoderOf(typ) + } + ptr := reflect2.PtrOf(obj) + if ptr == nil { + iter.ReportError("ReadVal", "can not read into nil pointer") + return + } + decoder.Decode(ptr, iter) +} + +// WriteVal copy the go interface into underlying JSON, same as json.Marshal +func (stream *Stream) WriteVal(val interface{}) { + if nil == val { + stream.WriteNil() + return + } + cacheKey := reflect2.RTypeOf(val) + encoder := stream.cfg.getEncoderFromCache(cacheKey) + if encoder == nil { + typ := reflect2.TypeOf(val) + encoder = stream.cfg.EncoderOf(typ) + } + encoder.Encode(reflect2.PtrOf(val), stream) +} + +func (cfg *frozenConfig) DecoderOf(typ reflect2.Type) ValDecoder { + cacheKey := typ.RType() + decoder := cfg.getDecoderFromCache(cacheKey) + if decoder != nil { + return decoder + } + ctx := &ctx{ + frozenConfig: cfg, + prefix: "", + decoders: map[reflect2.Type]ValDecoder{}, + encoders: map[reflect2.Type]ValEncoder{}, + } + ptrType := typ.(*reflect2.UnsafePtrType) + decoder = decoderOfType(ctx, ptrType.Elem()) + cfg.addDecoderToCache(cacheKey, decoder) + return decoder +} + +func decoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := getTypeDecoderFromExtension(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfType(ctx, typ) + for _, extension := range extensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder) + for _, extension := range ctx.extraExtensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + return decoder +} + +func createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := ctx.decoders[typ] + if decoder != nil { + return decoder + } + placeholder := &placeholderDecoder{} + ctx.decoders[typ] = placeholder + decoder = _createDecoderOfType(ctx, typ) + placeholder.decoder = decoder + return decoder +} + +func _createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := createDecoderOfJsonRawMessage(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfJsonNumber(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfMarshaler(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfAny(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfNative(ctx, typ) + if decoder != nil { + return decoder + } + switch typ.Kind() { + case reflect.Interface: + ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType) + if isIFace { + return &ifaceDecoder{valType: ifaceType} + } + return &efaceDecoder{} + case reflect.Struct: + return decoderOfStruct(ctx, typ) + case reflect.Array: + return decoderOfArray(ctx, typ) + case reflect.Slice: + return decoderOfSlice(ctx, typ) + case reflect.Map: + return decoderOfMap(ctx, typ) + case reflect.Ptr: + return decoderOfOptional(ctx, typ) + default: + return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())} + } +} + +func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder { + cacheKey := typ.RType() + encoder := cfg.getEncoderFromCache(cacheKey) + if encoder != nil { + return encoder + } + ctx := &ctx{ + frozenConfig: cfg, + prefix: "", + decoders: map[reflect2.Type]ValDecoder{}, + encoders: map[reflect2.Type]ValEncoder{}, + } + encoder = encoderOfType(ctx, typ) + if typ.LikePtr() { + encoder = &onePtrEncoder{encoder} + } + cfg.addEncoderToCache(cacheKey, encoder) + return encoder +} + +type onePtrEncoder struct { + encoder ValEncoder +} + +func (encoder *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) +} + +func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) +} + +func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := getTypeEncoderFromExtension(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfType(ctx, typ) + for _, extension := range extensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder) + for _, extension := range ctx.extraExtensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + return encoder +} + +func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := ctx.encoders[typ] + if encoder != nil { + return encoder + } + placeholder := &placeholderEncoder{} + ctx.encoders[typ] = placeholder + encoder = _createEncoderOfType(ctx, typ) + placeholder.encoder = encoder + return encoder +} +func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := createEncoderOfJsonRawMessage(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfJsonNumber(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfMarshaler(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfAny(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfNative(ctx, typ) + if encoder != nil { + return encoder + } + kind := typ.Kind() + switch kind { + case reflect.Interface: + return &dynamicEncoder{typ} + case reflect.Struct: + return encoderOfStruct(ctx, typ) + case reflect.Array: + return encoderOfArray(ctx, typ) + case reflect.Slice: + return encoderOfSlice(ctx, typ) + case reflect.Map: + return encoderOfMap(ctx, typ) + case reflect.Ptr: + return encoderOfOptional(ctx, typ) + default: + return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())} + } +} + +type lazyErrorDecoder struct { + err error +} + +func (decoder *lazyErrorDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.WhatIsNext() != NilValue { + if iter.Error == nil { + iter.Error = decoder.err + } + } else { + iter.Skip() + } +} + +type lazyErrorEncoder struct { + err error +} + +func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if ptr == nil { + stream.WriteNil() + } else if stream.Error == nil { + stream.Error = encoder.err + } +} + +func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type placeholderDecoder struct { + decoder ValDecoder +} + +func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.decoder.Decode(ptr, iter) +} + +type placeholderEncoder struct { + encoder ValEncoder +} + +func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.encoder.Encode(ptr, stream) +} + +func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(ptr) +} diff --git a/vendor/github.com/json-iterator/go/reflect_array.go b/vendor/github.com/json-iterator/go/reflect_array.go new file mode 100644 index 0000000..13a0b7b --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_array.go @@ -0,0 +1,104 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "unsafe" +) + +func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder { + arrayType := typ.(*reflect2.UnsafeArrayType) + decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) + return &arrayDecoder{arrayType, decoder} +} + +func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder { + arrayType := typ.(*reflect2.UnsafeArrayType) + if arrayType.Len() == 0 { + return emptyArrayEncoder{} + } + encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) + return &arrayEncoder{arrayType, encoder} +} + +type emptyArrayEncoder struct{} + +func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteEmptyArray() +} + +func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return true +} + +type arrayEncoder struct { + arrayType *reflect2.UnsafeArrayType + elemEncoder ValEncoder +} + +func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteArrayStart() + elemPtr := unsafe.Pointer(ptr) + encoder.elemEncoder.Encode(elemPtr, stream) + for i := 1; i < encoder.arrayType.Len(); i++ { + stream.WriteMore() + elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i) + encoder.elemEncoder.Encode(elemPtr, stream) + } + stream.WriteArrayEnd() + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error()) + } +} + +func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type arrayDecoder struct { + arrayType *reflect2.UnsafeArrayType + elemDecoder ValDecoder +} + +func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.doDecode(ptr, iter) + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error()) + } +} + +func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + arrayType := decoder.arrayType + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return + } + if c != '[' { + iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c})) + return + } + c = iter.nextToken() + if c == ']' { + return + } + iter.unreadByte() + elemPtr := arrayType.UnsafeGetIndex(ptr, 0) + decoder.elemDecoder.Decode(elemPtr, iter) + length := 1 + for c = iter.nextToken(); c == ','; c = iter.nextToken() { + if length >= arrayType.Len() { + iter.Skip() + continue + } + idx := length + length += 1 + elemPtr = arrayType.UnsafeGetIndex(ptr, idx) + decoder.elemDecoder.Decode(elemPtr, iter) + } + if c != ']' { + iter.ReportError("decode array", "expect ], but found "+string([]byte{c})) + return + } +} diff --git a/vendor/github.com/json-iterator/go/reflect_dynamic.go b/vendor/github.com/json-iterator/go/reflect_dynamic.go new file mode 100644 index 0000000..8b6bc8b --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_dynamic.go @@ -0,0 +1,70 @@ +package jsoniter + +import ( + "github.com/modern-go/reflect2" + "reflect" + "unsafe" +) + +type dynamicEncoder struct { + valType reflect2.Type +} + +func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + stream.WriteVal(obj) +} + +func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.valType.UnsafeIndirect(ptr) == nil +} + +type efaceDecoder struct { +} + +func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + pObj := (*interface{})(ptr) + obj := *pObj + if obj == nil { + *pObj = iter.Read() + return + } + typ := reflect2.TypeOf(obj) + if typ.Kind() != reflect.Ptr { + *pObj = iter.Read() + return + } + ptrType := typ.(*reflect2.UnsafePtrType) + ptrElemType := ptrType.Elem() + if iter.WhatIsNext() == NilValue { + if ptrElemType.Kind() != reflect.Ptr { + iter.skipFourBytes('n', 'u', 'l', 'l') + *pObj = nil + return + } + } + if reflect2.IsNil(obj) { + obj := ptrElemType.New() + iter.ReadVal(obj) + *pObj = obj + return + } + iter.ReadVal(obj) +} + +type ifaceDecoder struct { + valType *reflect2.UnsafeIFaceType +} + +func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.ReadNil() { + decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew()) + return + } + obj := decoder.valType.UnsafeIndirect(ptr) + if reflect2.IsNil(obj) { + iter.ReportError("decode non empty interface", "can not unmarshal into nil") + return + } + iter.ReadVal(obj) +} diff --git a/vendor/github.com/json-iterator/go/reflect_extension.go b/vendor/github.com/json-iterator/go/reflect_extension.go new file mode 100644 index 0000000..04f6875 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_extension.go @@ -0,0 +1,483 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "reflect" + "sort" + "strings" + "unicode" + "unsafe" +) + +var typeDecoders = map[string]ValDecoder{} +var fieldDecoders = map[string]ValDecoder{} +var typeEncoders = map[string]ValEncoder{} +var fieldEncoders = map[string]ValEncoder{} +var extensions = []Extension{} + +// StructDescriptor describe how should we encode/decode the struct +type StructDescriptor struct { + Type reflect2.Type + Fields []*Binding +} + +// GetField get one field from the descriptor by its name. +// Can not use map here to keep field orders. +func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding { + for _, binding := range structDescriptor.Fields { + if binding.Field.Name() == fieldName { + return binding + } + } + return nil +} + +// Binding describe how should we encode/decode the struct field +type Binding struct { + levels []int + Field reflect2.StructField + FromNames []string + ToNames []string + Encoder ValEncoder + Decoder ValDecoder +} + +// Extension the one for all SPI. Customize encoding/decoding by specifying alternate encoder/decoder. +// Can also rename fields by UpdateStructDescriptor. +type Extension interface { + UpdateStructDescriptor(structDescriptor *StructDescriptor) + CreateMapKeyDecoder(typ reflect2.Type) ValDecoder + CreateMapKeyEncoder(typ reflect2.Type) ValEncoder + CreateDecoder(typ reflect2.Type) ValDecoder + CreateEncoder(typ reflect2.Type) ValEncoder + DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder + DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder +} + +// DummyExtension embed this type get dummy implementation for all methods of Extension +type DummyExtension struct { +} + +// UpdateStructDescriptor No-op +func (extension *DummyExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { +} + +// CreateMapKeyDecoder No-op +func (extension *DummyExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateMapKeyEncoder No-op +func (extension *DummyExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// CreateDecoder No-op +func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateEncoder No-op +func (extension *DummyExtension) CreateEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// DecorateDecoder No-op +func (extension *DummyExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { + return decoder +} + +// DecorateEncoder No-op +func (extension *DummyExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { + return encoder +} + +type EncoderExtension map[reflect2.Type]ValEncoder + +// UpdateStructDescriptor No-op +func (extension EncoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { +} + +// CreateDecoder No-op +func (extension EncoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateEncoder get encoder from map +func (extension EncoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder { + return extension[typ] +} + +// CreateMapKeyDecoder No-op +func (extension EncoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateMapKeyEncoder No-op +func (extension EncoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// DecorateDecoder No-op +func (extension EncoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { + return decoder +} + +// DecorateEncoder No-op +func (extension EncoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { + return encoder +} + +type DecoderExtension map[reflect2.Type]ValDecoder + +// UpdateStructDescriptor No-op +func (extension DecoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { +} + +// CreateMapKeyDecoder No-op +func (extension DecoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateMapKeyEncoder No-op +func (extension DecoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// CreateDecoder get decoder from map +func (extension DecoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder { + return extension[typ] +} + +// CreateEncoder No-op +func (extension DecoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// DecorateDecoder No-op +func (extension DecoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { + return decoder +} + +// DecorateEncoder No-op +func (extension DecoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { + return encoder +} + +type funcDecoder struct { + fun DecoderFunc +} + +func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.fun(ptr, iter) +} + +type funcEncoder struct { + fun EncoderFunc + isEmptyFunc func(ptr unsafe.Pointer) bool +} + +func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.fun(ptr, stream) +} + +func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool { + if encoder.isEmptyFunc == nil { + return false + } + return encoder.isEmptyFunc(ptr) +} + +// DecoderFunc the function form of TypeDecoder +type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) + +// EncoderFunc the function form of TypeEncoder +type EncoderFunc func(ptr unsafe.Pointer, stream *Stream) + +// RegisterTypeDecoderFunc register TypeDecoder for a type with function +func RegisterTypeDecoderFunc(typ string, fun DecoderFunc) { + typeDecoders[typ] = &funcDecoder{fun} +} + +// RegisterTypeDecoder register TypeDecoder for a typ +func RegisterTypeDecoder(typ string, decoder ValDecoder) { + typeDecoders[typ] = decoder +} + +// RegisterFieldDecoderFunc register TypeDecoder for a struct field with function +func RegisterFieldDecoderFunc(typ string, field string, fun DecoderFunc) { + RegisterFieldDecoder(typ, field, &funcDecoder{fun}) +} + +// RegisterFieldDecoder register TypeDecoder for a struct field +func RegisterFieldDecoder(typ string, field string, decoder ValDecoder) { + fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = decoder +} + +// RegisterTypeEncoderFunc register TypeEncoder for a type with encode/isEmpty function +func RegisterTypeEncoderFunc(typ string, fun EncoderFunc, isEmptyFunc func(unsafe.Pointer) bool) { + typeEncoders[typ] = &funcEncoder{fun, isEmptyFunc} +} + +// RegisterTypeEncoder register TypeEncoder for a type +func RegisterTypeEncoder(typ string, encoder ValEncoder) { + typeEncoders[typ] = encoder +} + +// RegisterFieldEncoderFunc register TypeEncoder for a struct field with encode/isEmpty function +func RegisterFieldEncoderFunc(typ string, field string, fun EncoderFunc, isEmptyFunc func(unsafe.Pointer) bool) { + RegisterFieldEncoder(typ, field, &funcEncoder{fun, isEmptyFunc}) +} + +// RegisterFieldEncoder register TypeEncoder for a struct field +func RegisterFieldEncoder(typ string, field string, encoder ValEncoder) { + fieldEncoders[fmt.Sprintf("%s/%s", typ, field)] = encoder +} + +// RegisterExtension register extension +func RegisterExtension(extension Extension) { + extensions = append(extensions, extension) +} + +func getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := _getTypeDecoderFromExtension(ctx, typ) + if decoder != nil { + for _, extension := range extensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder) + for _, extension := range ctx.extraExtensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + } + return decoder +} +func _getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder { + for _, extension := range extensions { + decoder := extension.CreateDecoder(typ) + if decoder != nil { + return decoder + } + } + decoder := ctx.decoderExtension.CreateDecoder(typ) + if decoder != nil { + return decoder + } + for _, extension := range ctx.extraExtensions { + decoder := extension.CreateDecoder(typ) + if decoder != nil { + return decoder + } + } + typeName := typ.String() + decoder = typeDecoders[typeName] + if decoder != nil { + return decoder + } + if typ.Kind() == reflect.Ptr { + ptrType := typ.(*reflect2.UnsafePtrType) + decoder := typeDecoders[ptrType.Elem().String()] + if decoder != nil { + return &OptionalDecoder{ptrType.Elem(), decoder} + } + } + return nil +} + +func getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := _getTypeEncoderFromExtension(ctx, typ) + if encoder != nil { + for _, extension := range extensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder) + for _, extension := range ctx.extraExtensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + } + return encoder +} + +func _getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder { + for _, extension := range extensions { + encoder := extension.CreateEncoder(typ) + if encoder != nil { + return encoder + } + } + encoder := ctx.encoderExtension.CreateEncoder(typ) + if encoder != nil { + return encoder + } + for _, extension := range ctx.extraExtensions { + encoder := extension.CreateEncoder(typ) + if encoder != nil { + return encoder + } + } + typeName := typ.String() + encoder = typeEncoders[typeName] + if encoder != nil { + return encoder + } + if typ.Kind() == reflect.Ptr { + typePtr := typ.(*reflect2.UnsafePtrType) + encoder := typeEncoders[typePtr.Elem().String()] + if encoder != nil { + return &OptionalEncoder{encoder} + } + } + return nil +} + +func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor { + structType := typ.(*reflect2.UnsafeStructType) + embeddedBindings := []*Binding{} + bindings := []*Binding{} + for i := 0; i < structType.NumField(); i++ { + field := structType.Field(i) + tag, hastag := field.Tag().Lookup(ctx.getTagKey()) + if ctx.onlyTaggedField && !hastag { + continue + } + tagParts := strings.Split(tag, ",") + if tag == "-" { + continue + } + if field.Anonymous() && (tag == "" || tagParts[0] == "") { + if field.Type().Kind() == reflect.Struct { + structDescriptor := describeStruct(ctx, field.Type()) + for _, binding := range structDescriptor.Fields { + binding.levels = append([]int{i}, binding.levels...) + omitempty := binding.Encoder.(*structFieldEncoder).omitempty + binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty} + binding.Decoder = &structFieldDecoder{field, binding.Decoder} + embeddedBindings = append(embeddedBindings, binding) + } + continue + } else if field.Type().Kind() == reflect.Ptr { + ptrType := field.Type().(*reflect2.UnsafePtrType) + if ptrType.Elem().Kind() == reflect.Struct { + structDescriptor := describeStruct(ctx, ptrType.Elem()) + for _, binding := range structDescriptor.Fields { + binding.levels = append([]int{i}, binding.levels...) + omitempty := binding.Encoder.(*structFieldEncoder).omitempty + binding.Encoder = &dereferenceEncoder{binding.Encoder} + binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty} + binding.Decoder = &dereferenceDecoder{ptrType.Elem(), binding.Decoder} + binding.Decoder = &structFieldDecoder{field, binding.Decoder} + embeddedBindings = append(embeddedBindings, binding) + } + continue + } + } + } + fieldNames := calcFieldNames(field.Name(), tagParts[0], tag) + fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name()) + decoder := fieldDecoders[fieldCacheKey] + if decoder == nil { + decoder = decoderOfType(ctx.append(field.Name()), field.Type()) + } + encoder := fieldEncoders[fieldCacheKey] + if encoder == nil { + encoder = encoderOfType(ctx.append(field.Name()), field.Type()) + } + binding := &Binding{ + Field: field, + FromNames: fieldNames, + ToNames: fieldNames, + Decoder: decoder, + Encoder: encoder, + } + binding.levels = []int{i} + bindings = append(bindings, binding) + } + return createStructDescriptor(ctx, typ, bindings, embeddedBindings) +} +func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { + structDescriptor := &StructDescriptor{ + Type: typ, + Fields: bindings, + } + for _, extension := range extensions { + extension.UpdateStructDescriptor(structDescriptor) + } + ctx.encoderExtension.UpdateStructDescriptor(structDescriptor) + ctx.decoderExtension.UpdateStructDescriptor(structDescriptor) + for _, extension := range ctx.extraExtensions { + extension.UpdateStructDescriptor(structDescriptor) + } + processTags(structDescriptor, ctx.frozenConfig) + // merge normal & embedded bindings & sort with original order + allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...)) + sort.Sort(allBindings) + structDescriptor.Fields = allBindings + return structDescriptor +} + +type sortableBindings []*Binding + +func (bindings sortableBindings) Len() int { + return len(bindings) +} + +func (bindings sortableBindings) Less(i, j int) bool { + left := bindings[i].levels + right := bindings[j].levels + k := 0 + for { + if left[k] < right[k] { + return true + } else if left[k] > right[k] { + return false + } + k++ + } +} + +func (bindings sortableBindings) Swap(i, j int) { + bindings[i], bindings[j] = bindings[j], bindings[i] +} + +func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) { + for _, binding := range structDescriptor.Fields { + shouldOmitEmpty := false + tagParts := strings.Split(binding.Field.Tag().Get(cfg.getTagKey()), ",") + for _, tagPart := range tagParts[1:] { + if tagPart == "omitempty" { + shouldOmitEmpty = true + } else if tagPart == "string" { + if binding.Field.Type().Kind() == reflect.String { + binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg} + binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg} + } else { + binding.Decoder = &stringModeNumberDecoder{binding.Decoder} + binding.Encoder = &stringModeNumberEncoder{binding.Encoder} + } + } + } + binding.Decoder = &structFieldDecoder{binding.Field, binding.Decoder} + binding.Encoder = &structFieldEncoder{binding.Field, binding.Encoder, shouldOmitEmpty} + } +} + +func calcFieldNames(originalFieldName string, tagProvidedFieldName string, wholeTag string) []string { + // ignore? + if wholeTag == "-" { + return []string{} + } + // rename? + var fieldNames []string + if tagProvidedFieldName == "" { + fieldNames = []string{originalFieldName} + } else { + fieldNames = []string{tagProvidedFieldName} + } + // private? + isNotExported := unicode.IsLower(rune(originalFieldName[0])) + if isNotExported { + fieldNames = []string{} + } + return fieldNames +} diff --git a/vendor/github.com/json-iterator/go/reflect_json_number.go b/vendor/github.com/json-iterator/go/reflect_json_number.go new file mode 100644 index 0000000..98d45c1 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_json_number.go @@ -0,0 +1,112 @@ +package jsoniter + +import ( + "encoding/json" + "github.com/modern-go/reflect2" + "strconv" + "unsafe" +) + +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +func CastJsonNumber(val interface{}) (string, bool) { + switch typedVal := val.(type) { + case json.Number: + return string(typedVal), true + case Number: + return string(typedVal), true + } + return "", false +} + +var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem() +var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem() + +func createDecoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ.AssignableTo(jsonNumberType) { + return &jsonNumberCodec{} + } + if typ.AssignableTo(jsoniterNumberType) { + return &jsoniterNumberCodec{} + } + return nil +} + +func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ.AssignableTo(jsonNumberType) { + return &jsonNumberCodec{} + } + if typ.AssignableTo(jsoniterNumberType) { + return &jsoniterNumberCodec{} + } + return nil +} + +type jsonNumberCodec struct { +} + +func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + switch iter.WhatIsNext() { + case StringValue: + *((*json.Number)(ptr)) = json.Number(iter.ReadString()) + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + *((*json.Number)(ptr)) = "" + default: + *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString())) + } +} + +func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + number := *((*json.Number)(ptr)) + if len(number) == 0 { + stream.writeByte('0') + } else { + stream.WriteRaw(string(number)) + } +} + +func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*json.Number)(ptr))) == 0 +} + +type jsoniterNumberCodec struct { +} + +func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + switch iter.WhatIsNext() { + case StringValue: + *((*Number)(ptr)) = Number(iter.ReadString()) + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + *((*Number)(ptr)) = "" + default: + *((*Number)(ptr)) = Number([]byte(iter.readNumberAsString())) + } +} + +func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + number := *((*Number)(ptr)) + if len(number) == 0 { + stream.writeByte('0') + } else { + stream.WriteRaw(string(number)) + } +} + +func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*Number)(ptr))) == 0 +} diff --git a/vendor/github.com/json-iterator/go/reflect_json_raw_message.go b/vendor/github.com/json-iterator/go/reflect_json_raw_message.go new file mode 100644 index 0000000..f261993 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_json_raw_message.go @@ -0,0 +1,60 @@ +package jsoniter + +import ( + "encoding/json" + "github.com/modern-go/reflect2" + "unsafe" +) + +var jsonRawMessageType = reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem() +var jsoniterRawMessageType = reflect2.TypeOfPtr((*RawMessage)(nil)).Elem() + +func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ == jsonRawMessageType { + return &jsonRawMessageCodec{} + } + if typ == jsoniterRawMessageType { + return &jsoniterRawMessageCodec{} + } + return nil +} + +func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ == jsonRawMessageType { + return &jsonRawMessageCodec{} + } + if typ == jsoniterRawMessageType { + return &jsoniterRawMessageCodec{} + } + return nil +} + +type jsonRawMessageCodec struct { +} + +func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes()) +} + +func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteRaw(string(*((*json.RawMessage)(ptr)))) +} + +func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*json.RawMessage)(ptr))) == 0 +} + +type jsoniterRawMessageCodec struct { +} + +func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes()) +} + +func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteRaw(string(*((*RawMessage)(ptr)))) +} + +func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*RawMessage)(ptr))) == 0 +} diff --git a/vendor/github.com/json-iterator/go/reflect_map.go b/vendor/github.com/json-iterator/go/reflect_map.go new file mode 100644 index 0000000..7f66a88 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_map.go @@ -0,0 +1,326 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "reflect" + "sort" + "unsafe" +) + +func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder { + mapType := typ.(*reflect2.UnsafeMapType) + keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()) + elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem()) + return &mapDecoder{ + mapType: mapType, + keyType: mapType.Key(), + elemType: mapType.Elem(), + keyDecoder: keyDecoder, + elemDecoder: elemDecoder, + } +} + +func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder { + mapType := typ.(*reflect2.UnsafeMapType) + if ctx.sortMapKeys { + return &sortKeysMapEncoder{ + mapType: mapType, + keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()), + elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()), + } + } + return &mapEncoder{ + mapType: mapType, + keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()), + elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()), + } +} + +func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := ctx.decoderExtension.CreateMapKeyDecoder(typ) + if decoder != nil { + return decoder + } + for _, extension := range ctx.extraExtensions { + decoder := extension.CreateMapKeyDecoder(typ) + if decoder != nil { + return decoder + } + } + switch typ.Kind() { + case reflect.String: + return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) + case reflect.Bool, + reflect.Uint8, reflect.Int8, + reflect.Uint16, reflect.Int16, + reflect.Uint32, reflect.Int32, + reflect.Uint64, reflect.Int64, + reflect.Uint, reflect.Int, + reflect.Float32, reflect.Float64, + reflect.Uintptr: + typ = reflect2.DefaultTypeOfKind(typ.Kind()) + return &numericMapKeyDecoder{decoderOfType(ctx, typ)} + default: + ptrType := reflect2.PtrTo(typ) + if ptrType.Implements(textMarshalerType) { + return &referenceDecoder{ + &textUnmarshalerDecoder{ + valType: ptrType, + }, + } + } + if typ.Implements(textMarshalerType) { + return &textUnmarshalerDecoder{ + valType: typ, + } + } + return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)} + } +} + +func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := ctx.encoderExtension.CreateMapKeyEncoder(typ) + if encoder != nil { + return encoder + } + for _, extension := range ctx.extraExtensions { + encoder := extension.CreateMapKeyEncoder(typ) + if encoder != nil { + return encoder + } + } + switch typ.Kind() { + case reflect.String: + return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) + case reflect.Bool, + reflect.Uint8, reflect.Int8, + reflect.Uint16, reflect.Int16, + reflect.Uint32, reflect.Int32, + reflect.Uint64, reflect.Int64, + reflect.Uint, reflect.Int, + reflect.Float32, reflect.Float64, + reflect.Uintptr: + typ = reflect2.DefaultTypeOfKind(typ.Kind()) + return &numericMapKeyEncoder{encoderOfType(ctx, typ)} + default: + if typ == textMarshalerType { + return &directTextMarshalerEncoder{ + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + } + } + if typ.Implements(textMarshalerType) { + return &textMarshalerEncoder{ + valType: typ, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + } + } + if typ.Kind() == reflect.Interface { + return &dynamicMapKeyEncoder{ctx, typ} + } + return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)} + } +} + +type mapDecoder struct { + mapType *reflect2.UnsafeMapType + keyType reflect2.Type + elemType reflect2.Type + keyDecoder ValDecoder + elemDecoder ValDecoder +} + +func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + mapType := decoder.mapType + c := iter.nextToken() + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + *(*unsafe.Pointer)(ptr) = nil + mapType.UnsafeSet(ptr, mapType.UnsafeNew()) + return + } + if mapType.UnsafeIsNil(ptr) { + mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0)) + } + if c != '{' { + iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c})) + return + } + c = iter.nextToken() + if c == '}' { + return + } + if c != '"' { + iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c})) + return + } + iter.unreadByte() + key := decoder.keyType.UnsafeNew() + decoder.keyDecoder.Decode(key, iter) + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return + } + elem := decoder.elemType.UnsafeNew() + decoder.elemDecoder.Decode(elem, iter) + decoder.mapType.UnsafeSetIndex(ptr, key, elem) + for c = iter.nextToken(); c == ','; c = iter.nextToken() { + key := decoder.keyType.UnsafeNew() + decoder.keyDecoder.Decode(key, iter) + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return + } + elem := decoder.elemType.UnsafeNew() + decoder.elemDecoder.Decode(elem, iter) + decoder.mapType.UnsafeSetIndex(ptr, key, elem) + } + if c != '}' { + iter.ReportError("ReadMapCB", `expect }, but found `+string([]byte{c})) + } +} + +type numericMapKeyDecoder struct { + decoder ValDecoder +} + +func (decoder *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + if c != '"' { + iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c})) + return + } + decoder.decoder.Decode(ptr, iter) + c = iter.nextToken() + if c != '"' { + iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c})) + return + } +} + +type numericMapKeyEncoder struct { + encoder ValEncoder +} + +func (encoder *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.writeByte('"') + encoder.encoder.Encode(ptr, stream) + stream.writeByte('"') +} + +func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type dynamicMapKeyEncoder struct { + ctx *ctx + valType reflect2.Type +} + +func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream) +} + +func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { + obj := encoder.valType.UnsafeIndirect(ptr) + return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj)) +} + +type mapEncoder struct { + mapType *reflect2.UnsafeMapType + keyEncoder ValEncoder + elemEncoder ValEncoder +} + +func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteObjectStart() + iter := encoder.mapType.UnsafeIterate(ptr) + for i := 0; iter.HasNext(); i++ { + if i != 0 { + stream.WriteMore() + } + key, elem := iter.UnsafeNext() + encoder.keyEncoder.Encode(key, stream) + if stream.indention > 0 { + stream.writeTwoBytes(byte(':'), byte(' ')) + } else { + stream.writeByte(':') + } + encoder.elemEncoder.Encode(elem, stream) + } + stream.WriteObjectEnd() +} + +func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool { + iter := encoder.mapType.UnsafeIterate(ptr) + return !iter.HasNext() +} + +type sortKeysMapEncoder struct { + mapType *reflect2.UnsafeMapType + keyEncoder ValEncoder + elemEncoder ValEncoder +} + +func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if *(*unsafe.Pointer)(ptr) == nil { + stream.WriteNil() + return + } + stream.WriteObjectStart() + mapIter := encoder.mapType.UnsafeIterate(ptr) + subStream := stream.cfg.BorrowStream(nil) + subIter := stream.cfg.BorrowIterator(nil) + keyValues := encodedKeyValues{} + for mapIter.HasNext() { + subStream.buf = make([]byte, 0, 64) + key, elem := mapIter.UnsafeNext() + encoder.keyEncoder.Encode(key, subStream) + if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil { + stream.Error = subStream.Error + } + encodedKey := subStream.Buffer() + subIter.ResetBytes(encodedKey) + decodedKey := subIter.ReadString() + if stream.indention > 0 { + subStream.writeTwoBytes(byte(':'), byte(' ')) + } else { + subStream.writeByte(':') + } + encoder.elemEncoder.Encode(elem, subStream) + keyValues = append(keyValues, encodedKV{ + key: decodedKey, + keyValue: subStream.Buffer(), + }) + } + sort.Sort(keyValues) + for i, keyValue := range keyValues { + if i != 0 { + stream.WriteMore() + } + stream.Write(keyValue.keyValue) + } + stream.WriteObjectEnd() + stream.cfg.ReturnStream(subStream) + stream.cfg.ReturnIterator(subIter) +} + +func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool { + iter := encoder.mapType.UnsafeIterate(ptr) + return !iter.HasNext() +} + +type encodedKeyValues []encodedKV + +type encodedKV struct { + key string + keyValue []byte +} + +func (sv encodedKeyValues) Len() int { return len(sv) } +func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } +func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key } diff --git a/vendor/github.com/json-iterator/go/reflect_marshaler.go b/vendor/github.com/json-iterator/go/reflect_marshaler.go new file mode 100644 index 0000000..58ac959 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_marshaler.go @@ -0,0 +1,218 @@ +package jsoniter + +import ( + "encoding" + "encoding/json" + "github.com/modern-go/reflect2" + "unsafe" +) + +var marshalerType = reflect2.TypeOfPtr((*json.Marshaler)(nil)).Elem() +var unmarshalerType = reflect2.TypeOfPtr((*json.Unmarshaler)(nil)).Elem() +var textMarshalerType = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem() +var textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem() + +func createDecoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValDecoder { + ptrType := reflect2.PtrTo(typ) + if ptrType.Implements(unmarshalerType) { + return &referenceDecoder{ + &unmarshalerDecoder{ptrType}, + } + } + if ptrType.Implements(textUnmarshalerType) { + return &referenceDecoder{ + &textUnmarshalerDecoder{ptrType}, + } + } + return nil +} + +func createEncoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ == marshalerType { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &directMarshalerEncoder{ + checkIsEmpty: checkIsEmpty, + } + return encoder + } + if typ.Implements(marshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &marshalerEncoder{ + valType: typ, + checkIsEmpty: checkIsEmpty, + } + return encoder + } + ptrType := reflect2.PtrTo(typ) + if ctx.prefix != "" && ptrType.Implements(marshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, ptrType) + var encoder ValEncoder = &marshalerEncoder{ + valType: ptrType, + checkIsEmpty: checkIsEmpty, + } + return &referenceEncoder{encoder} + } + if typ == textMarshalerType { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &directTextMarshalerEncoder{ + checkIsEmpty: checkIsEmpty, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + } + return encoder + } + if typ.Implements(textMarshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &textMarshalerEncoder{ + valType: typ, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + checkIsEmpty: checkIsEmpty, + } + return encoder + } + // if prefix is empty, the type is the root type + if ctx.prefix != "" && ptrType.Implements(textMarshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, ptrType) + var encoder ValEncoder = &textMarshalerEncoder{ + valType: ptrType, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + checkIsEmpty: checkIsEmpty, + } + return &referenceEncoder{encoder} + } + return nil +} + +type marshalerEncoder struct { + checkIsEmpty checkIsEmpty + valType reflect2.Type +} + +func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + if encoder.valType.IsNullable() && reflect2.IsNil(obj) { + stream.WriteNil() + return + } + marshaler := obj.(json.Marshaler) + bytes, err := marshaler.MarshalJSON() + if err != nil { + stream.Error = err + } else { + stream.Write(bytes) + } +} + +func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type directMarshalerEncoder struct { + checkIsEmpty checkIsEmpty +} + +func (encoder *directMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + marshaler := *(*json.Marshaler)(ptr) + if marshaler == nil { + stream.WriteNil() + return + } + bytes, err := marshaler.MarshalJSON() + if err != nil { + stream.Error = err + } else { + stream.Write(bytes) + } +} + +func (encoder *directMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type textMarshalerEncoder struct { + valType reflect2.Type + stringEncoder ValEncoder + checkIsEmpty checkIsEmpty +} + +func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + if encoder.valType.IsNullable() && reflect2.IsNil(obj) { + stream.WriteNil() + return + } + marshaler := (obj).(encoding.TextMarshaler) + bytes, err := marshaler.MarshalText() + if err != nil { + stream.Error = err + } else { + str := string(bytes) + encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream) + } +} + +func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type directTextMarshalerEncoder struct { + stringEncoder ValEncoder + checkIsEmpty checkIsEmpty +} + +func (encoder *directTextMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + marshaler := *(*encoding.TextMarshaler)(ptr) + if marshaler == nil { + stream.WriteNil() + return + } + bytes, err := marshaler.MarshalText() + if err != nil { + stream.Error = err + } else { + str := string(bytes) + encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream) + } +} + +func (encoder *directTextMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type unmarshalerDecoder struct { + valType reflect2.Type +} + +func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + valType := decoder.valType + obj := valType.UnsafeIndirect(ptr) + unmarshaler := obj.(json.Unmarshaler) + iter.nextToken() + iter.unreadByte() // skip spaces + bytes := iter.SkipAndReturnBytes() + err := unmarshaler.UnmarshalJSON(bytes) + if err != nil { + iter.ReportError("unmarshalerDecoder", err.Error()) + } +} + +type textUnmarshalerDecoder struct { + valType reflect2.Type +} + +func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + valType := decoder.valType + obj := valType.UnsafeIndirect(ptr) + if reflect2.IsNil(obj) { + ptrType := valType.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + elem := elemType.UnsafeNew() + ptrType.UnsafeSet(ptr, unsafe.Pointer(&elem)) + obj = valType.UnsafeIndirect(ptr) + } + unmarshaler := (obj).(encoding.TextUnmarshaler) + str := iter.ReadString() + err := unmarshaler.UnmarshalText([]byte(str)) + if err != nil { + iter.ReportError("textUnmarshalerDecoder", err.Error()) + } +} diff --git a/vendor/github.com/json-iterator/go/reflect_native.go b/vendor/github.com/json-iterator/go/reflect_native.go new file mode 100644 index 0000000..9042eb0 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_native.go @@ -0,0 +1,451 @@ +package jsoniter + +import ( + "encoding/base64" + "reflect" + "strconv" + "unsafe" + + "github.com/modern-go/reflect2" +) + +const ptrSize = 32 << uintptr(^uintptr(0)>>63) + +func createEncoderOfNative(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { + sliceDecoder := decoderOfSlice(ctx, typ) + return &base64Codec{sliceDecoder: sliceDecoder} + } + typeName := typ.String() + kind := typ.Kind() + switch kind { + case reflect.String: + if typeName != "string" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem()) + } + return &stringCodec{} + case reflect.Int: + if typeName != "int" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &int32Codec{} + } + return &int64Codec{} + case reflect.Int8: + if typeName != "int8" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem()) + } + return &int8Codec{} + case reflect.Int16: + if typeName != "int16" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem()) + } + return &int16Codec{} + case reflect.Int32: + if typeName != "int32" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem()) + } + return &int32Codec{} + case reflect.Int64: + if typeName != "int64" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem()) + } + return &int64Codec{} + case reflect.Uint: + if typeName != "uint" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint8: + if typeName != "uint8" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem()) + } + return &uint8Codec{} + case reflect.Uint16: + if typeName != "uint16" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem()) + } + return &uint16Codec{} + case reflect.Uint32: + if typeName != "uint32" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem()) + } + return &uint32Codec{} + case reflect.Uintptr: + if typeName != "uintptr" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem()) + } + if ptrSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint64: + if typeName != "uint64" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem()) + } + return &uint64Codec{} + case reflect.Float32: + if typeName != "float32" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem()) + } + return &float32Codec{} + case reflect.Float64: + if typeName != "float64" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem()) + } + return &float64Codec{} + case reflect.Bool: + if typeName != "bool" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem()) + } + return &boolCodec{} + } + return nil +} + +func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { + sliceDecoder := decoderOfSlice(ctx, typ) + return &base64Codec{sliceDecoder: sliceDecoder} + } + typeName := typ.String() + switch typ.Kind() { + case reflect.String: + if typeName != "string" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem()) + } + return &stringCodec{} + case reflect.Int: + if typeName != "int" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &int32Codec{} + } + return &int64Codec{} + case reflect.Int8: + if typeName != "int8" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem()) + } + return &int8Codec{} + case reflect.Int16: + if typeName != "int16" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem()) + } + return &int16Codec{} + case reflect.Int32: + if typeName != "int32" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem()) + } + return &int32Codec{} + case reflect.Int64: + if typeName != "int64" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem()) + } + return &int64Codec{} + case reflect.Uint: + if typeName != "uint" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint8: + if typeName != "uint8" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem()) + } + return &uint8Codec{} + case reflect.Uint16: + if typeName != "uint16" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem()) + } + return &uint16Codec{} + case reflect.Uint32: + if typeName != "uint32" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem()) + } + return &uint32Codec{} + case reflect.Uintptr: + if typeName != "uintptr" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem()) + } + if ptrSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint64: + if typeName != "uint64" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem()) + } + return &uint64Codec{} + case reflect.Float32: + if typeName != "float32" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem()) + } + return &float32Codec{} + case reflect.Float64: + if typeName != "float64" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem()) + } + return &float64Codec{} + case reflect.Bool: + if typeName != "bool" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem()) + } + return &boolCodec{} + } + return nil +} + +type stringCodec struct { +} + +func (codec *stringCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*string)(ptr)) = iter.ReadString() +} + +func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + str := *((*string)(ptr)) + stream.WriteString(str) +} + +func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*string)(ptr)) == "" +} + +type int8Codec struct { +} + +func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int8)(ptr)) = iter.ReadInt8() + } +} + +func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt8(*((*int8)(ptr))) +} + +func (codec *int8Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int8)(ptr)) == 0 +} + +type int16Codec struct { +} + +func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int16)(ptr)) = iter.ReadInt16() + } +} + +func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt16(*((*int16)(ptr))) +} + +func (codec *int16Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int16)(ptr)) == 0 +} + +type int32Codec struct { +} + +func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int32)(ptr)) = iter.ReadInt32() + } +} + +func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt32(*((*int32)(ptr))) +} + +func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int32)(ptr)) == 0 +} + +type int64Codec struct { +} + +func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int64)(ptr)) = iter.ReadInt64() + } +} + +func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt64(*((*int64)(ptr))) +} + +func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int64)(ptr)) == 0 +} + +type uint8Codec struct { +} + +func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint8)(ptr)) = iter.ReadUint8() + } +} + +func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint8(*((*uint8)(ptr))) +} + +func (codec *uint8Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint8)(ptr)) == 0 +} + +type uint16Codec struct { +} + +func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint16)(ptr)) = iter.ReadUint16() + } +} + +func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint16(*((*uint16)(ptr))) +} + +func (codec *uint16Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint16)(ptr)) == 0 +} + +type uint32Codec struct { +} + +func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint32)(ptr)) = iter.ReadUint32() + } +} + +func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint32(*((*uint32)(ptr))) +} + +func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint32)(ptr)) == 0 +} + +type uint64Codec struct { +} + +func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint64)(ptr)) = iter.ReadUint64() + } +} + +func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint64(*((*uint64)(ptr))) +} + +func (codec *uint64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint64)(ptr)) == 0 +} + +type float32Codec struct { +} + +func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*float32)(ptr)) = iter.ReadFloat32() + } +} + +func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat32(*((*float32)(ptr))) +} + +func (codec *float32Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float32)(ptr)) == 0 +} + +type float64Codec struct { +} + +func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*float64)(ptr)) = iter.ReadFloat64() + } +} + +func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat64(*((*float64)(ptr))) +} + +func (codec *float64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float64)(ptr)) == 0 +} + +type boolCodec struct { +} + +func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*bool)(ptr)) = iter.ReadBool() + } +} + +func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteBool(*((*bool)(ptr))) +} + +func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool { + return !(*((*bool)(ptr))) +} + +type base64Codec struct { + sliceType *reflect2.UnsafeSliceType + sliceDecoder ValDecoder +} + +func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.ReadNil() { + codec.sliceType.UnsafeSetNil(ptr) + return + } + switch iter.WhatIsNext() { + case StringValue: + src := iter.ReadString() + dst, err := base64.StdEncoding.DecodeString(src) + if err != nil { + iter.ReportError("decode base64", err.Error()) + } else { + codec.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst)) + } + case ArrayValue: + codec.sliceDecoder.Decode(ptr, iter) + default: + iter.ReportError("base64Codec", "invalid input") + } +} + +func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + src := *((*[]byte)(ptr)) + if len(src) == 0 { + stream.WriteNil() + return + } + encoding := base64.StdEncoding + stream.writeByte('"') + size := encoding.EncodedLen(len(src)) + buf := make([]byte, size) + encoding.Encode(buf, src) + stream.buf = append(stream.buf, buf...) + stream.writeByte('"') +} + +func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*[]byte)(ptr))) == 0 +} diff --git a/vendor/github.com/json-iterator/go/reflect_optional.go b/vendor/github.com/json-iterator/go/reflect_optional.go new file mode 100644 index 0000000..43ec71d --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_optional.go @@ -0,0 +1,133 @@ +package jsoniter + +import ( + "github.com/modern-go/reflect2" + "reflect" + "unsafe" +) + +func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder { + ptrType := typ.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + decoder := decoderOfType(ctx, elemType) + if ctx.prefix == "" && elemType.Kind() == reflect.Ptr { + return &dereferenceDecoder{elemType, decoder} + } + return &OptionalDecoder{elemType, decoder} +} + +func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder { + ptrType := typ.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + elemEncoder := encoderOfType(ctx, elemType) + encoder := &OptionalEncoder{elemEncoder} + return encoder +} + +type OptionalDecoder struct { + ValueType reflect2.Type + ValueDecoder ValDecoder +} + +func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.ReadNil() { + *((*unsafe.Pointer)(ptr)) = nil + } else { + if *((*unsafe.Pointer)(ptr)) == nil { + //pointer to null, we have to allocate memory to hold the value + newPtr := decoder.ValueType.UnsafeNew() + decoder.ValueDecoder.Decode(newPtr, iter) + *((*unsafe.Pointer)(ptr)) = newPtr + } else { + //reuse existing instance + decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) + } + } +} + +type dereferenceDecoder struct { + // only to deference a pointer + valueType reflect2.Type + valueDecoder ValDecoder +} + +func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if *((*unsafe.Pointer)(ptr)) == nil { + //pointer to null, we have to allocate memory to hold the value + newPtr := decoder.valueType.UnsafeNew() + decoder.valueDecoder.Decode(newPtr, iter) + *((*unsafe.Pointer)(ptr)) = newPtr + } else { + //reuse existing instance + decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) + } +} + +type OptionalEncoder struct { + ValueEncoder ValEncoder +} + +func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if *((*unsafe.Pointer)(ptr)) == nil { + stream.WriteNil() + } else { + encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) + } +} + +func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*unsafe.Pointer)(ptr)) == nil +} + +type dereferenceEncoder struct { + ValueEncoder ValEncoder +} + +func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if *((*unsafe.Pointer)(ptr)) == nil { + stream.WriteNil() + } else { + encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) + } +} + +func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { + dePtr := *((*unsafe.Pointer)(ptr)) + if dePtr == nil { + return true + } + return encoder.ValueEncoder.IsEmpty(dePtr) +} + +func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { + deReferenced := *((*unsafe.Pointer)(ptr)) + if deReferenced == nil { + return true + } + isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil) + if !converted { + return false + } + fieldPtr := unsafe.Pointer(deReferenced) + return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr) +} + +type referenceEncoder struct { + encoder ValEncoder +} + +func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) +} + +func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) +} + +type referenceDecoder struct { + decoder ValDecoder +} + +func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.decoder.Decode(unsafe.Pointer(&ptr), iter) +} diff --git a/vendor/github.com/json-iterator/go/reflect_slice.go b/vendor/github.com/json-iterator/go/reflect_slice.go new file mode 100644 index 0000000..9441d79 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_slice.go @@ -0,0 +1,99 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "unsafe" +) + +func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder { + sliceType := typ.(*reflect2.UnsafeSliceType) + decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) + return &sliceDecoder{sliceType, decoder} +} + +func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder { + sliceType := typ.(*reflect2.UnsafeSliceType) + encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) + return &sliceEncoder{sliceType, encoder} +} + +type sliceEncoder struct { + sliceType *reflect2.UnsafeSliceType + elemEncoder ValEncoder +} + +func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if encoder.sliceType.UnsafeIsNil(ptr) { + stream.WriteNil() + return + } + length := encoder.sliceType.UnsafeLengthOf(ptr) + if length == 0 { + stream.WriteEmptyArray() + return + } + stream.WriteArrayStart() + encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream) + for i := 1; i < length; i++ { + stream.WriteMore() + elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i) + encoder.elemEncoder.Encode(elemPtr, stream) + } + stream.WriteArrayEnd() + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error()) + } +} + +func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.sliceType.UnsafeLengthOf(ptr) == 0 +} + +type sliceDecoder struct { + sliceType *reflect2.UnsafeSliceType + elemDecoder ValDecoder +} + +func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.doDecode(ptr, iter) + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error()) + } +} + +func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + sliceType := decoder.sliceType + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + sliceType.UnsafeSetNil(ptr) + return + } + if c != '[' { + iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c})) + return + } + c = iter.nextToken() + if c == ']' { + sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0)) + return + } + iter.unreadByte() + sliceType.UnsafeGrow(ptr, 1) + elemPtr := sliceType.UnsafeGetIndex(ptr, 0) + decoder.elemDecoder.Decode(elemPtr, iter) + length := 1 + for c = iter.nextToken(); c == ','; c = iter.nextToken() { + idx := length + length += 1 + sliceType.UnsafeGrow(ptr, length) + elemPtr = sliceType.UnsafeGetIndex(ptr, idx) + decoder.elemDecoder.Decode(elemPtr, iter) + } + if c != ']' { + iter.ReportError("decode slice", "expect ], but found "+string([]byte{c})) + return + } +} diff --git a/vendor/github.com/json-iterator/go/reflect_struct_decoder.go b/vendor/github.com/json-iterator/go/reflect_struct_decoder.go new file mode 100644 index 0000000..355d2d1 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_struct_decoder.go @@ -0,0 +1,1048 @@ +package jsoniter + +import ( + "fmt" + "io" + "strings" + "unsafe" + + "github.com/modern-go/reflect2" +) + +func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { + bindings := map[string]*Binding{} + structDescriptor := describeStruct(ctx, typ) + for _, binding := range structDescriptor.Fields { + for _, fromName := range binding.FromNames { + old := bindings[fromName] + if old == nil { + bindings[fromName] = binding + continue + } + ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding) + if ignoreOld { + delete(bindings, fromName) + } + if !ignoreNew { + bindings[fromName] = binding + } + } + } + fields := map[string]*structFieldDecoder{} + for k, binding := range bindings { + fields[k] = binding.Decoder.(*structFieldDecoder) + } + + if !ctx.caseSensitive() { + for k, binding := range bindings { + if _, found := fields[strings.ToLower(k)]; !found { + fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) + } + } + } + + return createStructDecoder(ctx, typ, fields) +} + +func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder { + if ctx.disallowUnknownFields { + return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true} + } + knownHash := map[int64]struct{}{ + 0: {}, + } + + switch len(fields) { + case 0: + return &skipObjectDecoder{typ} + case 1: + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder} + } + case 2: + var fieldHash1 int64 + var fieldHash2 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldHash1 == 0 { + fieldHash1 = fieldHash + fieldDecoder1 = fieldDecoder + } else { + fieldHash2 = fieldHash + fieldDecoder2 = fieldDecoder + } + } + return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2} + case 3: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } + } + return &threeFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3} + case 4: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } + } + return &fourFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4} + case 5: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } + } + return &fiveFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5} + case 6: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } + } + return &sixFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6} + case 7: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } + } + return &sevenFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7} + case 8: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldName8 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + var fieldDecoder8 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else if fieldName7 == 0 { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } else { + fieldName8 = fieldHash + fieldDecoder8 = fieldDecoder + } + } + return &eightFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7, + fieldName8, fieldDecoder8} + case 9: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldName8 int64 + var fieldName9 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + var fieldDecoder8 *structFieldDecoder + var fieldDecoder9 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else if fieldName7 == 0 { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } else if fieldName8 == 0 { + fieldName8 = fieldHash + fieldDecoder8 = fieldDecoder + } else { + fieldName9 = fieldHash + fieldDecoder9 = fieldDecoder + } + } + return &nineFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7, + fieldName8, fieldDecoder8, + fieldName9, fieldDecoder9} + case 10: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldName8 int64 + var fieldName9 int64 + var fieldName10 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + var fieldDecoder8 *structFieldDecoder + var fieldDecoder9 *structFieldDecoder + var fieldDecoder10 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else if fieldName7 == 0 { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } else if fieldName8 == 0 { + fieldName8 = fieldHash + fieldDecoder8 = fieldDecoder + } else if fieldName9 == 0 { + fieldName9 = fieldHash + fieldDecoder9 = fieldDecoder + } else { + fieldName10 = fieldHash + fieldDecoder10 = fieldDecoder + } + } + return &tenFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7, + fieldName8, fieldDecoder8, + fieldName9, fieldDecoder9, + fieldName10, fieldDecoder10} + } + return &generalStructDecoder{typ, fields, false} +} + +type generalStructDecoder struct { + typ reflect2.Type + fields map[string]*structFieldDecoder + disallowUnknownFields bool +} + +func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + var c byte + for c = ','; c == ','; c = iter.nextToken() { + decoder.decodeOneField(ptr, iter) + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } + if c != '}' { + iter.ReportError("struct Decode", `expect }, but found `+string([]byte{c})) + } +} + +func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) { + var field string + var fieldDecoder *structFieldDecoder + if iter.cfg.objectFieldMustBeSimpleString { + fieldBytes := iter.ReadStringAsSlice() + field = *(*string)(unsafe.Pointer(&fieldBytes)) + fieldDecoder = decoder.fields[field] + if fieldDecoder == nil && !iter.cfg.caseSensitive { + fieldDecoder = decoder.fields[strings.ToLower(field)] + } + } else { + field = iter.ReadString() + fieldDecoder = decoder.fields[field] + if fieldDecoder == nil && !iter.cfg.caseSensitive { + fieldDecoder = decoder.fields[strings.ToLower(field)] + } + } + if fieldDecoder == nil { + msg := "found unknown field: " + field + if decoder.disallowUnknownFields { + iter.ReportError("ReadObject", msg) + } + c := iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + iter.Skip() + return + } + c := iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + fieldDecoder.Decode(ptr, iter) +} + +type skipObjectDecoder struct { + typ reflect2.Type +} + +func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + valueType := iter.WhatIsNext() + if valueType != ObjectValue && valueType != NilValue { + iter.ReportError("skipObjectDecoder", "expect object or null") + return + } + iter.Skip() +} + +type oneFieldStructDecoder struct { + typ reflect2.Type + fieldHash int64 + fieldDecoder *structFieldDecoder +} + +func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + if iter.readFieldHash() == decoder.fieldHash { + decoder.fieldDecoder.Decode(ptr, iter) + } else { + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type twoFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder +} + +func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type threeFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder +} + +func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type fourFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder +} + +func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type fiveFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder +} + +func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type sixFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder +} + +func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type sevenFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder +} + +func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type eightFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder + fieldHash8 int64 + fieldDecoder8 *structFieldDecoder +} + +func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + case decoder.fieldHash8: + decoder.fieldDecoder8.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type nineFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder + fieldHash8 int64 + fieldDecoder8 *structFieldDecoder + fieldHash9 int64 + fieldDecoder9 *structFieldDecoder +} + +func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + case decoder.fieldHash8: + decoder.fieldDecoder8.Decode(ptr, iter) + case decoder.fieldHash9: + decoder.fieldDecoder9.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type tenFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder + fieldHash8 int64 + fieldDecoder8 *structFieldDecoder + fieldHash9 int64 + fieldDecoder9 *structFieldDecoder + fieldHash10 int64 + fieldDecoder10 *structFieldDecoder +} + +func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + case decoder.fieldHash8: + decoder.fieldDecoder8.Decode(ptr, iter) + case decoder.fieldHash9: + decoder.fieldDecoder9.Decode(ptr, iter) + case decoder.fieldHash10: + decoder.fieldDecoder10.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type structFieldDecoder struct { + field reflect2.StructField + fieldDecoder ValDecoder +} + +func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + fieldPtr := decoder.field.UnsafeGet(ptr) + decoder.fieldDecoder.Decode(fieldPtr, iter) + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%s: %s", decoder.field.Name(), iter.Error.Error()) + } +} + +type stringModeStringDecoder struct { + elemDecoder ValDecoder + cfg *frozenConfig +} + +func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.elemDecoder.Decode(ptr, iter) + str := *((*string)(ptr)) + tempIter := decoder.cfg.BorrowIterator([]byte(str)) + defer decoder.cfg.ReturnIterator(tempIter) + *((*string)(ptr)) = tempIter.ReadString() +} + +type stringModeNumberDecoder struct { + elemDecoder ValDecoder +} + +func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + if c != '"' { + iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) + return + } + decoder.elemDecoder.Decode(ptr, iter) + if iter.Error != nil { + return + } + c = iter.readByte() + if c != '"' { + iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) + return + } +} diff --git a/vendor/github.com/json-iterator/go/reflect_struct_encoder.go b/vendor/github.com/json-iterator/go/reflect_struct_encoder.go new file mode 100644 index 0000000..d0759cf --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_struct_encoder.go @@ -0,0 +1,210 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "reflect" + "unsafe" +) + +func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder { + type bindingTo struct { + binding *Binding + toName string + ignored bool + } + orderedBindings := []*bindingTo{} + structDescriptor := describeStruct(ctx, typ) + for _, binding := range structDescriptor.Fields { + for _, toName := range binding.ToNames { + new := &bindingTo{ + binding: binding, + toName: toName, + } + for _, old := range orderedBindings { + if old.toName != toName { + continue + } + old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding) + } + orderedBindings = append(orderedBindings, new) + } + } + if len(orderedBindings) == 0 { + return &emptyStructEncoder{} + } + finalOrderedFields := []structFieldTo{} + for _, bindingTo := range orderedBindings { + if !bindingTo.ignored { + finalOrderedFields = append(finalOrderedFields, structFieldTo{ + encoder: bindingTo.binding.Encoder.(*structFieldEncoder), + toName: bindingTo.toName, + }) + } + } + return &structEncoder{typ, finalOrderedFields} +} + +func createCheckIsEmpty(ctx *ctx, typ reflect2.Type) checkIsEmpty { + encoder := createEncoderOfNative(ctx, typ) + if encoder != nil { + return encoder + } + kind := typ.Kind() + switch kind { + case reflect.Interface: + return &dynamicEncoder{typ} + case reflect.Struct: + return &structEncoder{typ: typ} + case reflect.Array: + return &arrayEncoder{} + case reflect.Slice: + return &sliceEncoder{} + case reflect.Map: + return encoderOfMap(ctx, typ) + case reflect.Ptr: + return &OptionalEncoder{} + default: + return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)} + } +} + +func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) { + newTagged := new.Field.Tag().Get(cfg.getTagKey()) != "" + oldTagged := old.Field.Tag().Get(cfg.getTagKey()) != "" + if newTagged { + if oldTagged { + if len(old.levels) > len(new.levels) { + return true, false + } else if len(new.levels) > len(old.levels) { + return false, true + } else { + return true, true + } + } else { + return true, false + } + } else { + if oldTagged { + return true, false + } + if len(old.levels) > len(new.levels) { + return true, false + } else if len(new.levels) > len(old.levels) { + return false, true + } else { + return true, true + } + } +} + +type structFieldEncoder struct { + field reflect2.StructField + fieldEncoder ValEncoder + omitempty bool +} + +func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + fieldPtr := encoder.field.UnsafeGet(ptr) + encoder.fieldEncoder.Encode(fieldPtr, stream) + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error()) + } +} + +func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool { + fieldPtr := encoder.field.UnsafeGet(ptr) + return encoder.fieldEncoder.IsEmpty(fieldPtr) +} + +func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { + isEmbeddedPtrNil, converted := encoder.fieldEncoder.(IsEmbeddedPtrNil) + if !converted { + return false + } + fieldPtr := encoder.field.UnsafeGet(ptr) + return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr) +} + +type IsEmbeddedPtrNil interface { + IsEmbeddedPtrNil(ptr unsafe.Pointer) bool +} + +type structEncoder struct { + typ reflect2.Type + fields []structFieldTo +} + +type structFieldTo struct { + encoder *structFieldEncoder + toName string +} + +func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteObjectStart() + isNotFirst := false + for _, field := range encoder.fields { + if field.encoder.omitempty && field.encoder.IsEmpty(ptr) { + continue + } + if field.encoder.IsEmbeddedPtrNil(ptr) { + continue + } + if isNotFirst { + stream.WriteMore() + } + stream.WriteObjectField(field.toName) + field.encoder.Encode(ptr, stream) + isNotFirst = true + } + stream.WriteObjectEnd() + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error()) + } +} + +func (encoder *structEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type emptyStructEncoder struct { +} + +func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteEmptyObject() +} + +func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type stringModeNumberEncoder struct { + elemEncoder ValEncoder +} + +func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.writeByte('"') + encoder.elemEncoder.Encode(ptr, stream) + stream.writeByte('"') +} + +func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.elemEncoder.IsEmpty(ptr) +} + +type stringModeStringEncoder struct { + elemEncoder ValEncoder + cfg *frozenConfig +} + +func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + tempStream := encoder.cfg.BorrowStream(nil) + defer encoder.cfg.ReturnStream(tempStream) + encoder.elemEncoder.Encode(ptr, tempStream) + stream.WriteString(string(tempStream.Buffer())) +} + +func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.elemEncoder.IsEmpty(ptr) +} diff --git a/vendor/github.com/json-iterator/go/stream.go b/vendor/github.com/json-iterator/go/stream.go new file mode 100644 index 0000000..17662fd --- /dev/null +++ b/vendor/github.com/json-iterator/go/stream.go @@ -0,0 +1,211 @@ +package jsoniter + +import ( + "io" +) + +// stream is a io.Writer like object, with JSON specific write functions. +// Error is not returned as return value, but stored as Error member on this stream instance. +type Stream struct { + cfg *frozenConfig + out io.Writer + buf []byte + Error error + indention int + Attachment interface{} // open for customized encoder +} + +// NewStream create new stream instance. +// cfg can be jsoniter.ConfigDefault. +// out can be nil if write to internal buffer. +// bufSize is the initial size for the internal buffer in bytes. +func NewStream(cfg API, out io.Writer, bufSize int) *Stream { + return &Stream{ + cfg: cfg.(*frozenConfig), + out: out, + buf: make([]byte, 0, bufSize), + Error: nil, + indention: 0, + } +} + +// Pool returns a pool can provide more stream with same configuration +func (stream *Stream) Pool() StreamPool { + return stream.cfg +} + +// Reset reuse this stream instance by assign a new writer +func (stream *Stream) Reset(out io.Writer) { + stream.out = out + stream.buf = stream.buf[:0] +} + +// Available returns how many bytes are unused in the buffer. +func (stream *Stream) Available() int { + return cap(stream.buf) - len(stream.buf) +} + +// Buffered returns the number of bytes that have been written into the current buffer. +func (stream *Stream) Buffered() int { + return len(stream.buf) +} + +// Buffer if writer is nil, use this method to take the result +func (stream *Stream) Buffer() []byte { + return stream.buf +} + +// SetBuffer allows to append to the internal buffer directly +func (stream *Stream) SetBuffer(buf []byte) { + stream.buf = buf +} + +// Write writes the contents of p into the buffer. +// It returns the number of bytes written. +// If nn < len(p), it also returns an error explaining +// why the write is short. +func (stream *Stream) Write(p []byte) (nn int, err error) { + stream.buf = append(stream.buf, p...) + if stream.out != nil { + nn, err = stream.out.Write(stream.buf) + stream.buf = stream.buf[nn:] + return + } + return len(p), nil +} + +// WriteByte writes a single byte. +func (stream *Stream) writeByte(c byte) { + stream.buf = append(stream.buf, c) +} + +func (stream *Stream) writeTwoBytes(c1 byte, c2 byte) { + stream.buf = append(stream.buf, c1, c2) +} + +func (stream *Stream) writeThreeBytes(c1 byte, c2 byte, c3 byte) { + stream.buf = append(stream.buf, c1, c2, c3) +} + +func (stream *Stream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) { + stream.buf = append(stream.buf, c1, c2, c3, c4) +} + +func (stream *Stream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) { + stream.buf = append(stream.buf, c1, c2, c3, c4, c5) +} + +// Flush writes any buffered data to the underlying io.Writer. +func (stream *Stream) Flush() error { + if stream.out == nil { + return nil + } + if stream.Error != nil { + return stream.Error + } + n, err := stream.out.Write(stream.buf) + if err != nil { + if stream.Error == nil { + stream.Error = err + } + return err + } + stream.buf = stream.buf[n:] + return nil +} + +// WriteRaw write string out without quotes, just like []byte +func (stream *Stream) WriteRaw(s string) { + stream.buf = append(stream.buf, s...) +} + +// WriteNil write null to stream +func (stream *Stream) WriteNil() { + stream.writeFourBytes('n', 'u', 'l', 'l') +} + +// WriteTrue write true to stream +func (stream *Stream) WriteTrue() { + stream.writeFourBytes('t', 'r', 'u', 'e') +} + +// WriteFalse write false to stream +func (stream *Stream) WriteFalse() { + stream.writeFiveBytes('f', 'a', 'l', 's', 'e') +} + +// WriteBool write true or false into stream +func (stream *Stream) WriteBool(val bool) { + if val { + stream.WriteTrue() + } else { + stream.WriteFalse() + } +} + +// WriteObjectStart write { with possible indention +func (stream *Stream) WriteObjectStart() { + stream.indention += stream.cfg.indentionStep + stream.writeByte('{') + stream.writeIndention(0) +} + +// WriteObjectField write "field": with possible indention +func (stream *Stream) WriteObjectField(field string) { + stream.WriteString(field) + if stream.indention > 0 { + stream.writeTwoBytes(':', ' ') + } else { + stream.writeByte(':') + } +} + +// WriteObjectEnd write } with possible indention +func (stream *Stream) WriteObjectEnd() { + stream.writeIndention(stream.cfg.indentionStep) + stream.indention -= stream.cfg.indentionStep + stream.writeByte('}') +} + +// WriteEmptyObject write {} +func (stream *Stream) WriteEmptyObject() { + stream.writeByte('{') + stream.writeByte('}') +} + +// WriteMore write , with possible indention +func (stream *Stream) WriteMore() { + stream.writeByte(',') + stream.writeIndention(0) + stream.Flush() +} + +// WriteArrayStart write [ with possible indention +func (stream *Stream) WriteArrayStart() { + stream.indention += stream.cfg.indentionStep + stream.writeByte('[') + stream.writeIndention(0) +} + +// WriteEmptyArray write [] +func (stream *Stream) WriteEmptyArray() { + stream.writeTwoBytes('[', ']') +} + +// WriteArrayEnd write ] with possible indention +func (stream *Stream) WriteArrayEnd() { + stream.writeIndention(stream.cfg.indentionStep) + stream.indention -= stream.cfg.indentionStep + stream.writeByte(']') +} + +func (stream *Stream) writeIndention(delta int) { + if stream.indention == 0 { + return + } + stream.writeByte('\n') + toWrite := stream.indention - delta + for i := 0; i < toWrite; i++ { + stream.buf = append(stream.buf, ' ') + } +} diff --git a/vendor/github.com/json-iterator/go/stream_float.go b/vendor/github.com/json-iterator/go/stream_float.go new file mode 100644 index 0000000..f318d2c --- /dev/null +++ b/vendor/github.com/json-iterator/go/stream_float.go @@ -0,0 +1,94 @@ +package jsoniter + +import ( + "math" + "strconv" +) + +var pow10 []uint64 + +func init() { + pow10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000} +} + +// WriteFloat32 write float32 to stream +func (stream *Stream) WriteFloat32(val float32) { + abs := math.Abs(float64(val)) + fmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if float32(abs) < 1e-6 || float32(abs) >= 1e21 { + fmt = 'e' + } + } + stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 32) +} + +// WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster +func (stream *Stream) WriteFloat32Lossy(val float32) { + if val < 0 { + stream.writeByte('-') + val = -val + } + if val > 0x4ffffff { + stream.WriteFloat32(val) + return + } + precision := 6 + exp := uint64(1000000) // 6 + lval := uint64(float64(val)*float64(exp) + 0.5) + stream.WriteUint64(lval / exp) + fval := lval % exp + if fval == 0 { + return + } + stream.writeByte('.') + for p := precision - 1; p > 0 && fval < pow10[p]; p-- { + stream.writeByte('0') + } + stream.WriteUint64(fval) + for stream.buf[len(stream.buf)-1] == '0' { + stream.buf = stream.buf[:len(stream.buf)-1] + } +} + +// WriteFloat64 write float64 to stream +func (stream *Stream) WriteFloat64(val float64) { + abs := math.Abs(val) + fmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if abs < 1e-6 || abs >= 1e21 { + fmt = 'e' + } + } + stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 64) +} + +// WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster +func (stream *Stream) WriteFloat64Lossy(val float64) { + if val < 0 { + stream.writeByte('-') + val = -val + } + if val > 0x4ffffff { + stream.WriteFloat64(val) + return + } + precision := 6 + exp := uint64(1000000) // 6 + lval := uint64(val*float64(exp) + 0.5) + stream.WriteUint64(lval / exp) + fval := lval % exp + if fval == 0 { + return + } + stream.writeByte('.') + for p := precision - 1; p > 0 && fval < pow10[p]; p-- { + stream.writeByte('0') + } + stream.WriteUint64(fval) + for stream.buf[len(stream.buf)-1] == '0' { + stream.buf = stream.buf[:len(stream.buf)-1] + } +} diff --git a/vendor/github.com/json-iterator/go/stream_int.go b/vendor/github.com/json-iterator/go/stream_int.go new file mode 100644 index 0000000..d1059ee --- /dev/null +++ b/vendor/github.com/json-iterator/go/stream_int.go @@ -0,0 +1,190 @@ +package jsoniter + +var digits []uint32 + +func init() { + digits = make([]uint32, 1000) + for i := uint32(0); i < 1000; i++ { + digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0' + if i < 10 { + digits[i] += 2 << 24 + } else if i < 100 { + digits[i] += 1 << 24 + } + } +} + +func writeFirstBuf(space []byte, v uint32) []byte { + start := v >> 24 + if start == 0 { + space = append(space, byte(v>>16), byte(v>>8)) + } else if start == 1 { + space = append(space, byte(v>>8)) + } + space = append(space, byte(v)) + return space +} + +func writeBuf(buf []byte, v uint32) []byte { + return append(buf, byte(v>>16), byte(v>>8), byte(v)) +} + +// WriteUint8 write uint8 to stream +func (stream *Stream) WriteUint8(val uint8) { + stream.buf = writeFirstBuf(stream.buf, digits[val]) +} + +// WriteInt8 write int8 to stream +func (stream *Stream) WriteInt8(nval int8) { + var val uint8 + if nval < 0 { + val = uint8(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint8(nval) + } + stream.buf = writeFirstBuf(stream.buf, digits[val]) +} + +// WriteUint16 write uint16 to stream +func (stream *Stream) WriteUint16(val uint16) { + q1 := val / 1000 + if q1 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[val]) + return + } + r1 := val - q1*1000 + stream.buf = writeFirstBuf(stream.buf, digits[q1]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return +} + +// WriteInt16 write int16 to stream +func (stream *Stream) WriteInt16(nval int16) { + var val uint16 + if nval < 0 { + val = uint16(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint16(nval) + } + stream.WriteUint16(val) +} + +// WriteUint32 write uint32 to stream +func (stream *Stream) WriteUint32(val uint32) { + q1 := val / 1000 + if q1 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[val]) + return + } + r1 := val - q1*1000 + q2 := q1 / 1000 + if q2 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q1]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r2 := q1 - q2*1000 + q3 := q2 / 1000 + if q3 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q2]) + } else { + r3 := q2 - q3*1000 + stream.buf = append(stream.buf, byte(q3+'0')) + stream.buf = writeBuf(stream.buf, digits[r3]) + } + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) +} + +// WriteInt32 write int32 to stream +func (stream *Stream) WriteInt32(nval int32) { + var val uint32 + if nval < 0 { + val = uint32(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint32(nval) + } + stream.WriteUint32(val) +} + +// WriteUint64 write uint64 to stream +func (stream *Stream) WriteUint64(val uint64) { + q1 := val / 1000 + if q1 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[val]) + return + } + r1 := val - q1*1000 + q2 := q1 / 1000 + if q2 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q1]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r2 := q1 - q2*1000 + q3 := q2 / 1000 + if q3 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q2]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r3 := q2 - q3*1000 + q4 := q3 / 1000 + if q4 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q3]) + stream.buf = writeBuf(stream.buf, digits[r3]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r4 := q3 - q4*1000 + q5 := q4 / 1000 + if q5 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q4]) + stream.buf = writeBuf(stream.buf, digits[r4]) + stream.buf = writeBuf(stream.buf, digits[r3]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r5 := q4 - q5*1000 + q6 := q5 / 1000 + if q6 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q5]) + } else { + stream.buf = writeFirstBuf(stream.buf, digits[q6]) + r6 := q5 - q6*1000 + stream.buf = writeBuf(stream.buf, digits[r6]) + } + stream.buf = writeBuf(stream.buf, digits[r5]) + stream.buf = writeBuf(stream.buf, digits[r4]) + stream.buf = writeBuf(stream.buf, digits[r3]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) +} + +// WriteInt64 write int64 to stream +func (stream *Stream) WriteInt64(nval int64) { + var val uint64 + if nval < 0 { + val = uint64(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint64(nval) + } + stream.WriteUint64(val) +} + +// WriteInt write int to stream +func (stream *Stream) WriteInt(val int) { + stream.WriteInt64(int64(val)) +} + +// WriteUint write uint to stream +func (stream *Stream) WriteUint(val uint) { + stream.WriteUint64(uint64(val)) +} diff --git a/vendor/github.com/json-iterator/go/stream_str.go b/vendor/github.com/json-iterator/go/stream_str.go new file mode 100644 index 0000000..54c2ba0 --- /dev/null +++ b/vendor/github.com/json-iterator/go/stream_str.go @@ -0,0 +1,372 @@ +package jsoniter + +import ( + "unicode/utf8" +) + +// htmlSafeSet holds the value true if the ASCII character with the given +// array position can be safely represented inside a JSON string, embedded +// inside of HTML