vendor: github.com/prometheus/client_golang v1.12.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
985711c1f4
commit
ec47096efc
574 changed files with 101741 additions and 22828 deletions
1
vendor/google.golang.org/api/AUTHORS
generated
vendored
1
vendor/google.golang.org/api/AUTHORS
generated
vendored
|
@ -8,3 +8,4 @@
|
|||
|
||||
# Please keep the list sorted.
|
||||
Google Inc.
|
||||
LightStep Inc.
|
||||
|
|
6
vendor/google.golang.org/api/CONTRIBUTORS
generated
vendored
6
vendor/google.golang.org/api/CONTRIBUTORS
generated
vendored
|
@ -44,7 +44,13 @@ 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 Dolan <dolan@lightstep.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>
|
||||
|
|
46
vendor/google.golang.org/api/gensupport/backoff.go
generated
vendored
46
vendor/google.golang.org/api/gensupport/backoff.go
generated
vendored
|
@ -1,46 +0,0 @@
|
|||
// 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 (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BackoffStrategy interface {
|
||||
// Pause returns the duration of the next pause and true if the operation should be
|
||||
// retried, or false if no further retries should be attempted.
|
||||
Pause() (time.Duration, bool)
|
||||
|
||||
// Reset restores the strategy to its initial state.
|
||||
Reset()
|
||||
}
|
||||
|
||||
// ExponentialBackoff performs exponential backoff as per https://en.wikipedia.org/wiki/Exponential_backoff.
|
||||
// The initial pause time is given by Base.
|
||||
// Once the total pause time exceeds Max, Pause will indicate no further retries.
|
||||
type ExponentialBackoff struct {
|
||||
Base time.Duration
|
||||
Max time.Duration
|
||||
total time.Duration
|
||||
n uint
|
||||
}
|
||||
|
||||
func (eb *ExponentialBackoff) Pause() (time.Duration, bool) {
|
||||
if eb.total > eb.Max {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// The next pause is selected from randomly from [0, 2^n * Base).
|
||||
d := time.Duration(rand.Int63n((1 << eb.n) * int64(eb.Base)))
|
||||
eb.total += d
|
||||
eb.n++
|
||||
return d, true
|
||||
}
|
||||
|
||||
func (eb *ExponentialBackoff) Reset() {
|
||||
eb.n = 0
|
||||
eb.total = 0
|
||||
}
|
200
vendor/google.golang.org/api/gensupport/media.go
generated
vendored
200
vendor/google.golang.org/api/gensupport/media.go
generated
vendored
|
@ -1,200 +0,0 @@
|
|||
// 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 (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
|
||||
"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 creat 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
|
||||
pipeOpen bool
|
||||
ctype string
|
||||
}
|
||||
|
||||
func newMultipartReader(parts []typeReader) *multipartReader {
|
||||
mp := &multipartReader{pipeOpen: true}
|
||||
var pw *io.PipeWriter
|
||||
mp.pr, pw = io.Pipe()
|
||||
mpw := multipart.NewWriter(pw)
|
||||
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 {
|
||||
if !mp.pipeOpen {
|
||||
return nil
|
||||
}
|
||||
mp.pipeOpen = false
|
||||
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) {
|
||||
mp := newMultipartReader([]typeReader{
|
||||
{body, bodyContentType},
|
||||
{media, mediaContentType},
|
||||
})
|
||||
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 non-zero and the contents of media do not fit in a single
|
||||
// chunk (or there is an error reading media), then media will be returned as a
|
||||
// ResumableBuffer. Otherwise, media will be returned as a Reader.
|
||||
//
|
||||
// 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) (io.Reader,
|
||||
*ResumableBuffer) {
|
||||
if chunkSize == 0 { // do not chunk
|
||||
return media, nil
|
||||
}
|
||||
|
||||
rb := NewResumableBuffer(media, chunkSize)
|
||||
rdr, _, _, err := rb.Chunk()
|
||||
|
||||
if err == io.EOF { // we can upload this in a single request
|
||||
return rdr, nil
|
||||
}
|
||||
// err might be a non-EOF error. If it is, the next call to rb.Chunk will
|
||||
// return the same error. Returning a ResumableBuffer ensures that this error
|
||||
// will be handled at some point.
|
||||
|
||||
return nil, rb
|
||||
}
|
77
vendor/google.golang.org/api/gensupport/retry.go
generated
vendored
77
vendor/google.golang.org/api/gensupport/retry.go
generated
vendored
|
@ -1,77 +0,0 @@
|
|||
package gensupport
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Retry invokes the given function, retrying it multiple times if the connection failed or
|
||||
// the HTTP status response indicates the request should be attempted again. ctx may be nil.
|
||||
func Retry(ctx context.Context, f func() (*http.Response, error), backoff BackoffStrategy) (*http.Response, error) {
|
||||
for {
|
||||
resp, err := f()
|
||||
|
||||
var status int
|
||||
if resp != nil {
|
||||
status = resp.StatusCode
|
||||
}
|
||||
|
||||
// Return if we shouldn't retry.
|
||||
pause, retry := backoff.Pause()
|
||||
if !shouldRetry(status, err) || !retry {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Ensure the response body is closed, if any.
|
||||
if resp != nil && resp.Body != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
// Pause, but still listen to ctx.Done if context is not nil.
|
||||
var done <-chan struct{}
|
||||
if ctx != nil {
|
||||
done = ctx.Done()
|
||||
}
|
||||
select {
|
||||
case <-done:
|
||||
return nil, ctx.Err()
|
||||
case <-time.After(pause):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultBackoffStrategy returns a default strategy to use for retrying failed upload requests.
|
||||
func DefaultBackoffStrategy() BackoffStrategy {
|
||||
return &ExponentialBackoff{
|
||||
Base: 250 * time.Millisecond,
|
||||
Max: 16 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// shouldRetry returns true if the HTTP response / error indicates that the
|
||||
// request should be attempted again.
|
||||
func shouldRetry(status int, err error) bool {
|
||||
// Retry for 5xx response codes.
|
||||
if 500 <= status && status < 600 {
|
||||
return true
|
||||
}
|
||||
|
||||
// Retry on statusTooManyRequests{
|
||||
if status == statusTooManyRequests {
|
||||
return true
|
||||
}
|
||||
|
||||
// Retry on unexpected EOFs and temporary network errors.
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return true
|
||||
}
|
||||
if err, ok := err.(net.Error); ok {
|
||||
return err.Temporary()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
136
vendor/google.golang.org/api/googleapi/googleapi.go
generated
vendored
136
vendor/google.golang.org/api/googleapi/googleapi.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2011 Google Inc. All rights reserved.
|
||||
// Copyright 2011 Google LLC. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -16,7 +16,7 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/api/googleapi/internal/uritemplates"
|
||||
"google.golang.org/api/internal/third_party/uritemplates"
|
||||
)
|
||||
|
||||
// ContentTyper is an interface for Readers which know (or would like
|
||||
|
@ -37,24 +37,28 @@ type SizeReaderAt interface {
|
|||
// 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 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
|
||||
|
||||
// The default chunk size to use for resumable uplods if not specified by the user.
|
||||
DefaultUploadChunkSize = 8 * 1024 * 1024
|
||||
// DefaultUploadChunkSize is the default chunk size to use for resumable
|
||||
// uploads if not specified by the user.
|
||||
DefaultUploadChunkSize = 16 * 1024 * 1024
|
||||
|
||||
// The minimum chunk size that can be used for resumable uploads. All
|
||||
// user-specified chunk sizes must be multiple of this value.
|
||||
// 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
|
||||
)
|
||||
|
||||
|
@ -65,6 +69,8 @@ type Error struct {
|
|||
// Message is the server response message and is only populated when
|
||||
// explicitly referenced by the JSON server response.
|
||||
Message string `json:"message"`
|
||||
// Details provide more context to an error.
|
||||
Details []interface{} `json:"details"`
|
||||
// Body is the raw response returned by the server.
|
||||
// It is often but not always JSON, depending on how the request fails.
|
||||
Body string
|
||||
|
@ -91,6 +97,16 @@ func (e *Error) Error() string {
|
|||
if e.Message != "" {
|
||||
fmt.Fprintf(&buf, "%s", e.Message)
|
||||
}
|
||||
if len(e.Details) > 0 {
|
||||
var detailBuf bytes.Buffer
|
||||
enc := json.NewEncoder(&detailBuf)
|
||||
enc.SetIndent("", " ")
|
||||
if err := enc.Encode(e.Details); err == nil {
|
||||
fmt.Fprint(&buf, "\nDetails:")
|
||||
fmt.Fprintf(&buf, "\n%s", detailBuf.String())
|
||||
|
||||
}
|
||||
}
|
||||
if len(e.Errors) == 0 {
|
||||
return strings.TrimSpace(buf.String())
|
||||
}
|
||||
|
@ -149,21 +165,25 @@ func IsNotModified(err error) bool {
|
|||
// 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))
|
||||
res.Body.Close()
|
||||
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) {
|
||||
|
@ -181,37 +201,12 @@ func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) {
|
|||
return buf, nil
|
||||
}
|
||||
|
||||
// endingWithErrorReader from r until it returns an error. If the
|
||||
// final error from r is io.EOF and e is non-nil, e is used instead.
|
||||
type endingWithErrorReader struct {
|
||||
r io.Reader
|
||||
e error
|
||||
}
|
||||
|
||||
func (er endingWithErrorReader) Read(p []byte) (n int, err error) {
|
||||
n, err = er.r.Read(p)
|
||||
if err == io.EOF && er.e != nil {
|
||||
err = er.e
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// countingWriter counts the number of bytes it receives to write, but
|
||||
// discards them.
|
||||
type countingWriter struct {
|
||||
n *int64
|
||||
}
|
||||
|
||||
func (w countingWriter) Write(p []byte) (int, error) {
|
||||
*w.n += int64(len(p))
|
||||
return len(p), 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)
|
||||
}
|
||||
|
@ -268,51 +263,47 @@ func ProcessMediaOptions(opts []MediaOption) *MediaOptions {
|
|||
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).
|
||||
//
|
||||
// ResolveRelative panics if either basestr or relstr is not able to be parsed.
|
||||
func ResolveRelative(basestr, relstr string) string {
|
||||
u, _ := url.Parse(basestr)
|
||||
rel, _ := url.Parse(relstr)
|
||||
u, err := url.Parse(basestr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to parse %q", basestr))
|
||||
}
|
||||
afterColonPath := ""
|
||||
if i := strings.IndexRune(relstr, ':'); i > 0 {
|
||||
afterColonPath = relstr[i+1:]
|
||||
relstr = relstr[:i]
|
||||
}
|
||||
rel, err := url.Parse(relstr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to parse %q", 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
|
||||
}
|
||||
|
||||
// has4860Fix is whether this Go environment contains the fix for
|
||||
// http://golang.org/issue/4860
|
||||
var has4860Fix bool
|
||||
|
||||
// init initializes has4860Fix by checking the behavior of the net/http package.
|
||||
func init() {
|
||||
r := http.Request{
|
||||
URL: &url.URL{
|
||||
Scheme: "http",
|
||||
Opaque: "//opaque",
|
||||
},
|
||||
}
|
||||
b := &bytes.Buffer{}
|
||||
r.Write(b)
|
||||
has4860Fix = bytes.HasPrefix(b.Bytes(), []byte("GET http"))
|
||||
}
|
||||
|
||||
// SetOpaque sets u.Opaque from u.Path such that HTTP requests to it
|
||||
// don't alter any hex-escaped characters in u.Path.
|
||||
func SetOpaque(u *url.URL) {
|
||||
u.Opaque = "//" + u.Host + u.Path
|
||||
if !has4860Fix {
|
||||
u.Opaque = u.Scheme + ":" + u.Opaque
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
expanded, err := uritemplates.Expand(u.Path, expansions)
|
||||
escaped, unescaped, err := uritemplates.Expand(u.Path, expansions)
|
||||
if err == nil {
|
||||
u.Path = expanded
|
||||
SetOpaque(u)
|
||||
u.Path = unescaped
|
||||
u.RawPath = escaped
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,7 +351,7 @@ func ConvertVariant(v map[string]interface{}, dst interface{}) bool {
|
|||
}
|
||||
|
||||
// A Field names a field to be retrieved with a partial response.
|
||||
// See https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
|
||||
// https://cloud.google.com/storage/docs/json_api/v1/how-tos/performance
|
||||
//
|
||||
// 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
|
||||
|
@ -377,9 +368,6 @@ func ConvertVariant(v map[string]interface{}, dst interface{}) bool {
|
|||
//
|
||||
// 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
|
||||
|
@ -421,4 +409,12 @@ 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
18
vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE
generated
vendored
|
@ -1,18 +0,0 @@
|
|||
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.
|
13
vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go
generated
vendored
13
vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go
generated
vendored
|
@ -1,13 +0,0 @@
|
|||
// 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
|
||||
|
||||
func Expand(path string, values map[string]string) (string, error) {
|
||||
template, err := parse(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return template.Expand(values), nil
|
||||
}
|
44
vendor/google.golang.org/api/googleapi/transport/apikey.go
generated
vendored
Normal file
44
vendor/google.golang.org/api/googleapi/transport/apikey.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2012 Google LLC. 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.
|
||||
//
|
||||
// This package is DEPRECATED. Users should instead use,
|
||||
//
|
||||
// service, err := NewService(..., option.WithAPIKey(...))
|
||||
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.
|
||||
//
|
||||
// Deprecated: please use NewService(..., option.WithAPIKey(...)) instead.
|
||||
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)
|
||||
}
|
52
vendor/google.golang.org/api/googleapi/types.go
generated
vendored
52
vendor/google.golang.org/api/googleapi/types.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2013 Google Inc. All rights reserved.
|
||||
// Copyright 2013 Google LLC. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -6,6 +6,7 @@ package googleapi
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
@ -119,36 +120,55 @@ func quotedList(n int, fn func(dst []byte, i int) []byte) ([]byte, error) {
|
|||
return dst, nil
|
||||
}
|
||||
|
||||
func (s Int64s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(s), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendInt(dst, s[i], 10)
|
||||
func (q Int64s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(q), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendInt(dst, q[i], 10)
|
||||
})
|
||||
}
|
||||
|
||||
func (s Int32s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(s), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendInt(dst, int64(s[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 (s Uint64s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(s), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendUint(dst, s[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 (s Uint32s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(s), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendUint(dst, uint64(s[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 (s Float64s) MarshalJSON() ([]byte, error) {
|
||||
return quotedList(len(s), func(dst []byte, i int) []byte {
|
||||
return strconv.AppendFloat(dst, s[i], 'g', -1, 64)
|
||||
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.
|
||||
*/
|
||||
|
|
30
vendor/google.golang.org/api/internal/conn_pool.go
generated
vendored
Normal file
30
vendor/google.golang.org/api/internal/conn_pool.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2020 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// ConnPool is a pool of grpc.ClientConns.
|
||||
type ConnPool interface {
|
||||
// Conn returns a ClientConn from the pool.
|
||||
//
|
||||
// Conns aren't returned to the pool.
|
||||
Conn() *grpc.ClientConn
|
||||
|
||||
// Num returns the number of connections in the pool.
|
||||
//
|
||||
// It will always return the same value.
|
||||
Num() int
|
||||
|
||||
// Close closes every ClientConn in the pool.
|
||||
//
|
||||
// The error returned by Close may be a single error or multiple errors.
|
||||
Close() error
|
||||
|
||||
// ConnPool implements grpc.ClientConnInterface to enable it to be used directly with generated proto stubs.
|
||||
grpc.ClientConnInterface
|
||||
}
|
105
vendor/google.golang.org/api/internal/creds.go
generated
vendored
Normal file
105
vendor/google.golang.org/api/internal/creds.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2017 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// QuotaProjectFromCreds returns the quota project from the JSON blob in the provided credentials.
|
||||
//
|
||||
// NOTE(cbro): consider promoting this to a field on google.Credentials.
|
||||
func QuotaProjectFromCreds(cred *google.Credentials) string {
|
||||
var v struct {
|
||||
QuotaProject string `json:"quota_project_id"`
|
||||
}
|
||||
if err := json.Unmarshal(cred.JSON, &v); err != nil {
|
||||
return ""
|
||||
}
|
||||
return v.QuotaProject
|
||||
}
|
|
@ -11,8 +11,9 @@ import (
|
|||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
// ResumableBuffer buffers data from an io.Reader to support uploading media in retryable chunks.
|
||||
type ResumableBuffer struct {
|
||||
// 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.
|
||||
|
@ -22,42 +23,43 @@ type ResumableBuffer struct {
|
|||
off int64
|
||||
}
|
||||
|
||||
func NewResumableBuffer(media io.Reader, chunkSize int) *ResumableBuffer {
|
||||
return &ResumableBuffer{media: media, chunk: make([]byte, 0, chunkSize)}
|
||||
// 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 (rb *ResumableBuffer) Chunk() (chunk io.Reader, off int64, size int, err error) {
|
||||
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 rb.err == nil && len(rb.chunk) == 0 {
|
||||
rb.err = rb.loadChunk()
|
||||
if mb.err == nil && len(mb.chunk) == 0 {
|
||||
mb.err = mb.loadChunk()
|
||||
}
|
||||
return bytes.NewReader(rb.chunk), rb.off, len(rb.chunk), rb.err
|
||||
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 (rb *ResumableBuffer) loadChunk() error {
|
||||
bufSize := cap(rb.chunk)
|
||||
rb.chunk = rb.chunk[:bufSize]
|
||||
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 = rb.media.Read(rb.chunk[read:])
|
||||
n, err = mb.media.Read(mb.chunk[read:])
|
||||
read += n
|
||||
}
|
||||
rb.chunk = rb.chunk[:read]
|
||||
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 (rb *ResumableBuffer) Next() {
|
||||
rb.off += int64(len(rb.chunk))
|
||||
rb.chunk = rb.chunk[0:0]
|
||||
func (mb *MediaBuffer) Next() {
|
||||
mb.off += int64(len(mb.chunk))
|
||||
mb.chunk = mb.chunk[0:0]
|
||||
}
|
||||
|
||||
type readerTyper struct {
|
|
@ -12,29 +12,43 @@ import (
|
|||
)
|
||||
|
||||
// MarshalJSON returns a JSON encoding of schema containing only selected fields.
|
||||
// A field is selected if:
|
||||
// * it has a non-empty value, or
|
||||
// * its field name is present in forceSendFields, and
|
||||
// * it is not a nil pointer or nil interface.
|
||||
// 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 []string) ([]byte, error) {
|
||||
if len(forceSendFields) == 0 {
|
||||
func MarshalJSON(schema interface{}, forceSendFields, nullFields []string) ([]byte, error) {
|
||||
if len(forceSendFields) == 0 && len(nullFields) == 0 {
|
||||
return json.Marshal(schema)
|
||||
}
|
||||
|
||||
mustInclude := make(map[string]struct{})
|
||||
mustInclude := make(map[string]bool)
|
||||
for _, f := range forceSendFields {
|
||||
mustInclude[f] = struct{}{}
|
||||
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)
|
||||
dataMap, err := schemaToMap(schema, mustInclude, useNull, useNullMaps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(dataMap)
|
||||
}
|
||||
|
||||
func schemaToMap(schema interface{}, mustInclude map[string]struct{}) (map[string]interface{}, error) {
|
||||
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()
|
||||
|
@ -54,10 +68,36 @@ func schemaToMap(schema interface{}, mustInclude map[string]struct{}) (map[strin
|
|||
|
||||
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{}
|
||||
|
@ -127,7 +167,7 @@ func parseJSONTag(val string) (jsonTag, error) {
|
|||
}
|
||||
|
||||
// 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]struct{}) bool {
|
||||
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.
|
||||
|
@ -144,8 +184,7 @@ func includeField(v reflect.Value, f reflect.StructField, mustInclude map[string
|
|||
return false
|
||||
}
|
||||
|
||||
_, ok := mustInclude[f.Name]
|
||||
return ok || !isEmptyValue(v)
|
||||
return mustInclude[f.Name] || !isEmptyValue(v)
|
||||
}
|
||||
|
||||
// isEmptyValue reports whether v is the empty value for its type. This
|
47
vendor/google.golang.org/api/internal/gensupport/jsonfloat.go
generated
vendored
Normal file
47
vendor/google.golang.org/api/internal/gensupport/jsonfloat.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2016 Google LLC.
|
||||
// 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"
|
||||
"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")
|
||||
}
|
372
vendor/google.golang.org/api/internal/gensupport/media.go
generated
vendored
Normal file
372
vendor/google.golang.org/api/internal/gensupport/media.go
generated
vendored
Normal file
|
@ -0,0 +1,372 @@
|
|||
// 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)
|
||||
toCleanup := []io.Closer{
|
||||
combined,
|
||||
}
|
||||
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)
|
||||
toCleanup = append(toCleanup, r)
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
cleanup = func() {
|
||||
for _, closer := range toCleanup {
|
||||
_ = closer.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
|
||||
}
|
|
@ -43,6 +43,7 @@ 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())
|
|
@ -5,21 +5,34 @@
|
|||
package gensupport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
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}
|
||||
}
|
||||
// isRetryable is a platform-specific hook, specified in retryable_linux.go
|
||||
syscallRetryable func(error) bool = func(err error) bool { return false }
|
||||
)
|
||||
|
||||
const (
|
||||
// statusResumeIncomplete is the code returned by the Google uploader
|
||||
// when the transfer is not yet complete.
|
||||
statusResumeIncomplete = 308
|
||||
|
||||
// statusTooManyRequests is returned by the storage API if the
|
||||
// per-project limits have been temporarily exceeded. The request
|
||||
// should be retried.
|
||||
|
@ -35,7 +48,7 @@ type ResumableUpload struct {
|
|||
URI string
|
||||
UserAgent string // User-Agent for header of the request
|
||||
// Media is the object being uploaded.
|
||||
Media *ResumableBuffer
|
||||
Media *MediaBuffer
|
||||
// MediaType defines the media type, e.g. "image/jpeg".
|
||||
MediaType string
|
||||
|
||||
|
@ -44,9 +57,6 @@ type ResumableUpload struct {
|
|||
|
||||
// Callback is an optional function that will be periodically called with the cumulative number of bytes uploaded.
|
||||
Callback func(int64)
|
||||
|
||||
// If not specified, a default exponential backoff strategy will be used.
|
||||
Backoff BackoffStrategy
|
||||
}
|
||||
|
||||
// Progress returns the number of bytes uploaded at this point.
|
||||
|
@ -80,8 +90,23 @@ func (rx *ResumableUpload) doUploadRequest(ctx context.Context, data io.Reader,
|
|||
req.Header.Set("Content-Range", contentRange)
|
||||
req.Header.Set("Content-Type", rx.MediaType)
|
||||
req.Header.Set("User-Agent", rx.UserAgent)
|
||||
return ctxhttp.Do(ctx, rx.Client, req)
|
||||
|
||||
// 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.
|
||||
|
@ -112,87 +137,122 @@ func (rx *ResumableUpload) transferChunk(ctx context.Context) (*http.Response, e
|
|||
return res, err
|
||||
}
|
||||
|
||||
if res.StatusCode == statusResumeIncomplete || res.StatusCode == http.StatusOK {
|
||||
// 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 res.StatusCode == statusResumeIncomplete {
|
||||
if statusResumeIncomplete(res) {
|
||||
rx.Media.Next()
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func contextDone(ctx context.Context) bool {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 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 pause time.Duration
|
||||
backoff := rx.Backoff
|
||||
if backoff == nil {
|
||||
backoff = DefaultBackoffStrategy()
|
||||
}
|
||||
|
||||
for {
|
||||
// Ensure that we return in the case of cancelled context, even if pause is 0.
|
||||
if contextDone(ctx) {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case <-time.After(pause):
|
||||
}
|
||||
|
||||
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) {
|
||||
var retry bool
|
||||
pause, retry = backoff.Pause()
|
||||
if retry {
|
||||
if resp != nil && resp.Body != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If the chunk was uploaded successfully, but there's still
|
||||
// more to go, upload the next chunk without any delay.
|
||||
if status == statusResumeIncomplete {
|
||||
pause = 0
|
||||
backoff.Reset()
|
||||
resp.Body.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
// It's possible for err and resp to both be non-nil here, but 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.
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
// shouldRetry indicates whether an error is retryable for the purposes of this
|
||||
// package, following guidance from
|
||||
// https://cloud.google.com/storage/docs/exponential-backoff .
|
||||
func shouldRetry(status int, err error) bool {
|
||||
if 500 <= status && status <= 599 {
|
||||
return true
|
||||
}
|
||||
if status == statusTooManyRequests {
|
||||
return true
|
||||
}
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return true
|
||||
}
|
||||
// Transient network errors should be retried.
|
||||
if syscallRetryable(err) {
|
||||
return true
|
||||
}
|
||||
if err, ok := err.(interface{ Temporary() bool }); ok {
|
||||
if err.Temporary() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// If Go 1.13 error unwrapping is available, use this to examine wrapped
|
||||
// errors.
|
||||
if err, ok := err.(interface{ Unwrap() error }); ok {
|
||||
return shouldRetry(status, err.Unwrap())
|
||||
}
|
||||
return false
|
||||
}
|
15
vendor/google.golang.org/api/internal/gensupport/retryable_linux.go
generated
vendored
Normal file
15
vendor/google.golang.org/api/internal/gensupport/retryable_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2020 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux
|
||||
|
||||
package gensupport
|
||||
|
||||
import "syscall"
|
||||
|
||||
func init() {
|
||||
// Initialize syscallRetryable to return true on transient socket-level
|
||||
// errors. These errors are specific to Linux.
|
||||
syscallRetryable = func(err error) bool { return err == syscall.ECONNRESET || err == syscall.ECONNREFUSED }
|
||||
}
|
172
vendor/google.golang.org/api/internal/gensupport/send.go
generated
vendored
Normal file
172
vendor/google.golang.org/api/internal/gensupport/send.go
generated
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
// 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"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// SendRequestWithRetry sends a single HTTP request using the given client,
|
||||
// with retries if a retryable error is returned.
|
||||
// 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 SendRequestWithRetry(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 with retry.
|
||||
resp, err := sendAndRetry(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 sendAndRetry(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
||||
if client == nil {
|
||||
client = http.DefaultClient
|
||||
}
|
||||
|
||||
var resp *http.Response
|
||||
var err error
|
||||
|
||||
// Loop to retry the request, up to the context deadline.
|
||||
var pause time.Duration
|
||||
bo := backoff()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// If we got an error, and the context has been canceled,
|
||||
// the context's error is probably more useful.
|
||||
if err == nil {
|
||||
err = ctx.Err()
|
||||
}
|
||||
return resp, err
|
||||
case <-time.After(pause):
|
||||
}
|
||||
|
||||
resp, err = client.Do(req.WithContext(ctx))
|
||||
|
||||
var status int
|
||||
if resp != nil {
|
||||
status = resp.StatusCode
|
||||
}
|
||||
|
||||
// Check if we can retry the request. A retry can only be done if the error
|
||||
// is retryable and the request body can be re-created using GetBody (this
|
||||
// will not be possible if the body was unbuffered).
|
||||
if req.GetBody == nil || !shouldRetry(status, err) {
|
||||
break
|
||||
}
|
||||
var errBody error
|
||||
req.Body, errBody = req.GetBody()
|
||||
if errBody != nil {
|
||||
break
|
||||
}
|
||||
|
||||
pause = bo.Pause()
|
||||
if resp != nil && resp.Body != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
53
vendor/google.golang.org/api/internal/gensupport/version.go
generated
vendored
Normal file
53
vendor/google.golang.org/api/internal/gensupport/version.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2020 Google LLC. 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 (
|
||||
"runtime"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// GoVersion returns the Go runtime version. The returned string
|
||||
// has no whitespace.
|
||||
func GoVersion() string {
|
||||
return goVersion
|
||||
}
|
||||
|
||||
var goVersion = goVer(runtime.Version())
|
||||
|
||||
const develPrefix = "devel +"
|
||||
|
||||
func goVer(s string) string {
|
||||
if strings.HasPrefix(s, develPrefix) {
|
||||
s = s[len(develPrefix):]
|
||||
if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
|
||||
s = s[:p]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
if strings.HasPrefix(s, "go1") {
|
||||
s = s[2:]
|
||||
var prerelease string
|
||||
if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
|
||||
s, prerelease = s[:p], s[p:]
|
||||
}
|
||||
if strings.HasSuffix(s, ".") {
|
||||
s += "0"
|
||||
} else if strings.Count(s, ".") < 2 {
|
||||
s += ".0"
|
||||
}
|
||||
if prerelease != "" {
|
||||
s += "-" + prerelease
|
||||
}
|
||||
return s
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func notSemverRune(r rune) bool {
|
||||
return !strings.ContainsRune("0123456789.", r)
|
||||
}
|
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"
|
||||
}
|
110
vendor/google.golang.org/api/internal/settings.go
generated
vendored
Normal file
110
vendor/google.golang.org/api/internal/settings.go
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
// Copyright 2017 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package internal supports the options and transport packages.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"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
|
||||
DefaultEndpoint string
|
||||
DefaultMTLSEndpoint 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
|
||||
GRPCConnPool ConnPool
|
||||
GRPCConnPoolSize int
|
||||
NoAuth bool
|
||||
TelemetryDisabled bool
|
||||
ClientCertSource func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
|
||||
CustomClaims map[string]interface{}
|
||||
SkipValidation 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 {
|
||||
if ds.SkipValidation {
|
||||
return nil
|
||||
}
|
||||
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.GRPCConn != nil && ds.GRPCConnPool != nil {
|
||||
return errors.New("WithGRPCConn is incompatible with WithConnPool")
|
||||
}
|
||||
if ds.HTTPClient != nil && ds.GRPCConnPool != nil {
|
||||
return errors.New("WithHTTPClient is incompatible with WithConnPool")
|
||||
}
|
||||
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")
|
||||
}
|
||||
if ds.HTTPClient != nil && ds.ClientCertSource != nil {
|
||||
return errors.New("WithHTTPClient is incompatible with WithClientCertSource")
|
||||
}
|
||||
if ds.ClientCertSource != nil && (ds.GRPCConn != nil || ds.GRPCConnPool != nil || ds.GRPCConnPoolSize != 0 || ds.GRPCDialOpts != nil) {
|
||||
return errors.New("WithClientCertSource is currently only supported for HTTP. gRPC settings are incompatible")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
27
vendor/google.golang.org/api/internal/third_party/uritemplates/LICENSE
generated
vendored
Normal file
27
vendor/google.golang.org/api/internal/third_party/uritemplates/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2013 Joshua Tacoma. 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.
|
14
vendor/google.golang.org/api/internal/third_party/uritemplates/METADATA
generated
vendored
Normal file
14
vendor/google.golang.org/api/internal/third_party/uritemplates/METADATA
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
name: "uritemplates"
|
||||
description:
|
||||
"Package uritemplates is a level 4 implementation of RFC 6570 (URI "
|
||||
"Template, http://tools.ietf.org/html/rfc6570)."
|
||||
|
||||
third_party {
|
||||
url {
|
||||
type: GIT
|
||||
value: "https://github.com/jtacoma/uritemplates"
|
||||
}
|
||||
version: "0.1"
|
||||
last_upgrade_date { year: 2014 month: 8 day: 18 }
|
||||
license_type: NOTICE
|
||||
}
|
|
@ -34,11 +34,37 @@ func pctEncode(src []byte) []byte {
|
|||
return dst
|
||||
}
|
||||
|
||||
func escape(s string, allowReserved bool) string {
|
||||
// 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 {
|
||||
return string(reserved.ReplaceAllFunc([]byte(s), pctEncode))
|
||||
w.escaped.Write(reserved.ReplaceAllFunc([]byte(s), pctEncode))
|
||||
} else {
|
||||
w.escaped.Write(unreserved.ReplaceAllFunc([]byte(s), pctEncode))
|
||||
}
|
||||
return string(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.
|
||||
|
@ -165,23 +191,25 @@ func parseTerm(term string) (result templateTerm, err error) {
|
|||
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")
|
||||
err = errors.New("both explode and prefix modifiers on same term")
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Expand expands a URI template with a set of values to produce a string.
|
||||
func (t *uriTemplate) Expand(values map[string]string) string {
|
||||
var buf bytes.Buffer
|
||||
// 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(&buf, values)
|
||||
p.expand(&w, values)
|
||||
}
|
||||
return buf.String()
|
||||
return w.Escaped(), w.Unescaped()
|
||||
}
|
||||
|
||||
func (tp *templatePart) expand(buf *bytes.Buffer, values map[string]string) {
|
||||
func (tp *templatePart) expand(w *pairWriter, values map[string]string) {
|
||||
if len(tp.raw) > 0 {
|
||||
buf.WriteString(tp.raw)
|
||||
w.Write(tp.raw)
|
||||
return
|
||||
}
|
||||
var first = true
|
||||
|
@ -191,30 +219,30 @@ func (tp *templatePart) expand(buf *bytes.Buffer, values map[string]string) {
|
|||
continue
|
||||
}
|
||||
if first {
|
||||
buf.WriteString(tp.first)
|
||||
w.Write(tp.first)
|
||||
first = false
|
||||
} else {
|
||||
buf.WriteString(tp.sep)
|
||||
w.Write(tp.sep)
|
||||
}
|
||||
tp.expandString(buf, term, value)
|
||||
tp.expandString(w, term, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *templatePart) expandName(buf *bytes.Buffer, name string, empty bool) {
|
||||
func (tp *templatePart) expandName(w *pairWriter, name string, empty bool) {
|
||||
if tp.named {
|
||||
buf.WriteString(name)
|
||||
w.Write(name)
|
||||
if empty {
|
||||
buf.WriteString(tp.ifemp)
|
||||
w.Write(tp.ifemp)
|
||||
} else {
|
||||
buf.WriteString("=")
|
||||
w.Write("=")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *templatePart) expandString(buf *bytes.Buffer, t templateTerm, s string) {
|
||||
func (tp *templatePart) expandString(w *pairWriter, t templateTerm, s string) {
|
||||
if len(s) > t.truncate && t.truncate > 0 {
|
||||
s = s[:t.truncate]
|
||||
}
|
||||
tp.expandName(buf, t.name, len(s) == 0)
|
||||
buf.WriteString(escape(s, tp.allowReserved))
|
||||
tp.expandName(w, t.name, len(s) == 0)
|
||||
w.Escape(s, tp.allowReserved)
|
||||
}
|
17
vendor/google.golang.org/api/internal/third_party/uritemplates/utils.go
generated
vendored
Normal file
17
vendor/google.golang.org/api/internal/third_party/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
|
||||
}
|
23
vendor/google.golang.org/api/option/credentials_go19.go
generated
vendored
Normal file
23
vendor/google.golang.org/api/option/credentials_go19.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2018 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +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)
|
||||
}
|
22
vendor/google.golang.org/api/option/credentials_notgo19.go
generated
vendored
Normal file
22
vendor/google.golang.org/api/option/credentials_notgo19.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2018 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +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)
|
||||
}
|
52
vendor/google.golang.org/api/option/internaloption/internaloption.go
generated
vendored
Normal file
52
vendor/google.golang.org/api/option/internaloption/internaloption.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2020 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package internaloption contains options used internally by Google client code.
|
||||
package internaloption
|
||||
|
||||
import (
|
||||
"google.golang.org/api/internal"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
type defaultEndpointOption string
|
||||
|
||||
func (o defaultEndpointOption) Apply(settings *internal.DialSettings) {
|
||||
settings.DefaultEndpoint = string(o)
|
||||
}
|
||||
|
||||
// WithDefaultEndpoint is an option that indicates the default endpoint.
|
||||
//
|
||||
// It should only be used internally by generated clients.
|
||||
//
|
||||
// This is similar to WithEndpoint, but allows us to determine whether the user has overriden the default endpoint.
|
||||
func WithDefaultEndpoint(url string) option.ClientOption {
|
||||
return defaultEndpointOption(url)
|
||||
}
|
||||
|
||||
type defaultMTLSEndpointOption string
|
||||
|
||||
func (o defaultMTLSEndpointOption) Apply(settings *internal.DialSettings) {
|
||||
settings.DefaultMTLSEndpoint = string(o)
|
||||
}
|
||||
|
||||
// WithDefaultMTLSEndpoint is an option that indicates the default mTLS endpoint.
|
||||
//
|
||||
// It should only be used internally by generated clients.
|
||||
func WithDefaultMTLSEndpoint(url string) option.ClientOption {
|
||||
return defaultMTLSEndpointOption(url)
|
||||
}
|
||||
|
||||
// SkipDialSettingsValidation bypasses validation on ClientOptions.
|
||||
//
|
||||
// It should only be used internally.
|
||||
func SkipDialSettingsValidation() option.ClientOption {
|
||||
return skipDialSettingsValidation{}
|
||||
}
|
||||
|
||||
type skipDialSettingsValidation struct{}
|
||||
|
||||
func (s skipDialSettingsValidation) Apply(settings *internal.DialSettings) {
|
||||
settings.SkipValidation = true
|
||||
}
|
271
vendor/google.golang.org/api/option/option.go
generated
vendored
Normal file
271
vendor/google.golang.org/api/option/option.go
generated
vendored
Normal file
|
@ -0,0 +1,271 @@
|
|||
// Copyright 2017 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package option contains options for Google API clients.
|
||||
package option
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"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 may 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) {
|
||||
o.GRPCConnPoolSize = int(w)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// WithTelemetryDisabled returns a ClientOption that disables default telemetry (OpenCensus)
|
||||
// settings on gRPC and HTTP clients.
|
||||
// An example reason would be to bind custom telemetry that overrides the defaults.
|
||||
func WithTelemetryDisabled() ClientOption {
|
||||
return withTelemetryDisabled{}
|
||||
}
|
||||
|
||||
type withTelemetryDisabled struct{}
|
||||
|
||||
func (w withTelemetryDisabled) Apply(o *internal.DialSettings) {
|
||||
o.TelemetryDisabled = true
|
||||
}
|
||||
|
||||
// ClientCertSource is a function that returns a TLS client certificate to be used
|
||||
// when opening TLS connections.
|
||||
//
|
||||
// It follows the same semantics as crypto/tls.Config.GetClientCertificate.
|
||||
//
|
||||
// This is an EXPERIMENTAL API and may be changed or removed in the future.
|
||||
type ClientCertSource = func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
|
||||
|
||||
// WithClientCertSource returns a ClientOption that specifies a
|
||||
// callback function for obtaining a TLS client certificate.
|
||||
//
|
||||
// This option is used for supporting mTLS authentication, where the
|
||||
// server validates the client certifcate when establishing a connection.
|
||||
//
|
||||
// The callback function will be invoked whenever the server requests a
|
||||
// certificate from the client. Implementations of the callback function
|
||||
// should try to ensure that a valid certificate can be repeatedly returned
|
||||
// on demand for the entire life cycle of the transport client. If a nil
|
||||
// Certificate is returned (i.e. no Certificate can be obtained), an error
|
||||
// should be returned.
|
||||
//
|
||||
// This is an EXPERIMENTAL API and may be changed or removed in the future.
|
||||
func WithClientCertSource(s ClientCertSource) ClientOption {
|
||||
return withClientCertSource{s}
|
||||
}
|
||||
|
||||
type withClientCertSource struct{ s ClientCertSource }
|
||||
|
||||
func (w withClientCertSource) Apply(o *internal.DialSettings) {
|
||||
o.ClientCertSource = w.s
|
||||
}
|
7298
vendor/google.golang.org/api/storage/v1/storage-api.json
generated
vendored
7298
vendor/google.golang.org/api/storage/v1/storage-api.json
generated
vendored
File diff suppressed because it is too large
Load diff
7017
vendor/google.golang.org/api/storage/v1/storage-gen.go
generated
vendored
7017
vendor/google.golang.org/api/storage/v1/storage-gen.go
generated
vendored
File diff suppressed because it is too large
Load diff
110
vendor/google.golang.org/api/transport/cert/default_cert.go
generated
vendored
Normal file
110
vendor/google.golang.org/api/transport/cert/default_cert.go
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
// Copyright 2020 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package cert contains certificate tools for Google API clients.
|
||||
// This package is intended to be used with crypto/tls.Config.GetClientCertificate.
|
||||
//
|
||||
// The certificates can be used to satisfy Google's Endpoint Validation.
|
||||
// See https://cloud.google.com/endpoint-verification/docs/overview
|
||||
//
|
||||
// This package is not intended for use by end developers. Use the
|
||||
// google.golang.org/api/option package to configure API clients.
|
||||
package cert
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
metadataPath = ".secureConnect"
|
||||
metadataFile = "context_aware_metadata.json"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultSourceOnce sync.Once
|
||||
defaultSource Source
|
||||
defaultSourceErr error
|
||||
)
|
||||
|
||||
// Source is a function that can be passed into crypto/tls.Config.GetClientCertificate.
|
||||
type Source func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
|
||||
|
||||
// DefaultSource returns a certificate source that execs the command specified
|
||||
// in the file at ~/.secureConnect/context_aware_metadata.json
|
||||
//
|
||||
// If that file does not exist, a nil source is returned.
|
||||
func DefaultSource() (Source, error) {
|
||||
defaultSourceOnce.Do(func() {
|
||||
defaultSource, defaultSourceErr = newSecureConnectSource()
|
||||
})
|
||||
return defaultSource, defaultSourceErr
|
||||
}
|
||||
|
||||
type secureConnectSource struct {
|
||||
metadata secureConnectMetadata
|
||||
}
|
||||
|
||||
type secureConnectMetadata struct {
|
||||
Cmd []string `json:"cert_provider_command"`
|
||||
}
|
||||
|
||||
// newSecureConnectSource creates a secureConnectSource by reading the well-known file.
|
||||
func newSecureConnectSource() (Source, error) {
|
||||
user, err := user.Current()
|
||||
if err != nil {
|
||||
// Ignore.
|
||||
return nil, nil
|
||||
}
|
||||
filename := filepath.Join(user.HomeDir, metadataPath, metadataFile)
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
if os.IsNotExist(err) {
|
||||
// Ignore.
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var metadata secureConnectMetadata
|
||||
if err := json.Unmarshal(file, &metadata); err != nil {
|
||||
return nil, fmt.Errorf("cert: could not parse JSON in %q: %v", filename, err)
|
||||
}
|
||||
if err := validateMetadata(metadata); err != nil {
|
||||
return nil, fmt.Errorf("cert: invalid config in %q: %v", filename, err)
|
||||
}
|
||||
return (&secureConnectSource{
|
||||
metadata: metadata,
|
||||
}).getClientCertificate, nil
|
||||
}
|
||||
|
||||
func validateMetadata(metadata secureConnectMetadata) error {
|
||||
if len(metadata.Cmd) == 0 {
|
||||
return errors.New("empty cert_provider_command")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *secureConnectSource) getClientCertificate(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
// TODO(cbro): consider caching valid certificates rather than exec'ing every time.
|
||||
command := s.metadata.Cmd
|
||||
data, err := exec.Command(command[0], command[1:]...).Output()
|
||||
if err != nil {
|
||||
// TODO(cbro): read stderr for error message? Might contain sensitive info.
|
||||
return nil, err
|
||||
}
|
||||
cert, err := tls.X509KeyPair(data, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cert, nil
|
||||
}
|
20
vendor/google.golang.org/api/transport/http/default_transport_go113.go
generated
vendored
Normal file
20
vendor/google.golang.org/api/transport/http/default_transport_go113.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2020 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.13
|
||||
|
||||
package http
|
||||
|
||||
import "net/http"
|
||||
|
||||
// clonedTransport returns the given RoundTripper as a cloned *http.Transport.
|
||||
// It returns nil if the RoundTripper can't be cloned or coerced to
|
||||
// *http.Transport.
|
||||
func clonedTransport(rt http.RoundTripper) *http.Transport {
|
||||
t, ok := rt.(*http.Transport)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return t.Clone()
|
||||
}
|
15
vendor/google.golang.org/api/transport/http/default_transport_not_go113.go
generated
vendored
Normal file
15
vendor/google.golang.org/api/transport/http/default_transport_not_go113.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2020 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.13
|
||||
|
||||
package http
|
||||
|
||||
import "net/http"
|
||||
|
||||
// clonedTransport returns the given RoundTripper as a cloned *http.Transport.
|
||||
// For versions of Go <1.13, this is not supported, so return nil.
|
||||
func clonedTransport(rt http.RoundTripper) *http.Transport {
|
||||
return nil
|
||||
}
|
304
vendor/google.golang.org/api/transport/http/dial.go
generated
vendored
Normal file
304
vendor/google.golang.org/api/transport/http/dial.go
generated
vendored
Normal file
|
@ -0,0 +1,304 @@
|
|||
// Copyright 2015 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// 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"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/cert"
|
||||
"google.golang.org/api/transport/http/internal/propagation"
|
||||
)
|
||||
|
||||
const (
|
||||
mTLSModeAlways = "always"
|
||||
mTLSModeNever = "never"
|
||||
mTLSModeAuto = "auto"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
clientCertSource, err := getClientCertificateSource(settings)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
endpoint, err := getEndpoint(settings, clientCertSource)
|
||||
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, endpoint, nil
|
||||
}
|
||||
trans, err := newTransport(ctx, defaultBaseTransport(ctx, clientCertSource), settings)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return &http.Client{Transport: trans}, 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) {
|
||||
paramTransport := ¶meterTransport{
|
||||
base: base,
|
||||
userAgent: settings.UserAgent,
|
||||
quotaProject: settings.QuotaProject,
|
||||
requestReason: settings.RequestReason,
|
||||
}
|
||||
var trans http.RoundTripper = paramTransport
|
||||
trans = addOCTransport(trans, settings)
|
||||
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
|
||||
}
|
||||
if paramTransport.quotaProject == "" {
|
||||
paramTransport.quotaProject = internal.QuotaProjectFromCreds(creds)
|
||||
}
|
||||
|
||||
ts := creds.TokenSource
|
||||
if settings.TokenSource != nil {
|
||||
ts = settings.TokenSource
|
||||
}
|
||||
trans = &oauth2.Transport{
|
||||
Base: trans,
|
||||
Source: ts,
|
||||
}
|
||||
}
|
||||
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")
|
||||
}
|
||||
newReq := *req
|
||||
newReq.Header = make(http.Header)
|
||||
for k, vv := range req.Header {
|
||||
newReq.Header[k] = vv
|
||||
}
|
||||
if t.userAgent != "" {
|
||||
// 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, use a default transport, taking most defaults from
|
||||
// http.DefaultTransport.
|
||||
// If TLSCertificate is available, set TLSClientConfig as well.
|
||||
func defaultBaseTransport(ctx context.Context, clientCertSource cert.Source) http.RoundTripper {
|
||||
if appengineUrlfetchHook != nil {
|
||||
return appengineUrlfetchHook(ctx)
|
||||
}
|
||||
|
||||
// Copy http.DefaultTransport except for MaxIdleConnsPerHost setting,
|
||||
// which is increased due to reported performance issues under load in the GCS
|
||||
// client. Transport.Clone is only available in Go 1.13 and up.
|
||||
trans := clonedTransport(http.DefaultTransport)
|
||||
if trans == nil {
|
||||
trans = fallbackBaseTransport()
|
||||
}
|
||||
trans.MaxIdleConnsPerHost = 100
|
||||
|
||||
if clientCertSource != nil {
|
||||
trans.TLSClientConfig = &tls.Config{
|
||||
GetClientCertificate: clientCertSource,
|
||||
}
|
||||
}
|
||||
|
||||
return trans
|
||||
}
|
||||
|
||||
// fallbackBaseTransport is used in <go1.13 as well as in the rare case if
|
||||
// http.DefaultTransport has been reassigned something that's not a
|
||||
// *http.Transport.
|
||||
func fallbackBaseTransport() *http.Transport {
|
||||
return &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func addOCTransport(trans http.RoundTripper, settings *internal.DialSettings) http.RoundTripper {
|
||||
if settings.TelemetryDisabled {
|
||||
return trans
|
||||
}
|
||||
return &ochttp.Transport{
|
||||
Base: trans,
|
||||
Propagation: &propagation.HTTPFormat{},
|
||||
}
|
||||
}
|
||||
|
||||
// getClientCertificateSource returns a default client certificate source, if
|
||||
// not provided by the user.
|
||||
//
|
||||
// A nil default source can be returned if the source does not exist. Any exceptions
|
||||
// encountered while initializing the default source will be reported as client
|
||||
// error (ex. corrupt metadata file).
|
||||
//
|
||||
// The overall logic is as follows:
|
||||
// 1. If both endpoint override and client certificate are specified, use them as is.
|
||||
// 2. If user does not specify client certificate, we will attempt to use default
|
||||
// client certificate.
|
||||
// 3. If user does not specify endpoint override, we will use defaultMtlsEndpoint if
|
||||
// client certificate is available and defaultEndpoint otherwise.
|
||||
//
|
||||
// Implications of the above logic:
|
||||
// 1. If the user specifies a non-mTLS endpoint override but client certificate is
|
||||
// available, we will pass along the cert anyway and let the server decide what to do.
|
||||
// 2. If the user specifies an mTLS endpoint override but client certificate is not
|
||||
// available, we will not fail-fast, but let backend throw error when connecting.
|
||||
//
|
||||
// We would like to avoid introducing client-side logic that parses whether the
|
||||
// endpoint override is an mTLS url, since the url pattern may change at anytime.
|
||||
func getClientCertificateSource(settings *internal.DialSettings) (cert.Source, error) {
|
||||
if settings.HTTPClient != nil {
|
||||
return nil, nil // HTTPClient is incompatible with ClientCertificateSource
|
||||
} else if settings.ClientCertSource != nil {
|
||||
return settings.ClientCertSource, nil
|
||||
} else {
|
||||
return cert.DefaultSource()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// getEndpoint returns the endpoint for the service, taking into account the
|
||||
// user-provided endpoint override "settings.Endpoint"
|
||||
//
|
||||
// If no endpoint override is specified, we will either return the default endpoint or
|
||||
// the default mTLS endpoint if a client certificate is available.
|
||||
//
|
||||
// You can override the default endpoint (mtls vs. regular) by setting the
|
||||
// GOOGLE_API_USE_MTLS environment variable.
|
||||
//
|
||||
// If the endpoint override is an address (host:port) rather than full base
|
||||
// URL (ex. https://...), then the user-provided address will be merged into
|
||||
// the default endpoint. For example, WithEndpoint("myhost:8000") and
|
||||
// WithDefaultEndpoint("https://foo.com/bar/baz") will return "https://myhost:8080/bar/baz"
|
||||
func getEndpoint(settings *internal.DialSettings, clientCertSource cert.Source) (string, error) {
|
||||
if settings.Endpoint == "" {
|
||||
mtlsMode := getMTLSMode()
|
||||
if mtlsMode == mTLSModeAlways || (clientCertSource != nil && mtlsMode == mTLSModeAuto) {
|
||||
return settings.DefaultMTLSEndpoint, nil
|
||||
}
|
||||
return settings.DefaultEndpoint, nil
|
||||
}
|
||||
if strings.Contains(settings.Endpoint, "://") {
|
||||
// User passed in a full URL path, use it verbatim.
|
||||
return settings.Endpoint, nil
|
||||
}
|
||||
if settings.DefaultEndpoint == "" {
|
||||
return "", errors.New("WithEndpoint requires a full URL path")
|
||||
}
|
||||
|
||||
// Assume user-provided endpoint is host[:port], merge it with the default endpoint.
|
||||
return mergeEndpoints(settings.DefaultEndpoint, settings.Endpoint)
|
||||
}
|
||||
|
||||
func getMTLSMode() string {
|
||||
mode := os.Getenv("GOOGLE_API_USE_MTLS")
|
||||
if mode == "" {
|
||||
// TODO(shinfan): Update this to "auto" when the mTLS feature is fully released.
|
||||
return mTLSModeNever
|
||||
}
|
||||
return strings.ToLower(mode)
|
||||
}
|
||||
|
||||
func mergeEndpoints(base, newHost string) (string, error) {
|
||||
u, err := url.Parse(base)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
u.Host = newHost
|
||||
return u.String(), nil
|
||||
}
|
20
vendor/google.golang.org/api/transport/http/dial_appengine.go
generated
vendored
Normal file
20
vendor/google.golang.org/api/transport/http/dial_appengine.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2016 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +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}
|
||||
}
|
||||
}
|
86
vendor/google.golang.org/api/transport/http/internal/propagation/http.go
generated
vendored
Normal file
86
vendor/google.golang.org/api/transport/http/internal/propagation/http.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Copyright 2018 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +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)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue