add vendor
This commit is contained in:
10
vendor/google.golang.org/api/AUTHORS
generated
vendored
Normal file
10
vendor/google.golang.org/api/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# This is the official list of authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
|
||||
# Names should be added to this file as
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
# Please keep the list sorted.
|
||||
Google Inc.
|
55
vendor/google.golang.org/api/CONTRIBUTORS
generated
vendored
Normal file
55
vendor/google.golang.org/api/CONTRIBUTORS
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
# This is the official list of people who can contribute
|
||||
# (and typically have contributed) code to the repository.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees are listed here
|
||||
# but not in AUTHORS, because Google holds the copyright.
|
||||
#
|
||||
# The submission process automatically checks to make sure
|
||||
# that people submitting code are listed in this file (by email address).
|
||||
#
|
||||
# Names should be added to this file only after verifying that
|
||||
# the individual or the individual's organization has agreed to
|
||||
# the appropriate Contributor License Agreement, found here:
|
||||
#
|
||||
# https://cla.developers.google.com/about/google-individual
|
||||
# https://cla.developers.google.com/about/google-corporate
|
||||
#
|
||||
# The CLA can be filled out on the web:
|
||||
#
|
||||
# https://cla.developers.google.com/
|
||||
#
|
||||
# When adding J Random Contributor's name to this file,
|
||||
# either J's name or J's organization's name should be
|
||||
# added to the AUTHORS file, depending on whether the
|
||||
# individual or corporate CLA was used.
|
||||
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
#
|
||||
# An entry with two email addresses specifies that the
|
||||
# first address should be used in the submit logs and
|
||||
# that the second address should be recognized as the
|
||||
# same person when interacting with Rietveld.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Alain Vongsouvanhalainv <alainv@google.com>
|
||||
Andrew Gerrand <adg@golang.org>
|
||||
Brad Fitzpatrick <bradfitz@golang.org>
|
||||
Eric Koleda <ekoleda+devrel@googlers.com>
|
||||
Francesc Campoy <campoy@golang.org>
|
||||
Garrick Evans <garrick@google.com>
|
||||
Glenn Lewis <gmlewis@google.com>
|
||||
Ivan Krasin <krasin@golang.org>
|
||||
Jason Hall <jasonhall@google.com>
|
||||
Johan Euphrosine <proppy@google.com>
|
||||
Kostik Shtoyk <kostik@google.com>
|
||||
Kunpei Sakai <namusyaka@gmail.com>
|
||||
Matthew Whisenhunt <matt.whisenhunt@gmail.com>
|
||||
Michael McGreevy <mcgreevy@golang.org>
|
||||
Nick Craig-Wood <nickcw@gmail.com>
|
||||
Robbie Trencheny <me@robbiet.us>
|
||||
Ross Light <light@google.com>
|
||||
Sarah Adams <shadams@google.com>
|
||||
Scott Van Woudenberg <scottvw@google.com>
|
||||
Takashi Matsuo <tmatsuo@google.com>
|
27
vendor/google.golang.org/api/LICENSE
generated
vendored
Normal file
27
vendor/google.golang.org/api/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
79
vendor/google.golang.org/api/gensupport/buffer.go
generated
vendored
Normal file
79
vendor/google.golang.org/api/gensupport/buffer.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gensupport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
// MediaBuffer buffers data from an io.Reader to support uploading media in
|
||||
// retryable chunks. It should be created with NewMediaBuffer.
|
||||
type MediaBuffer struct {
|
||||
media io.Reader
|
||||
|
||||
chunk []byte // The current chunk which is pending upload. The capacity is the chunk size.
|
||||
err error // Any error generated when populating chunk by reading media.
|
||||
|
||||
// The absolute position of chunk in the underlying media.
|
||||
off int64
|
||||
}
|
||||
|
||||
// NewMediaBuffer initializes a MediaBuffer.
|
||||
func NewMediaBuffer(media io.Reader, chunkSize int) *MediaBuffer {
|
||||
return &MediaBuffer{media: media, chunk: make([]byte, 0, chunkSize)}
|
||||
}
|
||||
|
||||
// Chunk returns the current buffered chunk, the offset in the underlying media
|
||||
// from which the chunk is drawn, and the size of the chunk.
|
||||
// Successive calls to Chunk return the same chunk between calls to Next.
|
||||
func (mb *MediaBuffer) Chunk() (chunk io.Reader, off int64, size int, err error) {
|
||||
// There may already be data in chunk if Next has not been called since the previous call to Chunk.
|
||||
if mb.err == nil && len(mb.chunk) == 0 {
|
||||
mb.err = mb.loadChunk()
|
||||
}
|
||||
return bytes.NewReader(mb.chunk), mb.off, len(mb.chunk), mb.err
|
||||
}
|
||||
|
||||
// loadChunk will read from media into chunk, up to the capacity of chunk.
|
||||
func (mb *MediaBuffer) loadChunk() error {
|
||||
bufSize := cap(mb.chunk)
|
||||
mb.chunk = mb.chunk[:bufSize]
|
||||
|
||||
read := 0
|
||||
var err error
|
||||
for err == nil && read < bufSize {
|
||||
var n int
|
||||
n, err = mb.media.Read(mb.chunk[read:])
|
||||
read += n
|
||||
}
|
||||
mb.chunk = mb.chunk[:read]
|
||||
return err
|
||||
}
|
||||
|
||||
// Next advances to the next chunk, which will be returned by the next call to Chunk.
|
||||
// Calls to Next without a corresponding prior call to Chunk will have no effect.
|
||||
func (mb *MediaBuffer) Next() {
|
||||
mb.off += int64(len(mb.chunk))
|
||||
mb.chunk = mb.chunk[0:0]
|
||||
}
|
||||
|
||||
type readerTyper struct {
|
||||
io.Reader
|
||||
googleapi.ContentTyper
|
||||
}
|
||||
|
||||
// ReaderAtToReader adapts a ReaderAt to be used as a Reader.
|
||||
// If ra implements googleapi.ContentTyper, then the returned reader
|
||||
// will also implement googleapi.ContentTyper, delegating to ra.
|
||||
func ReaderAtToReader(ra io.ReaderAt, size int64) io.Reader {
|
||||
r := io.NewSectionReader(ra, 0, size)
|
||||
if typer, ok := ra.(googleapi.ContentTyper); ok {
|
||||
return readerTyper{r, typer}
|
||||
}
|
||||
return r
|
||||
}
|
10
vendor/google.golang.org/api/gensupport/doc.go
generated
vendored
Normal file
10
vendor/google.golang.org/api/gensupport/doc.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package gensupport is an internal implementation detail used by code
|
||||
// generated by the google-api-go-generator tool.
|
||||
//
|
||||
// This package may be modified at any time without regard for backwards
|
||||
// compatibility. It should not be used directly by API users.
|
||||
package gensupport
|
211
vendor/google.golang.org/api/gensupport/json.go
generated
vendored
Normal file
211
vendor/google.golang.org/api/gensupport/json.go
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gensupport
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MarshalJSON returns a JSON encoding of schema containing only selected fields.
|
||||
// A field is selected if any of the following is true:
|
||||
// * it has a non-empty value
|
||||
// * its field name is present in forceSendFields and it is not a nil pointer or nil interface
|
||||
// * its field name is present in nullFields.
|
||||
// The JSON key for each selected field is taken from the field's json: struct tag.
|
||||
func MarshalJSON(schema interface{}, forceSendFields, nullFields []string) ([]byte, error) {
|
||||
if len(forceSendFields) == 0 && len(nullFields) == 0 {
|
||||
return json.Marshal(schema)
|
||||
}
|
||||
|
||||
mustInclude := make(map[string]bool)
|
||||
for _, f := range forceSendFields {
|
||||
mustInclude[f] = true
|
||||
}
|
||||
useNull := make(map[string]bool)
|
||||
useNullMaps := make(map[string]map[string]bool)
|
||||
for _, nf := range nullFields {
|
||||
parts := strings.SplitN(nf, ".", 2)
|
||||
field := parts[0]
|
||||
if len(parts) == 1 {
|
||||
useNull[field] = true
|
||||
} else {
|
||||
if useNullMaps[field] == nil {
|
||||
useNullMaps[field] = map[string]bool{}
|
||||
}
|
||||
useNullMaps[field][parts[1]] = true
|
||||
}
|
||||
}
|
||||
|
||||
dataMap, err := schemaToMap(schema, mustInclude, useNull, useNullMaps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(dataMap)
|
||||
}
|
||||
|
||||
func schemaToMap(schema interface{}, mustInclude, useNull map[string]bool, useNullMaps map[string]map[string]bool) (map[string]interface{}, error) {
|
||||
m := make(map[string]interface{})
|
||||
s := reflect.ValueOf(schema)
|
||||
st := s.Type()
|
||||
|
||||
for i := 0; i < s.NumField(); i++ {
|
||||
jsonTag := st.Field(i).Tag.Get("json")
|
||||
if jsonTag == "" {
|
||||
continue
|
||||
}
|
||||
tag, err := parseJSONTag(jsonTag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tag.ignore {
|
||||
continue
|
||||
}
|
||||
|
||||
v := s.Field(i)
|
||||
f := st.Field(i)
|
||||
|
||||
if useNull[f.Name] {
|
||||
if !isEmptyValue(v) {
|
||||
return nil, fmt.Errorf("field %q in NullFields has non-empty value", f.Name)
|
||||
}
|
||||
m[tag.apiName] = nil
|
||||
continue
|
||||
}
|
||||
|
||||
if !includeField(v, f, mustInclude) {
|
||||
continue
|
||||
}
|
||||
|
||||
// If map fields are explicitly set to null, use a map[string]interface{}.
|
||||
if f.Type.Kind() == reflect.Map && useNullMaps[f.Name] != nil {
|
||||
ms, ok := v.Interface().(map[string]string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("field %q has keys in NullFields but is not a map[string]string", f.Name)
|
||||
}
|
||||
mi := map[string]interface{}{}
|
||||
for k, v := range ms {
|
||||
mi[k] = v
|
||||
}
|
||||
for k := range useNullMaps[f.Name] {
|
||||
mi[k] = nil
|
||||
}
|
||||
m[tag.apiName] = mi
|
||||
continue
|
||||
}
|
||||
|
||||
// nil maps are treated as empty maps.
|
||||
if f.Type.Kind() == reflect.Map && v.IsNil() {
|
||||
m[tag.apiName] = map[string]string{}
|
||||
continue
|
||||
}
|
||||
|
||||
// nil slices are treated as empty slices.
|
||||
if f.Type.Kind() == reflect.Slice && v.IsNil() {
|
||||
m[tag.apiName] = []bool{}
|
||||
continue
|
||||
}
|
||||
|
||||
if tag.stringFormat {
|
||||
m[tag.apiName] = formatAsString(v, f.Type.Kind())
|
||||
} else {
|
||||
m[tag.apiName] = v.Interface()
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// formatAsString returns a string representation of v, dereferencing it first if possible.
|
||||
func formatAsString(v reflect.Value, kind reflect.Kind) string {
|
||||
if kind == reflect.Ptr && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", v.Interface())
|
||||
}
|
||||
|
||||
// jsonTag represents a restricted version of the struct tag format used by encoding/json.
|
||||
// It is used to describe the JSON encoding of fields in a Schema struct.
|
||||
type jsonTag struct {
|
||||
apiName string
|
||||
stringFormat bool
|
||||
ignore bool
|
||||
}
|
||||
|
||||
// parseJSONTag parses a restricted version of the struct tag format used by encoding/json.
|
||||
// The format of the tag must match that generated by the Schema.writeSchemaStruct method
|
||||
// in the api generator.
|
||||
func parseJSONTag(val string) (jsonTag, error) {
|
||||
if val == "-" {
|
||||
return jsonTag{ignore: true}, nil
|
||||
}
|
||||
|
||||
var tag jsonTag
|
||||
|
||||
i := strings.Index(val, ",")
|
||||
if i == -1 || val[:i] == "" {
|
||||
return tag, fmt.Errorf("malformed json tag: %s", val)
|
||||
}
|
||||
|
||||
tag = jsonTag{
|
||||
apiName: val[:i],
|
||||
}
|
||||
|
||||
switch val[i+1:] {
|
||||
case "omitempty":
|
||||
case "omitempty,string":
|
||||
tag.stringFormat = true
|
||||
default:
|
||||
return tag, fmt.Errorf("malformed json tag: %s", val)
|
||||
}
|
||||
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
// Reports whether the struct field "f" with value "v" should be included in JSON output.
|
||||
func includeField(v reflect.Value, f reflect.StructField, mustInclude map[string]bool) bool {
|
||||
// The regular JSON encoding of a nil pointer is "null", which means "delete this field".
|
||||
// Therefore, we could enable field deletion by honoring pointer fields' presence in the mustInclude set.
|
||||
// However, many fields are not pointers, so there would be no way to delete these fields.
|
||||
// Rather than partially supporting field deletion, we ignore mustInclude for nil pointer fields.
|
||||
// Deletion will be handled by a separate mechanism.
|
||||
if f.Type.Kind() == reflect.Ptr && v.IsNil() {
|
||||
return false
|
||||
}
|
||||
|
||||
// The "any" type is represented as an interface{}. If this interface
|
||||
// is nil, there is no reasonable representation to send. We ignore
|
||||
// these fields, for the same reasons as given above for pointers.
|
||||
if f.Type.Kind() == reflect.Interface && v.IsNil() {
|
||||
return false
|
||||
}
|
||||
|
||||
return mustInclude[f.Name] || !isEmptyValue(v)
|
||||
}
|
||||
|
||||
// isEmptyValue reports whether v is the empty value for its type. This
|
||||
// implementation is based on that of the encoding/json package, but its
|
||||
// correctness does not depend on it being identical. What's important is that
|
||||
// this function return false in situations where v should not be sent as part
|
||||
// of a PATCH operation.
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
57
vendor/google.golang.org/api/gensupport/jsonfloat.go
generated
vendored
Normal file
57
vendor/google.golang.org/api/gensupport/jsonfloat.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2016 Google LLC
|
||||
//
|
||||
// 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 gensupport
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// JSONFloat64 is a float64 that supports proper unmarshaling of special float
|
||||
// values in JSON, according to
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3#json. Although
|
||||
// that is a proto-to-JSON spec, it applies to all Google APIs.
|
||||
//
|
||||
// The jsonpb package
|
||||
// (https://github.com/golang/protobuf/blob/master/jsonpb/jsonpb.go) has
|
||||
// similar functionality, but only for direct translation from proto messages
|
||||
// to JSON.
|
||||
type JSONFloat64 float64
|
||||
|
||||
func (f *JSONFloat64) UnmarshalJSON(data []byte) error {
|
||||
var ff float64
|
||||
if err := json.Unmarshal(data, &ff); err == nil {
|
||||
*f = JSONFloat64(ff)
|
||||
return nil
|
||||
}
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err == nil {
|
||||
switch s {
|
||||
case "NaN":
|
||||
ff = math.NaN()
|
||||
case "Infinity":
|
||||
ff = math.Inf(1)
|
||||
case "-Infinity":
|
||||
ff = math.Inf(-1)
|
||||
default:
|
||||
return fmt.Errorf("google.golang.org/api/internal: bad float string %q", s)
|
||||
}
|
||||
*f = JSONFloat64(ff)
|
||||
return nil
|
||||
}
|
||||
return errors.New("google.golang.org/api/internal: data not float or string")
|
||||
}
|
363
vendor/google.golang.org/api/gensupport/media.go
generated
vendored
Normal file
363
vendor/google.golang.org/api/gensupport/media.go
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gensupport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
const sniffBuffSize = 512
|
||||
|
||||
func newContentSniffer(r io.Reader) *contentSniffer {
|
||||
return &contentSniffer{r: r}
|
||||
}
|
||||
|
||||
// contentSniffer wraps a Reader, and reports the content type determined by sniffing up to 512 bytes from the Reader.
|
||||
type contentSniffer struct {
|
||||
r io.Reader
|
||||
start []byte // buffer for the sniffed bytes.
|
||||
err error // set to any error encountered while reading bytes to be sniffed.
|
||||
|
||||
ctype string // set on first sniff.
|
||||
sniffed bool // set to true on first sniff.
|
||||
}
|
||||
|
||||
func (cs *contentSniffer) Read(p []byte) (n int, err error) {
|
||||
// Ensure that the content type is sniffed before any data is consumed from Reader.
|
||||
_, _ = cs.ContentType()
|
||||
|
||||
if len(cs.start) > 0 {
|
||||
n := copy(p, cs.start)
|
||||
cs.start = cs.start[n:]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// We may have read some bytes into start while sniffing, even if the read ended in an error.
|
||||
// We should first return those bytes, then the error.
|
||||
if cs.err != nil {
|
||||
return 0, cs.err
|
||||
}
|
||||
|
||||
// Now we have handled all bytes that were buffered while sniffing. Now just delegate to the underlying reader.
|
||||
return cs.r.Read(p)
|
||||
}
|
||||
|
||||
// ContentType returns the sniffed content type, and whether the content type was succesfully sniffed.
|
||||
func (cs *contentSniffer) ContentType() (string, bool) {
|
||||
if cs.sniffed {
|
||||
return cs.ctype, cs.ctype != ""
|
||||
}
|
||||
cs.sniffed = true
|
||||
// If ReadAll hits EOF, it returns err==nil.
|
||||
cs.start, cs.err = ioutil.ReadAll(io.LimitReader(cs.r, sniffBuffSize))
|
||||
|
||||
// Don't try to detect the content type based on possibly incomplete data.
|
||||
if cs.err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
cs.ctype = http.DetectContentType(cs.start)
|
||||
return cs.ctype, true
|
||||
}
|
||||
|
||||
// DetermineContentType determines the content type of the supplied reader.
|
||||
// If the content type is already known, it can be specified via ctype.
|
||||
// Otherwise, the content of media will be sniffed to determine the content type.
|
||||
// If media implements googleapi.ContentTyper (deprecated), this will be used
|
||||
// instead of sniffing the content.
|
||||
// After calling DetectContentType the caller must not perform further reads on
|
||||
// media, but rather read from the Reader that is returned.
|
||||
func DetermineContentType(media io.Reader, ctype string) (io.Reader, string) {
|
||||
// Note: callers could avoid calling DetectContentType if ctype != "",
|
||||
// but doing the check inside this function reduces the amount of
|
||||
// generated code.
|
||||
if ctype != "" {
|
||||
return media, ctype
|
||||
}
|
||||
|
||||
// For backwards compatability, allow clients to set content
|
||||
// type by providing a ContentTyper for media.
|
||||
if typer, ok := media.(googleapi.ContentTyper); ok {
|
||||
return media, typer.ContentType()
|
||||
}
|
||||
|
||||
sniffer := newContentSniffer(media)
|
||||
if ctype, ok := sniffer.ContentType(); ok {
|
||||
return sniffer, ctype
|
||||
}
|
||||
// If content type could not be sniffed, reads from sniffer will eventually fail with an error.
|
||||
return sniffer, ""
|
||||
}
|
||||
|
||||
type typeReader struct {
|
||||
io.Reader
|
||||
typ string
|
||||
}
|
||||
|
||||
// multipartReader combines the contents of multiple readers to create a multipart/related HTTP body.
|
||||
// Close must be called if reads from the multipartReader are abandoned before reaching EOF.
|
||||
type multipartReader struct {
|
||||
pr *io.PipeReader
|
||||
ctype string
|
||||
mu sync.Mutex
|
||||
pipeOpen bool
|
||||
}
|
||||
|
||||
// boundary optionally specifies the MIME boundary
|
||||
func newMultipartReader(parts []typeReader, boundary string) *multipartReader {
|
||||
mp := &multipartReader{pipeOpen: true}
|
||||
var pw *io.PipeWriter
|
||||
mp.pr, pw = io.Pipe()
|
||||
mpw := multipart.NewWriter(pw)
|
||||
if boundary != "" {
|
||||
mpw.SetBoundary(boundary)
|
||||
}
|
||||
mp.ctype = "multipart/related; boundary=" + mpw.Boundary()
|
||||
go func() {
|
||||
for _, part := range parts {
|
||||
w, err := mpw.CreatePart(typeHeader(part.typ))
|
||||
if err != nil {
|
||||
mpw.Close()
|
||||
pw.CloseWithError(fmt.Errorf("googleapi: CreatePart failed: %v", err))
|
||||
return
|
||||
}
|
||||
_, err = io.Copy(w, part.Reader)
|
||||
if err != nil {
|
||||
mpw.Close()
|
||||
pw.CloseWithError(fmt.Errorf("googleapi: Copy failed: %v", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
mpw.Close()
|
||||
pw.Close()
|
||||
}()
|
||||
return mp
|
||||
}
|
||||
|
||||
func (mp *multipartReader) Read(data []byte) (n int, err error) {
|
||||
return mp.pr.Read(data)
|
||||
}
|
||||
|
||||
func (mp *multipartReader) Close() error {
|
||||
mp.mu.Lock()
|
||||
if !mp.pipeOpen {
|
||||
mp.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
mp.pipeOpen = false
|
||||
mp.mu.Unlock()
|
||||
return mp.pr.Close()
|
||||
}
|
||||
|
||||
// CombineBodyMedia combines a json body with media content to create a multipart/related HTTP body.
|
||||
// It returns a ReadCloser containing the combined body, and the overall "multipart/related" content type, with random boundary.
|
||||
//
|
||||
// The caller must call Close on the returned ReadCloser if reads are abandoned before reaching EOF.
|
||||
func CombineBodyMedia(body io.Reader, bodyContentType string, media io.Reader, mediaContentType string) (io.ReadCloser, string) {
|
||||
return combineBodyMedia(body, bodyContentType, media, mediaContentType, "")
|
||||
}
|
||||
|
||||
// combineBodyMedia is CombineBodyMedia but with an optional mimeBoundary field.
|
||||
func combineBodyMedia(body io.Reader, bodyContentType string, media io.Reader, mediaContentType, mimeBoundary string) (io.ReadCloser, string) {
|
||||
mp := newMultipartReader([]typeReader{
|
||||
{body, bodyContentType},
|
||||
{media, mediaContentType},
|
||||
}, mimeBoundary)
|
||||
return mp, mp.ctype
|
||||
}
|
||||
|
||||
func typeHeader(contentType string) textproto.MIMEHeader {
|
||||
h := make(textproto.MIMEHeader)
|
||||
if contentType != "" {
|
||||
h.Set("Content-Type", contentType)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// PrepareUpload determines whether the data in the supplied reader should be
|
||||
// uploaded in a single request, or in sequential chunks.
|
||||
// chunkSize is the size of the chunk that media should be split into.
|
||||
//
|
||||
// If chunkSize is zero, media is returned as the first value, and the other
|
||||
// two return values are nil, true.
|
||||
//
|
||||
// Otherwise, a MediaBuffer is returned, along with a bool indicating whether the
|
||||
// contents of media fit in a single chunk.
|
||||
//
|
||||
// After PrepareUpload has been called, media should no longer be used: the
|
||||
// media content should be accessed via one of the return values.
|
||||
func PrepareUpload(media io.Reader, chunkSize int) (r io.Reader, mb *MediaBuffer, singleChunk bool) {
|
||||
if chunkSize == 0 { // do not chunk
|
||||
return media, nil, true
|
||||
}
|
||||
mb = NewMediaBuffer(media, chunkSize)
|
||||
_, _, _, err := mb.Chunk()
|
||||
// If err is io.EOF, we can upload this in a single request. Otherwise, err is
|
||||
// either nil or a non-EOF error. If it is the latter, then the next call to
|
||||
// mb.Chunk will return the same error. Returning a MediaBuffer ensures that this
|
||||
// error will be handled at some point.
|
||||
return nil, mb, err == io.EOF
|
||||
}
|
||||
|
||||
// MediaInfo holds information for media uploads. It is intended for use by generated
|
||||
// code only.
|
||||
type MediaInfo struct {
|
||||
// At most one of Media and MediaBuffer will be set.
|
||||
media io.Reader
|
||||
buffer *MediaBuffer
|
||||
singleChunk bool
|
||||
mType string
|
||||
size int64 // mediaSize, if known. Used only for calls to progressUpdater_.
|
||||
progressUpdater googleapi.ProgressUpdater
|
||||
}
|
||||
|
||||
// NewInfoFromMedia should be invoked from the Media method of a call. It returns a
|
||||
// MediaInfo populated with chunk size and content type, and a reader or MediaBuffer
|
||||
// if needed.
|
||||
func NewInfoFromMedia(r io.Reader, options []googleapi.MediaOption) *MediaInfo {
|
||||
mi := &MediaInfo{}
|
||||
opts := googleapi.ProcessMediaOptions(options)
|
||||
if !opts.ForceEmptyContentType {
|
||||
r, mi.mType = DetermineContentType(r, opts.ContentType)
|
||||
}
|
||||
mi.media, mi.buffer, mi.singleChunk = PrepareUpload(r, opts.ChunkSize)
|
||||
return mi
|
||||
}
|
||||
|
||||
// NewInfoFromResumableMedia should be invoked from the ResumableMedia method of a
|
||||
// call. It returns a MediaInfo using the given reader, size and media type.
|
||||
func NewInfoFromResumableMedia(r io.ReaderAt, size int64, mediaType string) *MediaInfo {
|
||||
rdr := ReaderAtToReader(r, size)
|
||||
rdr, mType := DetermineContentType(rdr, mediaType)
|
||||
return &MediaInfo{
|
||||
size: size,
|
||||
mType: mType,
|
||||
buffer: NewMediaBuffer(rdr, googleapi.DefaultUploadChunkSize),
|
||||
media: nil,
|
||||
singleChunk: false,
|
||||
}
|
||||
}
|
||||
|
||||
// SetProgressUpdater sets the progress updater for the media info.
|
||||
func (mi *MediaInfo) SetProgressUpdater(pu googleapi.ProgressUpdater) {
|
||||
if mi != nil {
|
||||
mi.progressUpdater = pu
|
||||
}
|
||||
}
|
||||
|
||||
// UploadType determines the type of upload: a single request, or a resumable
|
||||
// series of requests.
|
||||
func (mi *MediaInfo) UploadType() string {
|
||||
if mi.singleChunk {
|
||||
return "multipart"
|
||||
}
|
||||
return "resumable"
|
||||
}
|
||||
|
||||
// UploadRequest sets up an HTTP request for media upload. It adds headers
|
||||
// as necessary, and returns a replacement for the body and a function for http.Request.GetBody.
|
||||
func (mi *MediaInfo) UploadRequest(reqHeaders http.Header, body io.Reader) (newBody io.Reader, getBody func() (io.ReadCloser, error), cleanup func()) {
|
||||
cleanup = func() {}
|
||||
if mi == nil {
|
||||
return body, nil, cleanup
|
||||
}
|
||||
var media io.Reader
|
||||
if mi.media != nil {
|
||||
// This only happens when the caller has turned off chunking. In that
|
||||
// case, we write all of media in a single non-retryable request.
|
||||
media = mi.media
|
||||
} else if mi.singleChunk {
|
||||
// The data fits in a single chunk, which has now been read into the MediaBuffer.
|
||||
// We obtain that chunk so we can write it in a single request. The request can
|
||||
// be retried because the data is stored in the MediaBuffer.
|
||||
media, _, _, _ = mi.buffer.Chunk()
|
||||
}
|
||||
if media != nil {
|
||||
fb := readerFunc(body)
|
||||
fm := readerFunc(media)
|
||||
combined, ctype := CombineBodyMedia(body, "application/json", media, mi.mType)
|
||||
if fb != nil && fm != nil {
|
||||
getBody = func() (io.ReadCloser, error) {
|
||||
rb := ioutil.NopCloser(fb())
|
||||
rm := ioutil.NopCloser(fm())
|
||||
var mimeBoundary string
|
||||
if _, params, err := mime.ParseMediaType(ctype); err == nil {
|
||||
mimeBoundary = params["boundary"]
|
||||
}
|
||||
r, _ := combineBodyMedia(rb, "application/json", rm, mi.mType, mimeBoundary)
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
cleanup = func() { combined.Close() }
|
||||
reqHeaders.Set("Content-Type", ctype)
|
||||
body = combined
|
||||
}
|
||||
if mi.buffer != nil && mi.mType != "" && !mi.singleChunk {
|
||||
reqHeaders.Set("X-Upload-Content-Type", mi.mType)
|
||||
}
|
||||
return body, getBody, cleanup
|
||||
}
|
||||
|
||||
// readerFunc returns a function that always returns an io.Reader that has the same
|
||||
// contents as r, provided that can be done without consuming r. Otherwise, it
|
||||
// returns nil.
|
||||
// See http.NewRequest (in net/http/request.go).
|
||||
func readerFunc(r io.Reader) func() io.Reader {
|
||||
switch r := r.(type) {
|
||||
case *bytes.Buffer:
|
||||
buf := r.Bytes()
|
||||
return func() io.Reader { return bytes.NewReader(buf) }
|
||||
case *bytes.Reader:
|
||||
snapshot := *r
|
||||
return func() io.Reader { r := snapshot; return &r }
|
||||
case *strings.Reader:
|
||||
snapshot := *r
|
||||
return func() io.Reader { r := snapshot; return &r }
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ResumableUpload returns an appropriately configured ResumableUpload value if the
|
||||
// upload is resumable, or nil otherwise.
|
||||
func (mi *MediaInfo) ResumableUpload(locURI string) *ResumableUpload {
|
||||
if mi == nil || mi.singleChunk {
|
||||
return nil
|
||||
}
|
||||
return &ResumableUpload{
|
||||
URI: locURI,
|
||||
Media: mi.buffer,
|
||||
MediaType: mi.mType,
|
||||
Callback: func(curr int64) {
|
||||
if mi.progressUpdater != nil {
|
||||
mi.progressUpdater(curr, mi.size)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SetGetBody sets the GetBody field of req to f. This was once needed
|
||||
// to gracefully support Go 1.7 and earlier which didn't have that
|
||||
// field.
|
||||
//
|
||||
// Deprecated: the code generator no longer uses this as of
|
||||
// 2019-02-19. Nothing else should be calling this anyway, but we
|
||||
// won't delete this immediately; it will be deleted in as early as 6
|
||||
// months.
|
||||
func SetGetBody(req *http.Request, f func() (io.ReadCloser, error)) {
|
||||
req.GetBody = f
|
||||
}
|
51
vendor/google.golang.org/api/gensupport/params.go
generated
vendored
Normal file
51
vendor/google.golang.org/api/gensupport/params.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gensupport
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
// URLParams is a simplified replacement for url.Values
|
||||
// that safely builds up URL parameters for encoding.
|
||||
type URLParams map[string][]string
|
||||
|
||||
// Get returns the first value for the given key, or "".
|
||||
func (u URLParams) Get(key string) string {
|
||||
vs := u[key]
|
||||
if len(vs) == 0 {
|
||||
return ""
|
||||
}
|
||||
return vs[0]
|
||||
}
|
||||
|
||||
// Set sets the key to value.
|
||||
// It replaces any existing values.
|
||||
func (u URLParams) Set(key, value string) {
|
||||
u[key] = []string{value}
|
||||
}
|
||||
|
||||
// SetMulti sets the key to an array of values.
|
||||
// It replaces any existing values.
|
||||
// Note that values must not be modified after calling SetMulti
|
||||
// so the caller is responsible for making a copy if necessary.
|
||||
func (u URLParams) SetMulti(key string, values []string) {
|
||||
u[key] = values
|
||||
}
|
||||
|
||||
// Encode encodes the values into ``URL encoded'' form
|
||||
// ("bar=baz&foo=quux") sorted by key.
|
||||
func (u URLParams) Encode() string {
|
||||
return url.Values(u).Encode()
|
||||
}
|
||||
|
||||
// SetOptions sets the URL params and any additional call options.
|
||||
func SetOptions(u URLParams, opts ...googleapi.CallOption) {
|
||||
for _, o := range opts {
|
||||
u.Set(o.Get())
|
||||
}
|
||||
}
|
241
vendor/google.golang.org/api/gensupport/resumable.go
generated
vendored
Normal file
241
vendor/google.golang.org/api/gensupport/resumable.go
generated
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gensupport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
gax "github.com/googleapis/gax-go/v2"
|
||||
)
|
||||
|
||||
// Backoff is an interface around gax.Backoff's Pause method, allowing tests to provide their
|
||||
// own implementation.
|
||||
type Backoff interface {
|
||||
Pause() time.Duration
|
||||
}
|
||||
|
||||
// These are declared as global variables so that tests can overwrite them.
|
||||
var (
|
||||
retryDeadline = 32 * time.Second
|
||||
backoff = func() Backoff {
|
||||
return &gax.Backoff{Initial: 100 * time.Millisecond}
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// statusTooManyRequests is returned by the storage API if the
|
||||
// per-project limits have been temporarily exceeded. The request
|
||||
// should be retried.
|
||||
// https://cloud.google.com/storage/docs/json_api/v1/status-codes#standardcodes
|
||||
statusTooManyRequests = 429
|
||||
)
|
||||
|
||||
// ResumableUpload is used by the generated APIs to provide resumable uploads.
|
||||
// It is not used by developers directly.
|
||||
type ResumableUpload struct {
|
||||
Client *http.Client
|
||||
// URI is the resumable resource destination provided by the server after specifying "&uploadType=resumable".
|
||||
URI string
|
||||
UserAgent string // User-Agent for header of the request
|
||||
// Media is the object being uploaded.
|
||||
Media *MediaBuffer
|
||||
// MediaType defines the media type, e.g. "image/jpeg".
|
||||
MediaType string
|
||||
|
||||
mu sync.Mutex // guards progress
|
||||
progress int64 // number of bytes uploaded so far
|
||||
|
||||
// Callback is an optional function that will be periodically called with the cumulative number of bytes uploaded.
|
||||
Callback func(int64)
|
||||
}
|
||||
|
||||
// Progress returns the number of bytes uploaded at this point.
|
||||
func (rx *ResumableUpload) Progress() int64 {
|
||||
rx.mu.Lock()
|
||||
defer rx.mu.Unlock()
|
||||
return rx.progress
|
||||
}
|
||||
|
||||
// doUploadRequest performs a single HTTP request to upload data.
|
||||
// off specifies the offset in rx.Media from which data is drawn.
|
||||
// size is the number of bytes in data.
|
||||
// final specifies whether data is the final chunk to be uploaded.
|
||||
func (rx *ResumableUpload) doUploadRequest(ctx context.Context, data io.Reader, off, size int64, final bool) (*http.Response, error) {
|
||||
req, err := http.NewRequest("POST", rx.URI, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.ContentLength = size
|
||||
var contentRange string
|
||||
if final {
|
||||
if size == 0 {
|
||||
contentRange = fmt.Sprintf("bytes */%v", off)
|
||||
} else {
|
||||
contentRange = fmt.Sprintf("bytes %v-%v/%v", off, off+size-1, off+size)
|
||||
}
|
||||
} else {
|
||||
contentRange = fmt.Sprintf("bytes %v-%v/*", off, off+size-1)
|
||||
}
|
||||
req.Header.Set("Content-Range", contentRange)
|
||||
req.Header.Set("Content-Type", rx.MediaType)
|
||||
req.Header.Set("User-Agent", rx.UserAgent)
|
||||
|
||||
// Google's upload endpoint uses status code 308 for a
|
||||
// different purpose than the "308 Permanent Redirect"
|
||||
// since-standardized in RFC 7238. Because of the conflict in
|
||||
// semantics, Google added this new request header which
|
||||
// causes it to not use "308" and instead reply with 200 OK
|
||||
// and sets the upload-specific "X-HTTP-Status-Code-Override:
|
||||
// 308" response header.
|
||||
req.Header.Set("X-GUploader-No-308", "yes")
|
||||
|
||||
return SendRequest(ctx, rx.Client, req)
|
||||
}
|
||||
|
||||
func statusResumeIncomplete(resp *http.Response) bool {
|
||||
// This is how the server signals "status resume incomplete"
|
||||
// when X-GUploader-No-308 is set to "yes":
|
||||
return resp != nil && resp.Header.Get("X-Http-Status-Code-Override") == "308"
|
||||
}
|
||||
|
||||
// reportProgress calls a user-supplied callback to report upload progress.
|
||||
// If old==updated, the callback is not called.
|
||||
func (rx *ResumableUpload) reportProgress(old, updated int64) {
|
||||
if updated-old == 0 {
|
||||
return
|
||||
}
|
||||
rx.mu.Lock()
|
||||
rx.progress = updated
|
||||
rx.mu.Unlock()
|
||||
if rx.Callback != nil {
|
||||
rx.Callback(updated)
|
||||
}
|
||||
}
|
||||
|
||||
// transferChunk performs a single HTTP request to upload a single chunk from rx.Media.
|
||||
func (rx *ResumableUpload) transferChunk(ctx context.Context) (*http.Response, error) {
|
||||
chunk, off, size, err := rx.Media.Chunk()
|
||||
|
||||
done := err == io.EOF
|
||||
if !done && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := rx.doUploadRequest(ctx, chunk, off, int64(size), done)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// We sent "X-GUploader-No-308: yes" (see comment elsewhere in
|
||||
// this file), so we don't expect to get a 308.
|
||||
if res.StatusCode == 308 {
|
||||
return nil, errors.New("unexpected 308 response status code")
|
||||
}
|
||||
|
||||
if res.StatusCode == http.StatusOK {
|
||||
rx.reportProgress(off, off+int64(size))
|
||||
}
|
||||
|
||||
if statusResumeIncomplete(res) {
|
||||
rx.Media.Next()
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Upload starts the process of a resumable upload with a cancellable context.
|
||||
// It retries using the provided back off strategy until cancelled or the
|
||||
// strategy indicates to stop retrying.
|
||||
// It is called from the auto-generated API code and is not visible to the user.
|
||||
// Before sending an HTTP request, Upload calls any registered hook functions,
|
||||
// and calls the returned functions after the request returns (see send.go).
|
||||
// rx is private to the auto-generated API code.
|
||||
// Exactly one of resp or err will be nil. If resp is non-nil, the caller must call resp.Body.Close.
|
||||
func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err error) {
|
||||
var shouldRetry = func(status int, err error) bool {
|
||||
if 500 <= status && status <= 599 {
|
||||
return true
|
||||
}
|
||||
if status == statusTooManyRequests {
|
||||
return true
|
||||
}
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return true
|
||||
}
|
||||
if err, ok := err.(interface{ Temporary() bool }); ok {
|
||||
return err.Temporary()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// There are a couple of cases where it's possible for err and resp to both
|
||||
// be non-nil. However, we expose a simpler contract to our callers: exactly
|
||||
// one of resp and err will be non-nil. This means that any response body
|
||||
// must be closed here before returning a non-nil error.
|
||||
var prepareReturn = func(resp *http.Response, err error) (*http.Response, error) {
|
||||
if err != nil {
|
||||
if resp != nil && resp.Body != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Send all chunks.
|
||||
for {
|
||||
var pause time.Duration
|
||||
|
||||
// Each chunk gets its own initialized-at-zero retry.
|
||||
bo := backoff()
|
||||
quitAfter := time.After(retryDeadline)
|
||||
|
||||
// Retry loop for a single chunk.
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if err == nil {
|
||||
err = ctx.Err()
|
||||
}
|
||||
return prepareReturn(resp, err)
|
||||
case <-time.After(pause):
|
||||
case <-quitAfter:
|
||||
return prepareReturn(resp, err)
|
||||
}
|
||||
|
||||
resp, err = rx.transferChunk(ctx)
|
||||
|
||||
var status int
|
||||
if resp != nil {
|
||||
status = resp.StatusCode
|
||||
}
|
||||
|
||||
// Check if we should retry the request.
|
||||
if !shouldRetry(status, err) {
|
||||
break
|
||||
}
|
||||
|
||||
pause = bo.Pause()
|
||||
if resp != nil && resp.Body != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// If the chunk was uploaded successfully, but there's still
|
||||
// more to go, upload the next chunk without any delay.
|
||||
if statusResumeIncomplete(resp) {
|
||||
resp.Body.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
return prepareReturn(resp, err)
|
||||
}
|
||||
}
|
87
vendor/google.golang.org/api/gensupport/send.go
generated
vendored
Normal file
87
vendor/google.golang.org/api/gensupport/send.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gensupport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Hook is the type of a function that is called once before each HTTP request
|
||||
// that is sent by a generated API. It returns a function that is called after
|
||||
// the request returns.
|
||||
// Hooks are not called if the context is nil.
|
||||
type Hook func(ctx context.Context, req *http.Request) func(resp *http.Response)
|
||||
|
||||
var hooks []Hook
|
||||
|
||||
// RegisterHook registers a Hook to be called before each HTTP request by a
|
||||
// generated API. Hooks are called in the order they are registered. Each
|
||||
// hook can return a function; if it is non-nil, it is called after the HTTP
|
||||
// request returns. These functions are called in the reverse order.
|
||||
// RegisterHook should not be called concurrently with itself or SendRequest.
|
||||
func RegisterHook(h Hook) {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
|
||||
// SendRequest sends a single HTTP request using the given client.
|
||||
// If ctx is non-nil, it calls all hooks, then sends the request with
|
||||
// req.WithContext, then calls any functions returned by the hooks in
|
||||
// reverse order.
|
||||
func SendRequest(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
||||
// Disallow Accept-Encoding because it interferes with the automatic gzip handling
|
||||
// done by the default http.Transport. See https://github.com/google/google-api-go-client/issues/219.
|
||||
if _, ok := req.Header["Accept-Encoding"]; ok {
|
||||
return nil, errors.New("google api: custom Accept-Encoding headers not allowed")
|
||||
}
|
||||
if ctx == nil {
|
||||
return client.Do(req)
|
||||
}
|
||||
// Call hooks in order of registration, store returned funcs.
|
||||
post := make([]func(resp *http.Response), len(hooks))
|
||||
for i, h := range hooks {
|
||||
fn := h(ctx, req)
|
||||
post[i] = fn
|
||||
}
|
||||
|
||||
// Send request.
|
||||
resp, err := send(ctx, client, req)
|
||||
|
||||
// Call returned funcs in reverse order.
|
||||
for i := len(post) - 1; i >= 0; i-- {
|
||||
if fn := post[i]; fn != nil {
|
||||
fn(resp)
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func send(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
||||
if client == nil {
|
||||
client = http.DefaultClient
|
||||
}
|
||||
resp, err := client.Do(req.WithContext(ctx))
|
||||
// If we got an error, and the context has been canceled,
|
||||
// the context's error is probably more useful.
|
||||
if err != nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
default:
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// DecodeResponse decodes the body of res into target. If there is no body,
|
||||
// target is unchanged.
|
||||
func DecodeResponse(target interface{}, res *http.Response) error {
|
||||
if res.StatusCode == http.StatusNoContent {
|
||||
return nil
|
||||
}
|
||||
return json.NewDecoder(res.Body).Decode(target)
|
||||
}
|
403
vendor/google.golang.org/api/googleapi/googleapi.go
generated
vendored
Normal file
403
vendor/google.golang.org/api/googleapi/googleapi.go
generated
vendored
Normal file
@ -0,0 +1,403 @@
|
||||
// Copyright 2011 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package googleapi contains the common code shared by all Google API
|
||||
// libraries.
|
||||
package googleapi // import "google.golang.org/api/googleapi"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/api/googleapi/internal/uritemplates"
|
||||
)
|
||||
|
||||
// ContentTyper is an interface for Readers which know (or would like
|
||||
// to override) their Content-Type. If a media body doesn't implement
|
||||
// ContentTyper, the type is sniffed from the content using
|
||||
// http.DetectContentType.
|
||||
type ContentTyper interface {
|
||||
ContentType() string
|
||||
}
|
||||
|
||||
// A SizeReaderAt is a ReaderAt with a Size method.
|
||||
// An io.SectionReader implements SizeReaderAt.
|
||||
type SizeReaderAt interface {
|
||||
io.ReaderAt
|
||||
Size() int64
|
||||
}
|
||||
|
||||
// ServerResponse is embedded in each Do response and
|
||||
// provides the HTTP status code and header sent by the server.
|
||||
type ServerResponse struct {
|
||||
// HTTPStatusCode is the server's response status code. When using a
|
||||
// resource method's Do call, this will always be in the 2xx range.
|
||||
HTTPStatusCode int
|
||||
// Header contains the response header fields from the server.
|
||||
Header http.Header
|
||||
}
|
||||
|
||||
const (
|
||||
// Version defines the gax version being used. This is typically sent
|
||||
// in an HTTP header to services.
|
||||
Version = "0.5"
|
||||
|
||||
// UserAgent is the header string used to identify this package.
|
||||
UserAgent = "google-api-go-client/" + Version
|
||||
|
||||
// DefaultUploadChunkSize is the default chunk size to use for resumable
|
||||
// uploads if not specified by the user.
|
||||
DefaultUploadChunkSize = 8 * 1024 * 1024
|
||||
|
||||
// MinUploadChunkSize is the minimum chunk size that can be used for
|
||||
// resumable uploads. All user-specified chunk sizes must be multiple of
|
||||
// this value.
|
||||
MinUploadChunkSize = 256 * 1024
|
||||
)
|
||||
|
||||
// Error contains an error response from the server.
|
||||
type Error struct {
|
||||
// Code is the HTTP response status code and will always be populated.
|
||||
Code int `json:"code"`
|
||||
// Message is the server response message and is only populated when
|
||||
// explicitly referenced by the JSON server response.
|
||||
Message string `json:"message"`
|
||||
// Body is the raw response returned by the server.
|
||||
// It is often but not always JSON, depending on how the request fails.
|
||||
Body string
|
||||
// Header contains the response header fields from the server.
|
||||
Header http.Header
|
||||
|
||||
Errors []ErrorItem
|
||||
}
|
||||
|
||||
// ErrorItem is a detailed error code & message from the Google API frontend.
|
||||
type ErrorItem struct {
|
||||
// Reason is the typed error code. For example: "some_example".
|
||||
Reason string `json:"reason"`
|
||||
// Message is the human-readable description of the error.
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
if len(e.Errors) == 0 && e.Message == "" {
|
||||
return fmt.Sprintf("googleapi: got HTTP response code %d with body: %v", e.Code, e.Body)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "googleapi: Error %d: ", e.Code)
|
||||
if e.Message != "" {
|
||||
fmt.Fprintf(&buf, "%s", e.Message)
|
||||
}
|
||||
if len(e.Errors) == 0 {
|
||||
return strings.TrimSpace(buf.String())
|
||||
}
|
||||
if len(e.Errors) == 1 && e.Errors[0].Message == e.Message {
|
||||
fmt.Fprintf(&buf, ", %s", e.Errors[0].Reason)
|
||||
return buf.String()
|
||||
}
|
||||
fmt.Fprintln(&buf, "\nMore details:")
|
||||
for _, v := range e.Errors {
|
||||
fmt.Fprintf(&buf, "Reason: %s, Message: %s\n", v.Reason, v.Message)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type errorReply struct {
|
||||
Error *Error `json:"error"`
|
||||
}
|
||||
|
||||
// CheckResponse returns an error (of type *Error) if the response
|
||||
// status code is not 2xx.
|
||||
func CheckResponse(res *http.Response) error {
|
||||
if res.StatusCode >= 200 && res.StatusCode <= 299 {
|
||||
return nil
|
||||
}
|
||||
slurp, err := ioutil.ReadAll(res.Body)
|
||||
if err == nil {
|
||||
jerr := new(errorReply)
|
||||
err = json.Unmarshal(slurp, jerr)
|
||||
if err == nil && jerr.Error != nil {
|
||||
if jerr.Error.Code == 0 {
|
||||
jerr.Error.Code = res.StatusCode
|
||||
}
|
||||
jerr.Error.Body = string(slurp)
|
||||
return jerr.Error
|
||||
}
|
||||
}
|
||||
return &Error{
|
||||
Code: res.StatusCode,
|
||||
Body: string(slurp),
|
||||
Header: res.Header,
|
||||
}
|
||||
}
|
||||
|
||||
// IsNotModified reports whether err is the result of the
|
||||
// server replying with http.StatusNotModified.
|
||||
// Such error values are sometimes returned by "Do" methods
|
||||
// on calls when If-None-Match is used.
|
||||
func IsNotModified(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
ae, ok := err.(*Error)
|
||||
return ok && ae.Code == http.StatusNotModified
|
||||
}
|
||||
|
||||
// CheckMediaResponse returns an error (of type *Error) if the response
|
||||
// status code is not 2xx. Unlike CheckResponse it does not assume the
|
||||
// body is a JSON error document.
|
||||
// It is the caller's responsibility to close res.Body.
|
||||
func CheckMediaResponse(res *http.Response) error {
|
||||
if res.StatusCode >= 200 && res.StatusCode <= 299 {
|
||||
return nil
|
||||
}
|
||||
slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20))
|
||||
return &Error{
|
||||
Code: res.StatusCode,
|
||||
Body: string(slurp),
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalStyle defines whether to marshal JSON with a {"data": ...} wrapper.
|
||||
type MarshalStyle bool
|
||||
|
||||
// WithDataWrapper marshals JSON with a {"data": ...} wrapper.
|
||||
var WithDataWrapper = MarshalStyle(true)
|
||||
|
||||
// WithoutDataWrapper marshals JSON without a {"data": ...} wrapper.
|
||||
var WithoutDataWrapper = MarshalStyle(false)
|
||||
|
||||
func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if wrap {
|
||||
buf.Write([]byte(`{"data": `))
|
||||
}
|
||||
err := json.NewEncoder(buf).Encode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if wrap {
|
||||
buf.Write([]byte(`}`))
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// ProgressUpdater is a function that is called upon every progress update of a resumable upload.
|
||||
// This is the only part of a resumable upload (from googleapi) that is usable by the developer.
|
||||
// The remaining usable pieces of resumable uploads is exposed in each auto-generated API.
|
||||
type ProgressUpdater func(current, total int64)
|
||||
|
||||
// MediaOption defines the interface for setting media options.
|
||||
type MediaOption interface {
|
||||
setOptions(o *MediaOptions)
|
||||
}
|
||||
|
||||
type contentTypeOption string
|
||||
|
||||
func (ct contentTypeOption) setOptions(o *MediaOptions) {
|
||||
o.ContentType = string(ct)
|
||||
if o.ContentType == "" {
|
||||
o.ForceEmptyContentType = true
|
||||
}
|
||||
}
|
||||
|
||||
// ContentType returns a MediaOption which sets the Content-Type header for media uploads.
|
||||
// If ctype is empty, the Content-Type header will be omitted.
|
||||
func ContentType(ctype string) MediaOption {
|
||||
return contentTypeOption(ctype)
|
||||
}
|
||||
|
||||
type chunkSizeOption int
|
||||
|
||||
func (cs chunkSizeOption) setOptions(o *MediaOptions) {
|
||||
size := int(cs)
|
||||
if size%MinUploadChunkSize != 0 {
|
||||
size += MinUploadChunkSize - (size % MinUploadChunkSize)
|
||||
}
|
||||
o.ChunkSize = size
|
||||
}
|
||||
|
||||
// ChunkSize returns a MediaOption which sets the chunk size for media uploads.
|
||||
// size will be rounded up to the nearest multiple of 256K.
|
||||
// Media which contains fewer than size bytes will be uploaded in a single request.
|
||||
// Media which contains size bytes or more will be uploaded in separate chunks.
|
||||
// If size is zero, media will be uploaded in a single request.
|
||||
func ChunkSize(size int) MediaOption {
|
||||
return chunkSizeOption(size)
|
||||
}
|
||||
|
||||
// MediaOptions stores options for customizing media upload. It is not used by developers directly.
|
||||
type MediaOptions struct {
|
||||
ContentType string
|
||||
ForceEmptyContentType bool
|
||||
|
||||
ChunkSize int
|
||||
}
|
||||
|
||||
// ProcessMediaOptions stores options from opts in a MediaOptions.
|
||||
// It is not used by developers directly.
|
||||
func ProcessMediaOptions(opts []MediaOption) *MediaOptions {
|
||||
mo := &MediaOptions{ChunkSize: DefaultUploadChunkSize}
|
||||
for _, o := range opts {
|
||||
o.setOptions(mo)
|
||||
}
|
||||
return mo
|
||||
}
|
||||
|
||||
// ResolveRelative resolves relatives such as "http://www.golang.org/" and
|
||||
// "topics/myproject/mytopic" into a single string, such as
|
||||
// "http://www.golang.org/topics/myproject/mytopic". It strips all parent
|
||||
// references (e.g. ../..) as well as anything after the host
|
||||
// (e.g. /bar/gaz gets stripped out of foo.com/bar/gaz).
|
||||
func ResolveRelative(basestr, relstr string) string {
|
||||
u, _ := url.Parse(basestr)
|
||||
afterColonPath := ""
|
||||
if i := strings.IndexRune(relstr, ':'); i > 0 {
|
||||
afterColonPath = relstr[i+1:]
|
||||
relstr = relstr[:i]
|
||||
}
|
||||
rel, _ := url.Parse(relstr)
|
||||
u = u.ResolveReference(rel)
|
||||
us := u.String()
|
||||
if afterColonPath != "" {
|
||||
us = fmt.Sprintf("%s:%s", us, afterColonPath)
|
||||
}
|
||||
us = strings.Replace(us, "%7B", "{", -1)
|
||||
us = strings.Replace(us, "%7D", "}", -1)
|
||||
us = strings.Replace(us, "%2A", "*", -1)
|
||||
return us
|
||||
}
|
||||
|
||||
// Expand subsitutes any {encoded} strings in the URL passed in using
|
||||
// the map supplied.
|
||||
//
|
||||
// This calls SetOpaque to avoid encoding of the parameters in the URL path.
|
||||
func Expand(u *url.URL, expansions map[string]string) {
|
||||
escaped, unescaped, err := uritemplates.Expand(u.Path, expansions)
|
||||
if err == nil {
|
||||
u.Path = unescaped
|
||||
u.RawPath = escaped
|
||||
}
|
||||
}
|
||||
|
||||
// CloseBody is used to close res.Body.
|
||||
// Prior to calling Close, it also tries to Read a small amount to see an EOF.
|
||||
// Not seeing an EOF can prevent HTTP Transports from reusing connections.
|
||||
func CloseBody(res *http.Response) {
|
||||
if res == nil || res.Body == nil {
|
||||
return
|
||||
}
|
||||
// Justification for 3 byte reads: two for up to "\r\n" after
|
||||
// a JSON/XML document, and then 1 to see EOF if we haven't yet.
|
||||
// TODO(bradfitz): detect Go 1.3+ and skip these reads.
|
||||
// See https://codereview.appspot.com/58240043
|
||||
// and https://codereview.appspot.com/49570044
|
||||
buf := make([]byte, 1)
|
||||
for i := 0; i < 3; i++ {
|
||||
_, err := res.Body.Read(buf)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
res.Body.Close()
|
||||
|
||||
}
|
||||
|
||||
// VariantType returns the type name of the given variant.
|
||||
// If the map doesn't contain the named key or the value is not a []interface{}, "" is returned.
|
||||
// This is used to support "variant" APIs that can return one of a number of different types.
|
||||
func VariantType(t map[string]interface{}) string {
|
||||
s, _ := t["type"].(string)
|
||||
return s
|
||||
}
|
||||
|
||||
// ConvertVariant uses the JSON encoder/decoder to fill in the struct 'dst' with the fields found in variant 'v'.
|
||||
// This is used to support "variant" APIs that can return one of a number of different types.
|
||||
// It reports whether the conversion was successful.
|
||||
func ConvertVariant(v map[string]interface{}, dst interface{}) bool {
|
||||
var buf bytes.Buffer
|
||||
err := json.NewEncoder(&buf).Encode(v)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return json.Unmarshal(buf.Bytes(), dst) == nil
|
||||
}
|
||||
|
||||
// A Field names a field to be retrieved with a partial response.
|
||||
// See https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
|
||||
//
|
||||
// Partial responses can dramatically reduce the amount of data that must be sent to your application.
|
||||
// In order to request partial responses, you can specify the full list of fields
|
||||
// that your application needs by adding the Fields option to your request.
|
||||
//
|
||||
// Field strings use camelCase with leading lower-case characters to identify fields within the response.
|
||||
//
|
||||
// For example, if your response has a "NextPageToken" and a slice of "Items" with "Id" fields,
|
||||
// you could request just those fields like this:
|
||||
//
|
||||
// svc.Events.List().Fields("nextPageToken", "items/id").Do()
|
||||
//
|
||||
// or if you were also interested in each Item's "Updated" field, you can combine them like this:
|
||||
//
|
||||
// svc.Events.List().Fields("nextPageToken", "items(id,updated)").Do()
|
||||
//
|
||||
// More information about field formatting can be found here:
|
||||
// https://developers.google.com/+/api/#fields-syntax
|
||||
//
|
||||
// Another way to find field names is through the Google API explorer:
|
||||
// https://developers.google.com/apis-explorer/#p/
|
||||
type Field string
|
||||
|
||||
// CombineFields combines fields into a single string.
|
||||
func CombineFields(s []Field) string {
|
||||
r := make([]string, len(s))
|
||||
for i, v := range s {
|
||||
r[i] = string(v)
|
||||
}
|
||||
return strings.Join(r, ",")
|
||||
}
|
||||
|
||||
// A CallOption is an optional argument to an API call.
|
||||
// It should be treated as an opaque value by users of Google APIs.
|
||||
//
|
||||
// A CallOption is something that configures an API call in a way that is
|
||||
// not specific to that API; for instance, controlling the quota user for
|
||||
// an API call is common across many APIs, and is thus a CallOption.
|
||||
type CallOption interface {
|
||||
Get() (key, value string)
|
||||
}
|
||||
|
||||
// QuotaUser returns a CallOption that will set the quota user for a call.
|
||||
// The quota user can be used by server-side applications to control accounting.
|
||||
// It can be an arbitrary string up to 40 characters, and will override UserIP
|
||||
// if both are provided.
|
||||
func QuotaUser(u string) CallOption { return quotaUser(u) }
|
||||
|
||||
type quotaUser string
|
||||
|
||||
func (q quotaUser) Get() (string, string) { return "quotaUser", string(q) }
|
||||
|
||||
// UserIP returns a CallOption that will set the "userIp" parameter of a call.
|
||||
// This should be the IP address of the originating request.
|
||||
func UserIP(ip string) CallOption { return userIP(ip) }
|
||||
|
||||
type userIP string
|
||||
|
||||
func (i userIP) Get() (string, string) { return "userIp", string(i) }
|
||||
|
||||
// Trace returns a CallOption that enables diagnostic tracing for a call.
|
||||
// traceToken is an ID supplied by Google support.
|
||||
func Trace(traceToken string) CallOption { return traceTok(traceToken) }
|
||||
|
||||
type traceTok string
|
||||
|
||||
func (t traceTok) Get() (string, string) { return "trace", "token:" + string(t) }
|
||||
|
||||
// TODO: Fields too
|
18
vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE
generated
vendored
Normal file
18
vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
Copyright (c) 2013 Joshua Tacoma
|
||||
|
||||
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.
|
248
vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go
generated
vendored
Normal file
248
vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go
generated
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
// Copyright 2013 Joshua Tacoma. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package uritemplates is a level 3 implementation of RFC 6570 (URI
|
||||
// Template, http://tools.ietf.org/html/rfc6570).
|
||||
// uritemplates does not support composite values (in Go: slices or maps)
|
||||
// and so does not qualify as a level 4 implementation.
|
||||
package uritemplates
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
unreserved = regexp.MustCompile("[^A-Za-z0-9\\-._~]")
|
||||
reserved = regexp.MustCompile("[^A-Za-z0-9\\-._~:/?#[\\]@!$&'()*+,;=]")
|
||||
validname = regexp.MustCompile("^([A-Za-z0-9_\\.]|%[0-9A-Fa-f][0-9A-Fa-f])+$")
|
||||
hex = []byte("0123456789ABCDEF")
|
||||
)
|
||||
|
||||
func pctEncode(src []byte) []byte {
|
||||
dst := make([]byte, len(src)*3)
|
||||
for i, b := range src {
|
||||
buf := dst[i*3 : i*3+3]
|
||||
buf[0] = 0x25
|
||||
buf[1] = hex[b/16]
|
||||
buf[2] = hex[b%16]
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// pairWriter is a convenience struct which allows escaped and unescaped
|
||||
// versions of the template to be written in parallel.
|
||||
type pairWriter struct {
|
||||
escaped, unescaped bytes.Buffer
|
||||
}
|
||||
|
||||
// Write writes the provided string directly without any escaping.
|
||||
func (w *pairWriter) Write(s string) {
|
||||
w.escaped.WriteString(s)
|
||||
w.unescaped.WriteString(s)
|
||||
}
|
||||
|
||||
// Escape writes the provided string, escaping the string for the
|
||||
// escaped output.
|
||||
func (w *pairWriter) Escape(s string, allowReserved bool) {
|
||||
w.unescaped.WriteString(s)
|
||||
if allowReserved {
|
||||
w.escaped.Write(reserved.ReplaceAllFunc([]byte(s), pctEncode))
|
||||
} else {
|
||||
w.escaped.Write(unreserved.ReplaceAllFunc([]byte(s), pctEncode))
|
||||
}
|
||||
}
|
||||
|
||||
// Escaped returns the escaped string.
|
||||
func (w *pairWriter) Escaped() string {
|
||||
return w.escaped.String()
|
||||
}
|
||||
|
||||
// Unescaped returns the unescaped string.
|
||||
func (w *pairWriter) Unescaped() string {
|
||||
return w.unescaped.String()
|
||||
}
|
||||
|
||||
// A uriTemplate is a parsed representation of a URI template.
|
||||
type uriTemplate struct {
|
||||
raw string
|
||||
parts []templatePart
|
||||
}
|
||||
|
||||
// parse parses a URI template string into a uriTemplate object.
|
||||
func parse(rawTemplate string) (*uriTemplate, error) {
|
||||
split := strings.Split(rawTemplate, "{")
|
||||
parts := make([]templatePart, len(split)*2-1)
|
||||
for i, s := range split {
|
||||
if i == 0 {
|
||||
if strings.Contains(s, "}") {
|
||||
return nil, errors.New("unexpected }")
|
||||
}
|
||||
parts[i].raw = s
|
||||
continue
|
||||
}
|
||||
subsplit := strings.Split(s, "}")
|
||||
if len(subsplit) != 2 {
|
||||
return nil, errors.New("malformed template")
|
||||
}
|
||||
expression := subsplit[0]
|
||||
var err error
|
||||
parts[i*2-1], err = parseExpression(expression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parts[i*2].raw = subsplit[1]
|
||||
}
|
||||
return &uriTemplate{
|
||||
raw: rawTemplate,
|
||||
parts: parts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type templatePart struct {
|
||||
raw string
|
||||
terms []templateTerm
|
||||
first string
|
||||
sep string
|
||||
named bool
|
||||
ifemp string
|
||||
allowReserved bool
|
||||
}
|
||||
|
||||
type templateTerm struct {
|
||||
name string
|
||||
explode bool
|
||||
truncate int
|
||||
}
|
||||
|
||||
func parseExpression(expression string) (result templatePart, err error) {
|
||||
switch expression[0] {
|
||||
case '+':
|
||||
result.sep = ","
|
||||
result.allowReserved = true
|
||||
expression = expression[1:]
|
||||
case '.':
|
||||
result.first = "."
|
||||
result.sep = "."
|
||||
expression = expression[1:]
|
||||
case '/':
|
||||
result.first = "/"
|
||||
result.sep = "/"
|
||||
expression = expression[1:]
|
||||
case ';':
|
||||
result.first = ";"
|
||||
result.sep = ";"
|
||||
result.named = true
|
||||
expression = expression[1:]
|
||||
case '?':
|
||||
result.first = "?"
|
||||
result.sep = "&"
|
||||
result.named = true
|
||||
result.ifemp = "="
|
||||
expression = expression[1:]
|
||||
case '&':
|
||||
result.first = "&"
|
||||
result.sep = "&"
|
||||
result.named = true
|
||||
result.ifemp = "="
|
||||
expression = expression[1:]
|
||||
case '#':
|
||||
result.first = "#"
|
||||
result.sep = ","
|
||||
result.allowReserved = true
|
||||
expression = expression[1:]
|
||||
default:
|
||||
result.sep = ","
|
||||
}
|
||||
rawterms := strings.Split(expression, ",")
|
||||
result.terms = make([]templateTerm, len(rawterms))
|
||||
for i, raw := range rawterms {
|
||||
result.terms[i], err = parseTerm(raw)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func parseTerm(term string) (result templateTerm, err error) {
|
||||
// TODO(djd): Remove "*" suffix parsing once we check that no APIs have
|
||||
// mistakenly used that attribute.
|
||||
if strings.HasSuffix(term, "*") {
|
||||
result.explode = true
|
||||
term = term[:len(term)-1]
|
||||
}
|
||||
split := strings.Split(term, ":")
|
||||
if len(split) == 1 {
|
||||
result.name = term
|
||||
} else if len(split) == 2 {
|
||||
result.name = split[0]
|
||||
var parsed int64
|
||||
parsed, err = strconv.ParseInt(split[1], 10, 0)
|
||||
result.truncate = int(parsed)
|
||||
} else {
|
||||
err = errors.New("multiple colons in same term")
|
||||
}
|
||||
if !validname.MatchString(result.name) {
|
||||
err = errors.New("not a valid name: " + result.name)
|
||||
}
|
||||
if result.explode && result.truncate > 0 {
|
||||
err = errors.New("both explode and prefix modifers on same term")
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Expand expands a URI template with a set of values to produce the
|
||||
// resultant URI. Two forms of the result are returned: one with all the
|
||||
// elements escaped, and one with the elements unescaped.
|
||||
func (t *uriTemplate) Expand(values map[string]string) (escaped, unescaped string) {
|
||||
var w pairWriter
|
||||
for _, p := range t.parts {
|
||||
p.expand(&w, values)
|
||||
}
|
||||
return w.Escaped(), w.Unescaped()
|
||||
}
|
||||
|
||||
func (tp *templatePart) expand(w *pairWriter, values map[string]string) {
|
||||
if len(tp.raw) > 0 {
|
||||
w.Write(tp.raw)
|
||||
return
|
||||
}
|
||||
var first = true
|
||||
for _, term := range tp.terms {
|
||||
value, exists := values[term.name]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
if first {
|
||||
w.Write(tp.first)
|
||||
first = false
|
||||
} else {
|
||||
w.Write(tp.sep)
|
||||
}
|
||||
tp.expandString(w, term, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *templatePart) expandName(w *pairWriter, name string, empty bool) {
|
||||
if tp.named {
|
||||
w.Write(name)
|
||||
if empty {
|
||||
w.Write(tp.ifemp)
|
||||
} else {
|
||||
w.Write("=")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *templatePart) expandString(w *pairWriter, t templateTerm, s string) {
|
||||
if len(s) > t.truncate && t.truncate > 0 {
|
||||
s = s[:t.truncate]
|
||||
}
|
||||
tp.expandName(w, t.name, len(s) == 0)
|
||||
w.Escape(s, tp.allowReserved)
|
||||
}
|
17
vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go
generated
vendored
Normal file
17
vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package uritemplates
|
||||
|
||||
// Expand parses then expands a URI template with a set of values to produce
|
||||
// the resultant URI. Two forms of the result are returned: one with all the
|
||||
// elements escaped, and one with the elements unescaped.
|
||||
func Expand(path string, values map[string]string) (escaped, unescaped string, err error) {
|
||||
template, err := parse(path)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
escaped, unescaped = template.Expand(values)
|
||||
return escaped, unescaped, nil
|
||||
}
|
38
vendor/google.golang.org/api/googleapi/transport/apikey.go
generated
vendored
Normal file
38
vendor/google.golang.org/api/googleapi/transport/apikey.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package transport contains HTTP transports used to make
|
||||
// authenticated API requests.
|
||||
package transport
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// APIKey is an HTTP Transport which wraps an underlying transport and
|
||||
// appends an API Key "key" parameter to the URL of outgoing requests.
|
||||
type APIKey struct {
|
||||
// Key is the API Key to set on requests.
|
||||
Key string
|
||||
|
||||
// Transport is the underlying HTTP transport.
|
||||
// If nil, http.DefaultTransport is used.
|
||||
Transport http.RoundTripper
|
||||
}
|
||||
|
||||
func (t *APIKey) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
rt := t.Transport
|
||||
if rt == nil {
|
||||
rt = http.DefaultTransport
|
||||
if rt == nil {
|
||||
return nil, errors.New("googleapi/transport: no Transport specified or available")
|
||||
}
|
||||
}
|
||||
newReq := *req
|
||||
args := newReq.URL.Query()
|
||||
args.Set("key", t.Key)
|
||||
newReq.URL.RawQuery = args.Encode()
|
||||
return rt.RoundTrip(&newReq)
|
||||
}
|
202
vendor/google.golang.org/api/googleapi/types.go
generated
vendored
Normal file
202
vendor/google.golang.org/api/googleapi/types.go
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
// Copyright 2013 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package googleapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Int64s is a slice of int64s that marshal as quoted strings in JSON.
|
||||
type Int64s []int64
|
||||
|
||||
func (q *Int64s) UnmarshalJSON(raw []byte) error {
|
||||
*q = (*q)[:0]
|
||||
var ss []string
|
||||
if err := json.Unmarshal(raw, &ss); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range ss {
|
||||
v, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*q = append(*q, int64(v))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int32s is a slice of int32s that marshal as quoted strings in JSON.
|
||||
type Int32s []int32
|
||||
|
||||
func (q *Int32s) UnmarshalJSON(raw []byte) error {
|
||||
*q = (*q)[:0]
|
||||
var ss []string
|
||||
if err := json.Unmarshal(raw, &ss); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range ss {
|
||||
v, err := strconv.ParseInt(s, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*q = append(*q, int32(v))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uint64s is a slice of uint64s that marshal as quoted strings in JSON.
|
||||
type Uint64s []uint64
|
||||
|
||||
func (q *Uint64s) UnmarshalJSON(raw []byte) error {
|
||||
*q = (*q)[:0]
|
||||
var ss []string
|
||||
if err := json.Unmarshal(raw, &ss); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range ss {
|
||||
v, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*q = append(*q, uint64(v))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uint32s is a slice of uint32s that marshal as quoted strings in JSON.
|
||||
type Uint32s []uint32
|
||||
|
||||
func (q *Uint32s) UnmarshalJSON(raw []byte) error {
|
||||
*q = (*q)[:0]
|
||||
var ss []string
|
||||
if err := json.Unmarshal(raw, &ss); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range ss {
|
||||
v, err := strconv.ParseUint(s, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*q = append(*q, uint32(v))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Float64s is a slice of float64s that marshal as quoted strings in JSON.
|
||||
type Float64s []float64
|
||||
|
||||
func (q *Float64s) UnmarshalJSON(raw []byte) error {
|
||||
*q = (*q)[:0]
|
||||
var ss []string
|
||||
if err := json.Unmarshal(raw, &ss); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range ss {
|
||||
v, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*q = append(*q, float64(v))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func quotedList(n int, fn func(dst []byte, i int) []byte) ([]byte, error) {
|
||||
dst := make([]byte, 0, 2+n*10) // somewhat arbitrary
|
||||
dst = append(dst, '[')
|
||||
for i := 0; i < n; i++ {
|
||||
if i > 0 {
|
||||
dst = append(dst, ',')
|
||||
}
|
||||
dst = append(dst, '"')
|
||||
dst = fn(dst, i)
|
||||
dst = append(dst, '"')
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (q Int64s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(q), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendInt(dst, q[i], 10)
|
||||
})
|
||||
}
|
||||
|
||||
func (q Int32s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(q), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendInt(dst, int64(q[i]), 10)
|
||||
})
|
||||
}
|
||||
|
||||
func (q Uint64s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(q), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendUint(dst, q[i], 10)
|
||||
})
|
||||
}
|
||||
|
||||
func (q Uint32s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(q), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendUint(dst, uint64(q[i]), 10)
|
||||
})
|
||||
}
|
||||
|
||||
func (q Float64s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(q), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendFloat(dst, q[i], 'g', -1, 64)
|
||||
})
|
||||
}
|
||||
|
||||
// RawMessage is a raw encoded JSON value.
|
||||
// It is identical to json.RawMessage, except it does not suffer from
|
||||
// https://golang.org/issue/14493.
|
||||
type RawMessage []byte
|
||||
|
||||
// MarshalJSON returns m.
|
||||
func (m RawMessage) MarshalJSON() ([]byte, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets *m to a copy of data.
|
||||
func (m *RawMessage) UnmarshalJSON(data []byte) error {
|
||||
if m == nil {
|
||||
return errors.New("googleapi.RawMessage: UnmarshalJSON on nil pointer")
|
||||
}
|
||||
*m = append((*m)[:0], data...)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routines for simplifying the creation of optional fields of basic type.
|
||||
*/
|
||||
|
||||
// Bool is a helper routine that allocates a new bool value
|
||||
// to store v and returns a pointer to it.
|
||||
func Bool(v bool) *bool { return &v }
|
||||
|
||||
// Int32 is a helper routine that allocates a new int32 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Int32(v int32) *int32 { return &v }
|
||||
|
||||
// Int64 is a helper routine that allocates a new int64 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Int64(v int64) *int64 { return &v }
|
||||
|
||||
// Float64 is a helper routine that allocates a new float64 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Float64(v float64) *float64 { return &v }
|
||||
|
||||
// Uint32 is a helper routine that allocates a new uint32 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Uint32(v uint32) *uint32 { return &v }
|
||||
|
||||
// Uint64 is a helper routine that allocates a new uint64 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Uint64(v uint64) *uint64 { return &v }
|
||||
|
||||
// String is a helper routine that allocates a new string value
|
||||
// to store v and returns a pointer to it.
|
||||
func String(v string) *string { return &v }
|
102
vendor/google.golang.org/api/internal/creds.go
generated
vendored
Normal file
102
vendor/google.golang.org/api/internal/creds.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// 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 internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"golang.org/x/oauth2/google"
|
||||
)
|
||||
|
||||
// Creds returns credential information obtained from DialSettings, or if none, then
|
||||
// it returns default credential information.
|
||||
func Creds(ctx context.Context, ds *DialSettings) (*google.Credentials, error) {
|
||||
if ds.Credentials != nil {
|
||||
return ds.Credentials, nil
|
||||
}
|
||||
if ds.CredentialsJSON != nil {
|
||||
return credentialsFromJSON(ctx, ds.CredentialsJSON, ds.Endpoint, ds.Scopes, ds.Audiences)
|
||||
}
|
||||
if ds.CredentialsFile != "" {
|
||||
data, err := ioutil.ReadFile(ds.CredentialsFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read credentials file: %v", err)
|
||||
}
|
||||
return credentialsFromJSON(ctx, data, ds.Endpoint, ds.Scopes, ds.Audiences)
|
||||
}
|
||||
if ds.TokenSource != nil {
|
||||
return &google.Credentials{TokenSource: ds.TokenSource}, nil
|
||||
}
|
||||
cred, err := google.FindDefaultCredentials(ctx, ds.Scopes...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cred.JSON) > 0 {
|
||||
return credentialsFromJSON(ctx, cred.JSON, ds.Endpoint, ds.Scopes, ds.Audiences)
|
||||
}
|
||||
// For GAE and GCE, the JSON is empty so return the default credentials directly.
|
||||
return cred, nil
|
||||
}
|
||||
|
||||
// JSON key file type.
|
||||
const (
|
||||
serviceAccountKey = "service_account"
|
||||
)
|
||||
|
||||
// credentialsFromJSON returns a google.Credentials based on the input.
|
||||
//
|
||||
// - If the JSON is a service account and no scopes provided, returns self-signed JWT auth flow
|
||||
// - Otherwise, returns OAuth 2.0 flow.
|
||||
func credentialsFromJSON(ctx context.Context, data []byte, endpoint string, scopes []string, audiences []string) (*google.Credentials, error) {
|
||||
cred, err := google.CredentialsFromJSON(ctx, data, scopes...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(data) > 0 && len(scopes) == 0 {
|
||||
var f struct {
|
||||
Type string `json:"type"`
|
||||
// The rest JSON fields are omitted because they are not used.
|
||||
}
|
||||
if err := json.Unmarshal(cred.JSON, &f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.Type == serviceAccountKey {
|
||||
ts, err := selfSignedJWTTokenSource(data, endpoint, audiences)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cred.TokenSource = ts
|
||||
}
|
||||
}
|
||||
return cred, err
|
||||
}
|
||||
|
||||
func selfSignedJWTTokenSource(data []byte, endpoint string, audiences []string) (oauth2.TokenSource, error) {
|
||||
// Use the API endpoint as the default audience
|
||||
audience := endpoint
|
||||
if len(audiences) > 0 {
|
||||
// TODO(shinfan): Update golang oauth to support multiple audiences.
|
||||
if len(audiences) > 1 {
|
||||
return nil, fmt.Errorf("multiple audiences support is not implemented")
|
||||
}
|
||||
audience = audiences[0]
|
||||
}
|
||||
return google.JWTAccessTokenSourceFromJSON(data, audience)
|
||||
}
|
61
vendor/google.golang.org/api/internal/pool.go
generated
vendored
Normal file
61
vendor/google.golang.org/api/internal/pool.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2016 Google LLC
|
||||
//
|
||||
// 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 internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"google.golang.org/grpc/naming"
|
||||
)
|
||||
|
||||
// PoolResolver provides a fixed list of addresses to load balance between
|
||||
// and does not provide further updates.
|
||||
type PoolResolver struct {
|
||||
poolSize int
|
||||
dialOpt *DialSettings
|
||||
ch chan []*naming.Update
|
||||
}
|
||||
|
||||
// NewPoolResolver returns a PoolResolver
|
||||
// This is an EXPERIMENTAL API and may be changed or removed in the future.
|
||||
func NewPoolResolver(size int, o *DialSettings) *PoolResolver {
|
||||
return &PoolResolver{poolSize: size, dialOpt: o}
|
||||
}
|
||||
|
||||
// Resolve returns a Watcher for the endpoint defined by the DialSettings
|
||||
// provided to NewPoolResolver.
|
||||
func (r *PoolResolver) Resolve(target string) (naming.Watcher, error) {
|
||||
if r.dialOpt.Endpoint == "" {
|
||||
return nil, errors.New("no endpoint configured")
|
||||
}
|
||||
addrs := make([]*naming.Update, 0, r.poolSize)
|
||||
for i := 0; i < r.poolSize; i++ {
|
||||
addrs = append(addrs, &naming.Update{Op: naming.Add, Addr: r.dialOpt.Endpoint, Metadata: i})
|
||||
}
|
||||
r.ch = make(chan []*naming.Update, 1)
|
||||
r.ch <- addrs
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Next returns a static list of updates on the first call,
|
||||
// and blocks indefinitely until Close is called on subsequent calls.
|
||||
func (r *PoolResolver) Next() ([]*naming.Update, error) {
|
||||
return <-r.ch, nil
|
||||
}
|
||||
|
||||
// Close releases resources associated with the pool and causes Next to unblock.
|
||||
func (r *PoolResolver) Close() {
|
||||
close(r.ch)
|
||||
}
|
12
vendor/google.golang.org/api/internal/service-account.json
generated
vendored
Normal file
12
vendor/google.golang.org/api/internal/service-account.json
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"type": "service_account",
|
||||
"project_id": "project_id",
|
||||
"private_key_id": "private_key_id",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzd9ZdbPLAR4/g\nj+Rodu15kEasMpxf/Mz+gKRb2fmgR2Y18Y/iRBYZ4SkmF2pBSfzvwE/aTCzSPBGl\njHhPzohXnSN029eWoItmxVONlqCbR29pD07aLzv08LGeIGdHIEdhVjhvRwTkYZIF\ndXmlHNDRUU/EbJN9D+3ahw22BNnC4PaDgfIWTs3xIlTCSf2rL39I4DSNLTS/LzxK\n/XrQfBMtfwMWwyQaemXbc7gRgzOy8L56wa1W1zyXx99th97j1bLnoAXBGplhB4Co\n25ohyDAuhxRm+XGMEaO0Mzo7u97kvhj48a569RH1QRhOf7EBf60jO4h5eOmfi5P5\nPV3l7041AgMBAAECggEAEZ0RTNoEeRqM5F067YW+iM/AH+ZXspP9Cn1VpC4gcbqQ\nLXsnw+0qvh97CmIB66Z3TJBzRdl0DK4YjUbcB/kdKHwjnrR01DOtesijCqJd4N+B\n762w73jzSXbV9872U+S3HLZ5k3JE6KUqz55X8fyCAgkY6w4862lEzs2yasrPFHEV\nRoQp3PM0Miif8R3hGDhOWcHxcobullthG6JHAQFfc1ctwEjZI4TK0iWqlzfWGyKN\nT9UgvjUDud5cGvS9el0AiLN6keAf77tcPn1zetUVhxN1KN4bVAm1Q+6O8esl63Rj\n7JXpHzxaRnit9S6/aH/twHsGGtLg5Puw6jey6xs4AQKBgQD2JNy1wzewCRkD+jug\n8CHbJ+LIJVRNIaWa/RK1QD8/UjmFPkIzRQSF3AKC5mRAWSa2FL3yVK3N/DD7hazW\n85XSBB7IDcnoJnA9SkUeWwqQGkDx3EntlU3gX8Kn/+ofF8O9jLXxAa901MAVXVuf\n5YDzrl4PNE3bFnPCdiNmSdRfhQKBgQC6p4DsCpwqbeTu9f5ak9VW/fQP47Fgt+Mf\nwGjBnKP5PbbNJpHCfamF7jqSRH83Xy0KNssH7jD/NZ2oT594sMmiQPUC5ni9VYY6\nsuYB0JbD5Mq+EjKIVhYtxaQJ76LzHreEI+G4z6k3H7/hRpr3/C48n9G/uVkT9DbJ\noplxxEx68QKBgQCdJ23vcwO0Firtmi/GEmtbVHz70rGfSXNFoHz4UlvPXv0wsE5u\nE4vOt2i3EMhDOWh46odYGG6bzH+tp2xyFTW70Dui+QLHgPs6dpfoyLHWzZxXj5F3\n6lK9hgZvYvqk/XRRKmzjwnK2wjsdqOyeC1covlR5mqh20D/6kZkKbur0TQKBgAwy\nCZBimRWEnKKoW/gbFKNccGfhXqONID/g2Hdd/rC4QYth68AjacIgcJ9B7nX1uAGk\n1tsryvPB0w0+NpMyKdp6GAgaeuUUA3MuYSzZLiCagEyu77JMvaI7+Z3UlHcCGMd/\neK4Uk1/QqT7U2Cc/yN2ZK6E1QQa2vCWshA4U31JhAoGAbtbSSSsul1c+PsJ13Cfk\n6qVnqYzPqt23QTyOZmGAvUHH/M4xRiQpOE0cDF4t/r5PwenAQPQzTvMmWRzj6uAY\n3eaU0eAK7ZfoweCoOIAPnpFbbRLrXfoY46H7MYh7euWGXOKEpxz5yzuEkd9ByNUE\n86vSEidqbMIiXVgEgnu/k08=\n-----END PRIVATE KEY-----\n",
|
||||
"client_email": "xyz@developer.gserviceaccount.com",
|
||||
"client_id": "123",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://accounts.google.com/o/oauth2/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xyz%40developer.gserviceaccount.com"
|
||||
}
|
96
vendor/google.golang.org/api/internal/settings.go
generated
vendored
Normal file
96
vendor/google.golang.org/api/internal/settings.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// 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 internal supports the options and transport packages.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// DialSettings holds information needed to establish a connection with a
|
||||
// Google API service.
|
||||
type DialSettings struct {
|
||||
Endpoint string
|
||||
Scopes []string
|
||||
TokenSource oauth2.TokenSource
|
||||
Credentials *google.Credentials
|
||||
CredentialsFile string // if set, Token Source is ignored.
|
||||
CredentialsJSON []byte
|
||||
UserAgent string
|
||||
APIKey string
|
||||
Audiences []string
|
||||
HTTPClient *http.Client
|
||||
GRPCDialOpts []grpc.DialOption
|
||||
GRPCConn *grpc.ClientConn
|
||||
NoAuth bool
|
||||
|
||||
// Google API system parameters. For more information please read:
|
||||
// https://cloud.google.com/apis/docs/system-parameters
|
||||
QuotaProject string
|
||||
RequestReason string
|
||||
}
|
||||
|
||||
// Validate reports an error if ds is invalid.
|
||||
func (ds *DialSettings) Validate() error {
|
||||
hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil
|
||||
if ds.NoAuth && hasCreds {
|
||||
return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials")
|
||||
}
|
||||
// Credentials should not appear with other options.
|
||||
// We currently allow TokenSource and CredentialsFile to coexist.
|
||||
// TODO(jba): make TokenSource & CredentialsFile an error (breaking change).
|
||||
nCreds := 0
|
||||
if ds.Credentials != nil {
|
||||
nCreds++
|
||||
}
|
||||
if ds.CredentialsJSON != nil {
|
||||
nCreds++
|
||||
}
|
||||
if ds.CredentialsFile != "" {
|
||||
nCreds++
|
||||
}
|
||||
if ds.APIKey != "" {
|
||||
nCreds++
|
||||
}
|
||||
if ds.TokenSource != nil {
|
||||
nCreds++
|
||||
}
|
||||
if len(ds.Scopes) > 0 && len(ds.Audiences) > 0 {
|
||||
return errors.New("WithScopes is incompatible with WithAudience")
|
||||
}
|
||||
// Accept only one form of credentials, except we allow TokenSource and CredentialsFile for backwards compatibility.
|
||||
if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") {
|
||||
return errors.New("multiple credential options provided")
|
||||
}
|
||||
if ds.HTTPClient != nil && ds.GRPCConn != nil {
|
||||
return errors.New("WithHTTPClient is incompatible with WithGRPCConn")
|
||||
}
|
||||
if ds.HTTPClient != nil && ds.GRPCDialOpts != nil {
|
||||
return errors.New("WithHTTPClient is incompatible with gRPC dial options")
|
||||
}
|
||||
if ds.HTTPClient != nil && ds.QuotaProject != "" {
|
||||
return errors.New("WithHTTPClient is incompatible with QuotaProject")
|
||||
}
|
||||
if ds.HTTPClient != nil && ds.RequestReason != "" {
|
||||
return errors.New("WithHTTPClient is incompatible with RequestReason")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
231
vendor/google.golang.org/api/iterator/iterator.go
generated
vendored
Normal file
231
vendor/google.golang.org/api/iterator/iterator.go
generated
vendored
Normal file
@ -0,0 +1,231 @@
|
||||
// Copyright 2016 Google LLC
|
||||
//
|
||||
// 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 iterator provides support for standard Google API iterators.
|
||||
// See https://github.com/GoogleCloudPlatform/gcloud-golang/wiki/Iterator-Guidelines.
|
||||
package iterator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Done is returned by an iterator's Next method when the iteration is
|
||||
// complete; when there are no more items to return.
|
||||
var Done = errors.New("no more items in iterator")
|
||||
|
||||
// We don't support mixed calls to Next and NextPage because they play
|
||||
// with the paging state in incompatible ways.
|
||||
var errMixed = errors.New("iterator: Next and NextPage called on same iterator")
|
||||
|
||||
// PageInfo contains information about an iterator's paging state.
|
||||
type PageInfo struct {
|
||||
// Token is the token used to retrieve the next page of items from the
|
||||
// API. You may set Token immediately after creating an iterator to
|
||||
// begin iteration at a particular point. If Token is the empty string,
|
||||
// the iterator will begin with the first eligible item.
|
||||
//
|
||||
// The result of setting Token after the first call to Next is undefined.
|
||||
//
|
||||
// After the underlying API method is called to retrieve a page of items,
|
||||
// Token is set to the next-page token in the response.
|
||||
Token string
|
||||
|
||||
// MaxSize is the maximum number of items returned by a call to the API.
|
||||
// Set MaxSize as a hint to optimize the buffering behavior of the iterator.
|
||||
// If zero, the page size is determined by the underlying service.
|
||||
//
|
||||
// Use Pager to retrieve a page of a specific, exact size.
|
||||
MaxSize int
|
||||
|
||||
// The error state of the iterator. Manipulated by PageInfo.next and Pager.
|
||||
// This is a latch: it starts as nil, and once set should never change.
|
||||
err error
|
||||
|
||||
// If true, no more calls to fetch should be made. Set to true when fetch
|
||||
// returns an empty page token. The iterator is Done when this is true AND
|
||||
// the buffer is empty.
|
||||
atEnd bool
|
||||
|
||||
// Function that fetches a page from the underlying service. It should pass
|
||||
// the pageSize and pageToken arguments to the service, fill the buffer
|
||||
// with the results from the call, and return the next-page token returned
|
||||
// by the service. The function must not remove any existing items from the
|
||||
// buffer. If the underlying RPC takes an int32 page size, pageSize should
|
||||
// be silently truncated.
|
||||
fetch func(pageSize int, pageToken string) (nextPageToken string, err error)
|
||||
|
||||
// Function that returns the number of currently buffered items.
|
||||
bufLen func() int
|
||||
|
||||
// Function that returns the buffer, after setting the buffer variable to nil.
|
||||
takeBuf func() interface{}
|
||||
|
||||
// Set to true on first call to PageInfo.next or Pager.NextPage. Used to check
|
||||
// for calls to both Next and NextPage with the same iterator.
|
||||
nextCalled, nextPageCalled bool
|
||||
}
|
||||
|
||||
// NewPageInfo exposes internals for iterator implementations.
|
||||
// It is not a stable interface.
|
||||
var NewPageInfo = newPageInfo
|
||||
|
||||
// If an iterator can support paging, its iterator-creating method should call
|
||||
// this (via the NewPageInfo variable above).
|
||||
//
|
||||
// The fetch, bufLen and takeBuf arguments provide access to the
|
||||
// iterator's internal slice of buffered items. They behave as described in
|
||||
// PageInfo, above.
|
||||
//
|
||||
// The return value is the PageInfo.next method bound to the returned PageInfo value.
|
||||
// (Returning it avoids exporting PageInfo.next.)
|
||||
func newPageInfo(fetch func(int, string) (string, error), bufLen func() int, takeBuf func() interface{}) (*PageInfo, func() error) {
|
||||
pi := &PageInfo{
|
||||
fetch: fetch,
|
||||
bufLen: bufLen,
|
||||
takeBuf: takeBuf,
|
||||
}
|
||||
return pi, pi.next
|
||||
}
|
||||
|
||||
// Remaining returns the number of items available before the iterator makes another API call.
|
||||
func (pi *PageInfo) Remaining() int { return pi.bufLen() }
|
||||
|
||||
// next provides support for an iterator's Next function. An iterator's Next
|
||||
// should return the error returned by next if non-nil; else it can assume
|
||||
// there is at least one item in its buffer, and it should return that item and
|
||||
// remove it from the buffer.
|
||||
func (pi *PageInfo) next() error {
|
||||
pi.nextCalled = true
|
||||
if pi.err != nil { // Once we get an error, always return it.
|
||||
// TODO(jba): fix so users can retry on transient errors? Probably not worth it.
|
||||
return pi.err
|
||||
}
|
||||
if pi.nextPageCalled {
|
||||
pi.err = errMixed
|
||||
return pi.err
|
||||
}
|
||||
// Loop until we get some items or reach the end.
|
||||
for pi.bufLen() == 0 && !pi.atEnd {
|
||||
if err := pi.fill(pi.MaxSize); err != nil {
|
||||
pi.err = err
|
||||
return pi.err
|
||||
}
|
||||
if pi.Token == "" {
|
||||
pi.atEnd = true
|
||||
}
|
||||
}
|
||||
// Either the buffer is non-empty or pi.atEnd is true (or both).
|
||||
if pi.bufLen() == 0 {
|
||||
// The buffer is empty and pi.atEnd is true, i.e. the service has no
|
||||
// more items.
|
||||
pi.err = Done
|
||||
}
|
||||
return pi.err
|
||||
}
|
||||
|
||||
// Call the service to fill the buffer, using size and pi.Token. Set pi.Token to the
|
||||
// next-page token returned by the call.
|
||||
// If fill returns a non-nil error, the buffer will be empty.
|
||||
func (pi *PageInfo) fill(size int) error {
|
||||
tok, err := pi.fetch(size, pi.Token)
|
||||
if err != nil {
|
||||
pi.takeBuf() // clear the buffer
|
||||
return err
|
||||
}
|
||||
pi.Token = tok
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pageable is implemented by iterators that support paging.
|
||||
type Pageable interface {
|
||||
// PageInfo returns paging information associated with the iterator.
|
||||
PageInfo() *PageInfo
|
||||
}
|
||||
|
||||
// Pager supports retrieving iterator items a page at a time.
|
||||
type Pager struct {
|
||||
pageInfo *PageInfo
|
||||
pageSize int
|
||||
}
|
||||
|
||||
// NewPager returns a pager that uses iter. Calls to its NextPage method will
|
||||
// obtain exactly pageSize items, unless fewer remain. The pageToken argument
|
||||
// indicates where to start the iteration. Pass the empty string to start at
|
||||
// the beginning, or pass a token retrieved from a call to Pager.NextPage.
|
||||
//
|
||||
// If you use an iterator with a Pager, you must not call Next on the iterator.
|
||||
func NewPager(iter Pageable, pageSize int, pageToken string) *Pager {
|
||||
p := &Pager{
|
||||
pageInfo: iter.PageInfo(),
|
||||
pageSize: pageSize,
|
||||
}
|
||||
p.pageInfo.Token = pageToken
|
||||
if pageSize <= 0 {
|
||||
p.pageInfo.err = errors.New("iterator: page size must be positive")
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// NextPage retrieves a sequence of items from the iterator and appends them
|
||||
// to slicep, which must be a pointer to a slice of the iterator's item type.
|
||||
// Exactly p.pageSize items will be appended, unless fewer remain.
|
||||
//
|
||||
// The first return value is the page token to use for the next page of items.
|
||||
// If empty, there are no more pages. Aside from checking for the end of the
|
||||
// iteration, the returned page token is only needed if the iteration is to be
|
||||
// resumed a later time, in another context (possibly another process).
|
||||
//
|
||||
// The second return value is non-nil if an error occurred. It will never be
|
||||
// the special iterator sentinel value Done. To recognize the end of the
|
||||
// iteration, compare nextPageToken to the empty string.
|
||||
//
|
||||
// It is possible for NextPage to return a single zero-length page along with
|
||||
// an empty page token when there are no more items in the iteration.
|
||||
func (p *Pager) NextPage(slicep interface{}) (nextPageToken string, err error) {
|
||||
p.pageInfo.nextPageCalled = true
|
||||
if p.pageInfo.err != nil {
|
||||
return "", p.pageInfo.err
|
||||
}
|
||||
if p.pageInfo.nextCalled {
|
||||
p.pageInfo.err = errMixed
|
||||
return "", p.pageInfo.err
|
||||
}
|
||||
if p.pageInfo.bufLen() > 0 {
|
||||
return "", errors.New("must call NextPage with an empty buffer")
|
||||
}
|
||||
// The buffer must be empty here, so takeBuf is a no-op. We call it just to get
|
||||
// the buffer's type.
|
||||
wantSliceType := reflect.PtrTo(reflect.ValueOf(p.pageInfo.takeBuf()).Type())
|
||||
if slicep == nil {
|
||||
return "", errors.New("nil passed to Pager.NextPage")
|
||||
}
|
||||
vslicep := reflect.ValueOf(slicep)
|
||||
if vslicep.Type() != wantSliceType {
|
||||
return "", fmt.Errorf("slicep should be of type %s, got %T", wantSliceType, slicep)
|
||||
}
|
||||
for p.pageInfo.bufLen() < p.pageSize {
|
||||
if err := p.pageInfo.fill(p.pageSize - p.pageInfo.bufLen()); err != nil {
|
||||
p.pageInfo.err = err
|
||||
return "", p.pageInfo.err
|
||||
}
|
||||
if p.pageInfo.Token == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
e := vslicep.Elem()
|
||||
e.Set(reflect.AppendSlice(e, reflect.ValueOf(p.pageInfo.takeBuf())))
|
||||
return p.pageInfo.Token, nil
|
||||
}
|
33
vendor/google.golang.org/api/option/credentials_go19.go
generated
vendored
Normal file
33
vendor/google.golang.org/api/option/credentials_go19.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package option
|
||||
|
||||
import (
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/internal"
|
||||
)
|
||||
|
||||
type withCreds google.Credentials
|
||||
|
||||
func (w *withCreds) Apply(o *internal.DialSettings) {
|
||||
o.Credentials = (*google.Credentials)(w)
|
||||
}
|
||||
|
||||
// WithCredentials returns a ClientOption that authenticates API calls.
|
||||
func WithCredentials(creds *google.Credentials) ClientOption {
|
||||
return (*withCreds)(creds)
|
||||
}
|
32
vendor/google.golang.org/api/option/credentials_notgo19.go
generated
vendored
Normal file
32
vendor/google.golang.org/api/option/credentials_notgo19.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build !go1.9
|
||||
|
||||
package option
|
||||
|
||||
import (
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/internal"
|
||||
)
|
||||
|
||||
type withCreds google.DefaultCredentials
|
||||
|
||||
func (w *withCreds) Apply(o *internal.DialSettings) {
|
||||
o.Credentials = (*google.DefaultCredentials)(w)
|
||||
}
|
||||
|
||||
func WithCredentials(creds *google.DefaultCredentials) ClientOption {
|
||||
return (*withCreds)(creds)
|
||||
}
|
235
vendor/google.golang.org/api/option/option.go
generated
vendored
Normal file
235
vendor/google.golang.org/api/option/option.go
generated
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// 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 option contains options for Google API clients.
|
||||
package option
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"google.golang.org/api/internal"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// A ClientOption is an option for a Google API client.
|
||||
type ClientOption interface {
|
||||
Apply(*internal.DialSettings)
|
||||
}
|
||||
|
||||
// WithTokenSource returns a ClientOption that specifies an OAuth2 token
|
||||
// source to be used as the basis for authentication.
|
||||
func WithTokenSource(s oauth2.TokenSource) ClientOption {
|
||||
return withTokenSource{s}
|
||||
}
|
||||
|
||||
type withTokenSource struct{ ts oauth2.TokenSource }
|
||||
|
||||
func (w withTokenSource) Apply(o *internal.DialSettings) {
|
||||
o.TokenSource = w.ts
|
||||
}
|
||||
|
||||
type withCredFile string
|
||||
|
||||
func (w withCredFile) Apply(o *internal.DialSettings) {
|
||||
o.CredentialsFile = string(w)
|
||||
}
|
||||
|
||||
// WithCredentialsFile returns a ClientOption that authenticates
|
||||
// API calls with the given service account or refresh token JSON
|
||||
// credentials file.
|
||||
func WithCredentialsFile(filename string) ClientOption {
|
||||
return withCredFile(filename)
|
||||
}
|
||||
|
||||
// WithServiceAccountFile returns a ClientOption that uses a Google service
|
||||
// account credentials file to authenticate.
|
||||
//
|
||||
// Deprecated: Use WithCredentialsFile instead.
|
||||
func WithServiceAccountFile(filename string) ClientOption {
|
||||
return WithCredentialsFile(filename)
|
||||
}
|
||||
|
||||
// WithCredentialsJSON returns a ClientOption that authenticates
|
||||
// API calls with the given service account or refresh token JSON
|
||||
// credentials.
|
||||
func WithCredentialsJSON(p []byte) ClientOption {
|
||||
return withCredentialsJSON(p)
|
||||
}
|
||||
|
||||
type withCredentialsJSON []byte
|
||||
|
||||
func (w withCredentialsJSON) Apply(o *internal.DialSettings) {
|
||||
o.CredentialsJSON = make([]byte, len(w))
|
||||
copy(o.CredentialsJSON, w)
|
||||
}
|
||||
|
||||
// WithEndpoint returns a ClientOption that overrides the default endpoint
|
||||
// to be used for a service.
|
||||
func WithEndpoint(url string) ClientOption {
|
||||
return withEndpoint(url)
|
||||
}
|
||||
|
||||
type withEndpoint string
|
||||
|
||||
func (w withEndpoint) Apply(o *internal.DialSettings) {
|
||||
o.Endpoint = string(w)
|
||||
}
|
||||
|
||||
// WithScopes returns a ClientOption that overrides the default OAuth2 scopes
|
||||
// to be used for a service.
|
||||
func WithScopes(scope ...string) ClientOption {
|
||||
return withScopes(scope)
|
||||
}
|
||||
|
||||
type withScopes []string
|
||||
|
||||
func (w withScopes) Apply(o *internal.DialSettings) {
|
||||
o.Scopes = make([]string, len(w))
|
||||
copy(o.Scopes, w)
|
||||
}
|
||||
|
||||
// WithUserAgent returns a ClientOption that sets the User-Agent.
|
||||
func WithUserAgent(ua string) ClientOption {
|
||||
return withUA(ua)
|
||||
}
|
||||
|
||||
type withUA string
|
||||
|
||||
func (w withUA) Apply(o *internal.DialSettings) { o.UserAgent = string(w) }
|
||||
|
||||
// WithHTTPClient returns a ClientOption that specifies the HTTP client to use
|
||||
// as the basis of communications. This option may only be used with services
|
||||
// that support HTTP as their communication transport. When used, the
|
||||
// WithHTTPClient option takes precedent over all other supplied options.
|
||||
func WithHTTPClient(client *http.Client) ClientOption {
|
||||
return withHTTPClient{client}
|
||||
}
|
||||
|
||||
type withHTTPClient struct{ client *http.Client }
|
||||
|
||||
func (w withHTTPClient) Apply(o *internal.DialSettings) {
|
||||
o.HTTPClient = w.client
|
||||
}
|
||||
|
||||
// WithGRPCConn returns a ClientOption that specifies the gRPC client
|
||||
// connection to use as the basis of communications. This option many only be
|
||||
// used with services that support gRPC as their communication transport. When
|
||||
// used, the WithGRPCConn option takes precedent over all other supplied
|
||||
// options.
|
||||
func WithGRPCConn(conn *grpc.ClientConn) ClientOption {
|
||||
return withGRPCConn{conn}
|
||||
}
|
||||
|
||||
type withGRPCConn struct{ conn *grpc.ClientConn }
|
||||
|
||||
func (w withGRPCConn) Apply(o *internal.DialSettings) {
|
||||
o.GRPCConn = w.conn
|
||||
}
|
||||
|
||||
// WithGRPCDialOption returns a ClientOption that appends a new grpc.DialOption
|
||||
// to an underlying gRPC dial. It does not work with WithGRPCConn.
|
||||
func WithGRPCDialOption(opt grpc.DialOption) ClientOption {
|
||||
return withGRPCDialOption{opt}
|
||||
}
|
||||
|
||||
type withGRPCDialOption struct{ opt grpc.DialOption }
|
||||
|
||||
func (w withGRPCDialOption) Apply(o *internal.DialSettings) {
|
||||
o.GRPCDialOpts = append(o.GRPCDialOpts, w.opt)
|
||||
}
|
||||
|
||||
// WithGRPCConnectionPool returns a ClientOption that creates a pool of gRPC
|
||||
// connections that requests will be balanced between.
|
||||
// This is an EXPERIMENTAL API and may be changed or removed in the future.
|
||||
func WithGRPCConnectionPool(size int) ClientOption {
|
||||
return withGRPCConnectionPool(size)
|
||||
}
|
||||
|
||||
type withGRPCConnectionPool int
|
||||
|
||||
func (w withGRPCConnectionPool) Apply(o *internal.DialSettings) {
|
||||
balancer := grpc.RoundRobin(internal.NewPoolResolver(int(w), o))
|
||||
o.GRPCDialOpts = append(o.GRPCDialOpts, grpc.WithBalancer(balancer))
|
||||
}
|
||||
|
||||
// WithAPIKey returns a ClientOption that specifies an API key to be used
|
||||
// as the basis for authentication.
|
||||
//
|
||||
// API Keys can only be used for JSON-over-HTTP APIs, including those under
|
||||
// the import path google.golang.org/api/....
|
||||
func WithAPIKey(apiKey string) ClientOption {
|
||||
return withAPIKey(apiKey)
|
||||
}
|
||||
|
||||
type withAPIKey string
|
||||
|
||||
func (w withAPIKey) Apply(o *internal.DialSettings) { o.APIKey = string(w) }
|
||||
|
||||
// WithAudiences returns a ClientOption that specifies an audience to be used
|
||||
// as the audience field ("aud") for the JWT token authentication.
|
||||
func WithAudiences(audience ...string) ClientOption {
|
||||
return withAudiences(audience)
|
||||
}
|
||||
|
||||
type withAudiences []string
|
||||
|
||||
func (w withAudiences) Apply(o *internal.DialSettings) {
|
||||
o.Audiences = make([]string, len(w))
|
||||
copy(o.Audiences, w)
|
||||
}
|
||||
|
||||
// WithoutAuthentication returns a ClientOption that specifies that no
|
||||
// authentication should be used. It is suitable only for testing and for
|
||||
// accessing public resources, like public Google Cloud Storage buckets.
|
||||
// It is an error to provide both WithoutAuthentication and any of WithAPIKey,
|
||||
// WithTokenSource, WithCredentialsFile or WithServiceAccountFile.
|
||||
func WithoutAuthentication() ClientOption {
|
||||
return withoutAuthentication{}
|
||||
}
|
||||
|
||||
type withoutAuthentication struct{}
|
||||
|
||||
func (w withoutAuthentication) Apply(o *internal.DialSettings) { o.NoAuth = true }
|
||||
|
||||
// WithQuotaProject returns a ClientOption that specifies the project used
|
||||
// for quota and billing purposes.
|
||||
//
|
||||
// For more information please read:
|
||||
// https://cloud.google.com/apis/docs/system-parameters
|
||||
func WithQuotaProject(quotaProject string) ClientOption {
|
||||
return withQuotaProject(quotaProject)
|
||||
}
|
||||
|
||||
type withQuotaProject string
|
||||
|
||||
func (w withQuotaProject) Apply(o *internal.DialSettings) {
|
||||
o.QuotaProject = string(w)
|
||||
}
|
||||
|
||||
// WithRequestReason returns a ClientOption that specifies a reason for
|
||||
// making the request, which is intended to be recorded in audit logging.
|
||||
// An example reason would be a support-case ticket number.
|
||||
//
|
||||
// For more information please read:
|
||||
// https://cloud.google.com/apis/docs/system-parameters
|
||||
func WithRequestReason(requestReason string) ClientOption {
|
||||
return withRequestReason(requestReason)
|
||||
}
|
||||
|
||||
type withRequestReason string
|
||||
|
||||
func (w withRequestReason) Apply(o *internal.DialSettings) {
|
||||
o.RequestReason = string(w)
|
||||
}
|
4385
vendor/google.golang.org/api/storage/v1/storage-api.json
generated
vendored
Normal file
4385
vendor/google.golang.org/api/storage/v1/storage-api.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13266
vendor/google.golang.org/api/storage/v1/storage-gen.go
generated
vendored
Normal file
13266
vendor/google.golang.org/api/storage/v1/storage-gen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
161
vendor/google.golang.org/api/transport/http/dial.go
generated
vendored
Normal file
161
vendor/google.golang.org/api/transport/http/dial.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2015 Google LLC
|
||||
//
|
||||
// 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 http supports network connections to HTTP servers.
|
||||
// This package is not intended for use by end developers. Use the
|
||||
// google.golang.org/api/option package to configure API clients.
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"go.opencensus.io/plugin/ochttp"
|
||||
"golang.org/x/oauth2"
|
||||
"google.golang.org/api/googleapi/transport"
|
||||
"google.golang.org/api/internal"
|
||||
"google.golang.org/api/option"
|
||||
"google.golang.org/api/transport/http/internal/propagation"
|
||||
)
|
||||
|
||||
// NewClient returns an HTTP client for use communicating with a Google cloud
|
||||
// service, configured with the given ClientOptions. It also returns the endpoint
|
||||
// for the service as specified in the options.
|
||||
func NewClient(ctx context.Context, opts ...option.ClientOption) (*http.Client, string, error) {
|
||||
settings, err := newSettings(opts)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
// TODO(cbro): consider injecting the User-Agent even if an explicit HTTP client is provided?
|
||||
if settings.HTTPClient != nil {
|
||||
return settings.HTTPClient, settings.Endpoint, nil
|
||||
}
|
||||
trans, err := newTransport(ctx, defaultBaseTransport(ctx), settings)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return &http.Client{Transport: trans}, settings.Endpoint, nil
|
||||
}
|
||||
|
||||
// NewTransport creates an http.RoundTripper for use communicating with a Google
|
||||
// cloud service, configured with the given ClientOptions. Its RoundTrip method delegates to base.
|
||||
func NewTransport(ctx context.Context, base http.RoundTripper, opts ...option.ClientOption) (http.RoundTripper, error) {
|
||||
settings, err := newSettings(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if settings.HTTPClient != nil {
|
||||
return nil, errors.New("transport/http: WithHTTPClient passed to NewTransport")
|
||||
}
|
||||
return newTransport(ctx, base, settings)
|
||||
}
|
||||
|
||||
func newTransport(ctx context.Context, base http.RoundTripper, settings *internal.DialSettings) (http.RoundTripper, error) {
|
||||
trans := base
|
||||
trans = parameterTransport{
|
||||
base: trans,
|
||||
userAgent: settings.UserAgent,
|
||||
quotaProject: settings.QuotaProject,
|
||||
requestReason: settings.RequestReason,
|
||||
}
|
||||
trans = addOCTransport(trans)
|
||||
switch {
|
||||
case settings.NoAuth:
|
||||
// Do nothing.
|
||||
case settings.APIKey != "":
|
||||
trans = &transport.APIKey{
|
||||
Transport: trans,
|
||||
Key: settings.APIKey,
|
||||
}
|
||||
default:
|
||||
creds, err := internal.Creds(ctx, settings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trans = &oauth2.Transport{
|
||||
Base: trans,
|
||||
Source: creds.TokenSource,
|
||||
}
|
||||
}
|
||||
return trans, nil
|
||||
}
|
||||
|
||||
func newSettings(opts []option.ClientOption) (*internal.DialSettings, error) {
|
||||
var o internal.DialSettings
|
||||
for _, opt := range opts {
|
||||
opt.Apply(&o)
|
||||
}
|
||||
if err := o.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.GRPCConn != nil {
|
||||
return nil, errors.New("unsupported gRPC connection specified")
|
||||
}
|
||||
return &o, nil
|
||||
}
|
||||
|
||||
type parameterTransport struct {
|
||||
userAgent string
|
||||
quotaProject string
|
||||
requestReason string
|
||||
|
||||
base http.RoundTripper
|
||||
}
|
||||
|
||||
func (t parameterTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
rt := t.base
|
||||
if rt == nil {
|
||||
return nil, errors.New("transport: no Transport specified")
|
||||
}
|
||||
if t.userAgent == "" {
|
||||
return rt.RoundTrip(req)
|
||||
}
|
||||
newReq := *req
|
||||
newReq.Header = make(http.Header)
|
||||
for k, vv := range req.Header {
|
||||
newReq.Header[k] = vv
|
||||
}
|
||||
// TODO(cbro): append to existing User-Agent header?
|
||||
newReq.Header.Set("User-Agent", t.userAgent)
|
||||
|
||||
// Attach system parameters into the header
|
||||
if t.quotaProject != "" {
|
||||
newReq.Header.Set("X-Goog-User-Project", t.quotaProject)
|
||||
}
|
||||
if t.requestReason != "" {
|
||||
newReq.Header.Set("X-Goog-Request-Reason", t.requestReason)
|
||||
}
|
||||
|
||||
return rt.RoundTrip(&newReq)
|
||||
}
|
||||
|
||||
// Set at init time by dial_appengine.go. If nil, we're not on App Engine.
|
||||
var appengineUrlfetchHook func(context.Context) http.RoundTripper
|
||||
|
||||
// defaultBaseTransport returns the base HTTP transport.
|
||||
// On App Engine, this is urlfetch.Transport, otherwise it's http.DefaultTransport.
|
||||
func defaultBaseTransport(ctx context.Context) http.RoundTripper {
|
||||
if appengineUrlfetchHook != nil {
|
||||
return appengineUrlfetchHook(ctx)
|
||||
}
|
||||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
func addOCTransport(trans http.RoundTripper) http.RoundTripper {
|
||||
return &ochttp.Transport{
|
||||
Base: trans,
|
||||
Propagation: &propagation.HTTPFormat{},
|
||||
}
|
||||
}
|
30
vendor/google.golang.org/api/transport/http/dial_appengine.go
generated
vendored
Normal file
30
vendor/google.golang.org/api/transport/http/dial_appengine.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2016 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build appengine
|
||||
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"google.golang.org/appengine/urlfetch"
|
||||
)
|
||||
|
||||
func init() {
|
||||
appengineUrlfetchHook = func(ctx context.Context) http.RoundTripper {
|
||||
return &urlfetch.Transport{Context: ctx}
|
||||
}
|
||||
}
|
96
vendor/google.golang.org/api/transport/http/internal/propagation/http.go
generated
vendored
Normal file
96
vendor/google.golang.org/api/transport/http/internal/propagation/http.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
// Package propagation implements X-Cloud-Trace-Context header propagation used
|
||||
// by Google Cloud products.
|
||||
package propagation
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.opencensus.io/trace"
|
||||
"go.opencensus.io/trace/propagation"
|
||||
)
|
||||
|
||||
const (
|
||||
httpHeaderMaxSize = 200
|
||||
httpHeader = `X-Cloud-Trace-Context`
|
||||
)
|
||||
|
||||
var _ propagation.HTTPFormat = (*HTTPFormat)(nil)
|
||||
|
||||
// HTTPFormat implements propagation.HTTPFormat to propagate
|
||||
// traces in HTTP headers for Google Cloud Platform and Stackdriver Trace.
|
||||
type HTTPFormat struct{}
|
||||
|
||||
// SpanContextFromRequest extracts a Stackdriver Trace span context from incoming requests.
|
||||
func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) {
|
||||
h := req.Header.Get(httpHeader)
|
||||
// See https://cloud.google.com/trace/docs/faq for the header HTTPFormat.
|
||||
// Return if the header is empty or missing, or if the header is unreasonably
|
||||
// large, to avoid making unnecessary copies of a large string.
|
||||
if h == "" || len(h) > httpHeaderMaxSize {
|
||||
return trace.SpanContext{}, false
|
||||
}
|
||||
|
||||
// Parse the trace id field.
|
||||
slash := strings.Index(h, `/`)
|
||||
if slash == -1 {
|
||||
return trace.SpanContext{}, false
|
||||
}
|
||||
tid, h := h[:slash], h[slash+1:]
|
||||
|
||||
buf, err := hex.DecodeString(tid)
|
||||
if err != nil {
|
||||
return trace.SpanContext{}, false
|
||||
}
|
||||
copy(sc.TraceID[:], buf)
|
||||
|
||||
// Parse the span id field.
|
||||
spanstr := h
|
||||
semicolon := strings.Index(h, `;`)
|
||||
if semicolon != -1 {
|
||||
spanstr, h = h[:semicolon], h[semicolon+1:]
|
||||
}
|
||||
sid, err := strconv.ParseUint(spanstr, 10, 64)
|
||||
if err != nil {
|
||||
return trace.SpanContext{}, false
|
||||
}
|
||||
binary.BigEndian.PutUint64(sc.SpanID[:], sid)
|
||||
|
||||
// Parse the options field, options field is optional.
|
||||
if !strings.HasPrefix(h, "o=") {
|
||||
return sc, true
|
||||
}
|
||||
o, err := strconv.ParseUint(h[2:], 10, 64)
|
||||
if err != nil {
|
||||
return trace.SpanContext{}, false
|
||||
}
|
||||
sc.TraceOptions = trace.TraceOptions(o)
|
||||
return sc, true
|
||||
}
|
||||
|
||||
// SpanContextToRequest modifies the given request to include a Stackdriver Trace header.
|
||||
func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) {
|
||||
sid := binary.BigEndian.Uint64(sc.SpanID[:])
|
||||
header := fmt.Sprintf("%s/%d;o=%d", hex.EncodeToString(sc.TraceID[:]), sid, int64(sc.TraceOptions))
|
||||
req.Header.Set(httpHeader, header)
|
||||
}
|
Reference in New Issue
Block a user