1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

Switch from govendor to go modules. (#587)

Thanks to @BenoitKnecht for leading the way on this.
This commit is contained in:
Tom Limoncelli
2020-01-18 14:40:28 -05:00
committed by GitHub
parent 31188c3a70
commit 16d0043cce
1554 changed files with 400867 additions and 98222 deletions

10
vendor/google.golang.org/api/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,10 @@
# This is the official list of authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as
# Name or Organization <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
Google Inc.

55
vendor/google.golang.org/api/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1,55 @@
# This is the official list of people who can contribute
# (and typically have contributed) code to the repository.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# The submission process automatically checks to make sure
# that people submitting code are listed in this file (by email address).
#
# Names should be added to this file only after verifying that
# the individual or the individual's organization has agreed to
# the appropriate Contributor License Agreement, found here:
#
# https://cla.developers.google.com/about/google-individual
# https://cla.developers.google.com/about/google-corporate
#
# The CLA can be filled out on the web:
#
# https://cla.developers.google.com/
#
# When adding J Random Contributor's name to this file,
# either J's name or J's organization's name should be
# added to the AUTHORS file, depending on whether the
# individual or corporate CLA was used.
# Names should be added to this file like so:
# Name <email address>
#
# An entry with two email addresses specifies that the
# first address should be used in the submit logs and
# that the second address should be recognized as the
# same person when interacting with Rietveld.
# Please keep the list sorted.
Alain Vongsouvanhalainv <alainv@google.com>
Andrew Gerrand <adg@golang.org>
Brad Fitzpatrick <bradfitz@golang.org>
Eric Koleda <ekoleda+devrel@googlers.com>
Francesc Campoy <campoy@golang.org>
Garrick Evans <garrick@google.com>
Glenn Lewis <gmlewis@google.com>
Ivan Krasin <krasin@golang.org>
Jason Hall <jasonhall@google.com>
Johan Euphrosine <proppy@google.com>
Kostik Shtoyk <kostik@google.com>
Kunpei Sakai <namusyaka@gmail.com>
Matthew Whisenhunt <matt.whisenhunt@gmail.com>
Michael McGreevy <mcgreevy@golang.org>
Nick Craig-Wood <nickcw@gmail.com>
Robbie Trencheny <me@robbiet.us>
Ross Light <light@google.com>
Sarah Adams <shadams@google.com>
Scott Van Woudenberg <scottvw@google.com>
Takashi Matsuo <tmatsuo@google.com>

27
vendor/google.golang.org/api/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2011 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,8 @@ import (
"time"
)
// BackoffStrategy defines the set of functions that a backoff-er must
// implement.
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.
@ -28,6 +30,7 @@ type ExponentialBackoff struct {
n uint
}
// Pause returns the amount of time the caller should wait.
func (eb *ExponentialBackoff) Pause() (time.Duration, bool) {
if eb.total > eb.Max {
return 0, false
@ -40,6 +43,8 @@ func (eb *ExponentialBackoff) Pause() (time.Duration, bool) {
return d, true
}
// Reset resets the backoff strategy such that the next Pause call will begin
// counting from the start. It is not safe to call concurrently with Pause.
func (eb *ExponentialBackoff) Reset() {
eb.n = 0
eb.total = 0

View File

@ -11,7 +11,8 @@ import (
"google.golang.org/api/googleapi"
)
// MediaBuffer buffers data from an io.Reader to support uploading media in retryable chunks.
// 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
@ -22,6 +23,7 @@ type MediaBuffer struct {
off int64
}
// NewMediaBuffer initializes a MediaBuffer.
func NewMediaBuffer(media io.Reader, chunkSize int) *MediaBuffer {
return &MediaBuffer{media: media, chunk: make([]byte, 0, chunkSize)}
}

View File

@ -1,4 +1,4 @@
// Copyright 2016 Google Inc. All Rights Reserved.
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -5,12 +5,16 @@
package gensupport
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"mime"
"mime/multipart"
"net/http"
"net/textproto"
"strings"
"sync"
"google.golang.org/api/googleapi"
)
@ -103,19 +107,24 @@ type typeReader struct {
typ string
}
// multipartReader combines the contents of multiple readers to creat a multipart/related HTTP body.
// 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
pipeOpen bool
ctype string
mu sync.Mutex
pipeOpen bool
}
func newMultipartReader(parts []typeReader) *multipartReader {
// 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 {
@ -144,10 +153,13 @@ func (mp *multipartReader) Read(data []byte) (n int, err error) {
}
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()
}
@ -156,10 +168,15 @@ func (mp *multipartReader) Close() error {
//
// 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
}
@ -235,6 +252,7 @@ func NewInfoFromResumableMedia(r io.ReaderAt, size int64, mediaType string) *Med
}
}
// SetProgressUpdater sets the progress updater for the media info.
func (mi *MediaInfo) SetProgressUpdater(pu googleapi.ProgressUpdater) {
if mi != nil {
mi.progressUpdater = pu
@ -251,11 +269,11 @@ func (mi *MediaInfo) UploadType() string {
}
// UploadRequest sets up an HTTP request for media upload. It adds headers
// as necessary, and returns a replacement for the body.
func (mi *MediaInfo) UploadRequest(reqHeaders http.Header, body io.Reader) (newBody io.Reader, cleanup func()) {
// 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, cleanup
return body, nil, cleanup
}
var media io.Reader
if mi.media != nil {
@ -269,7 +287,21 @@ func (mi *MediaInfo) UploadRequest(reqHeaders http.Header, body io.Reader) (newB
media, _, _, _ = mi.buffer.Chunk()
}
if media != nil {
fb := readerFunc(body)
fm := readerFunc(media)
combined, ctype := CombineBodyMedia(body, "application/json", media, mi.mType)
if fb != nil && fm != nil {
getBody = func() (io.ReadCloser, error) {
rb := ioutil.NopCloser(fb())
rm := ioutil.NopCloser(fm())
var mimeBoundary string
if _, params, err := mime.ParseMediaType(ctype); err == nil {
mimeBoundary = params["boundary"]
}
r, _ := combineBodyMedia(rb, "application/json", rm, mi.mType, mimeBoundary)
return r, nil
}
}
cleanup = func() { combined.Close() }
reqHeaders.Set("Content-Type", ctype)
body = combined
@ -277,7 +309,27 @@ func (mi *MediaInfo) UploadRequest(reqHeaders http.Header, body io.Reader) (newB
if mi.buffer != nil && mi.mType != "" && !mi.singleChunk {
reqHeaders.Set("X-Upload-Content-Type", mi.mType)
}
return body, cleanup
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
@ -297,3 +349,15 @@ func (mi *MediaInfo) ResumableUpload(locURI string) *ResumableUpload {
},
}
}
// 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
}

View File

@ -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())

View File

@ -5,14 +5,13 @@
package gensupport
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"sync"
"time"
"golang.org/x/net/context"
)
const (

View File

@ -1,4 +1,4 @@
// Copyright 2017 Google Inc. All Rights Reserved.
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -15,12 +15,11 @@
package gensupport
import (
"context"
"io"
"net"
"net/http"
"time"
"golang.org/x/net/context"
)
// Retry invokes the given function, retrying it multiple times if the connection failed or

View File

@ -5,11 +5,10 @@
package gensupport
import (
"context"
"encoding/json"
"errors"
"net/http"
"golang.org/x/net/context"
"golang.org/x/net/context/ctxhttp"
)
// Hook is the type of a function that is called once before each HTTP request
@ -31,7 +30,8 @@ func RegisterHook(h Hook) {
// SendRequest sends a single HTTP request using the given client.
// If ctx is non-nil, it calls all hooks, then sends the request with
// ctxhttp.Do, then calls any functions returned by the hooks in reverse order.
// 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.
@ -49,7 +49,7 @@ func SendRequest(ctx context.Context, client *http.Client, req *http.Request) (*
}
// Send request.
resp, err := ctxhttp.Do(ctx, client, req)
resp, err := send(ctx, client, req)
// Call returned funcs in reverse order.
for i := len(post) - 1; i >= 0; i-- {
@ -59,3 +59,29 @@ func SendRequest(ctx context.Context, client *http.Client, req *http.Request) (*
}
return resp, err
}
func send(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
if client == nil {
client = http.DefaultClient
}
resp, err := client.Do(req.WithContext(ctx))
// If we got an error, and the context has been canceled,
// the context's error is probably more useful.
if err != nil {
select {
case <-ctx.Done():
err = ctx.Err()
default:
}
}
return resp, err
}
// DecodeResponse decodes the body of res into target. If there is no body,
// target is unchanged.
func DecodeResponse(target interface{}, res *http.Response) error {
if res.StatusCode == http.StatusNoContent {
return nil
}
return json.NewDecoder(res.Body).Decode(target)
}

View File

@ -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 uploads if not specified by the user.
// DefaultUploadChunkSize is the default chunk size to use for resumable
// uploads if not specified by the user.
DefaultUploadChunkSize = 8 * 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
)
@ -161,9 +165,13 @@ func CheckMediaResponse(res *http.Response) error {
}
}
// 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 +189,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,13 +251,27 @@ 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).
func ResolveRelative(basestr, relstr string) string {
u, _ := url.Parse(basestr)
afterColonPath := ""
if i := strings.IndexRune(relstr, ':'); i > 0 {
afterColonPath = relstr[i+1:]
relstr = relstr[:i]
}
rel, _ := url.Parse(relstr)
u = u.ResolveReference(rel)
us := u.String()
if afterColonPath != "" {
us = fmt.Sprintf("%s:%s", us, afterColonPath)
}
us = strings.Replace(us, "%7B", "{", -1)
us = strings.Replace(us, "%7D", "}", -1)
us = strings.Replace(us, "%2A", "*", -1)
return us
}

View File

@ -0,0 +1,38 @@
// Copyright 2012 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package transport contains HTTP transports used to make
// authenticated API requests.
package transport
import (
"errors"
"net/http"
)
// APIKey is an HTTP Transport which wraps an underlying transport and
// appends an API Key "key" parameter to the URL of outgoing requests.
type APIKey struct {
// Key is the API Key to set on requests.
Key string
// Transport is the underlying HTTP transport.
// If nil, http.DefaultTransport is used.
Transport http.RoundTripper
}
func (t *APIKey) RoundTrip(req *http.Request) (*http.Response, error) {
rt := t.Transport
if rt == nil {
rt = http.DefaultTransport
if rt == nil {
return nil, errors.New("googleapi/transport: no Transport specified or available")
}
}
newReq := *req
args := newReq.URL.Query()
args.Set("key", t.Key)
newReq.URL.RawQuery = args.Encode()
return rt.RoundTrip(&newReq)
}

View File

@ -120,33 +120,33 @@ 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)
})
}

102
vendor/google.golang.org/api/internal/creds.go generated vendored Normal file
View File

@ -0,0 +1,102 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package internal
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
// Creds returns credential information obtained from DialSettings, or if none, then
// it returns default credential information.
func Creds(ctx context.Context, ds *DialSettings) (*google.Credentials, error) {
if ds.Credentials != nil {
return ds.Credentials, nil
}
if ds.CredentialsJSON != nil {
return credentialsFromJSON(ctx, ds.CredentialsJSON, ds.Endpoint, ds.Scopes, ds.Audiences)
}
if ds.CredentialsFile != "" {
data, err := ioutil.ReadFile(ds.CredentialsFile)
if err != nil {
return nil, fmt.Errorf("cannot read credentials file: %v", err)
}
return credentialsFromJSON(ctx, data, ds.Endpoint, ds.Scopes, ds.Audiences)
}
if ds.TokenSource != nil {
return &google.Credentials{TokenSource: ds.TokenSource}, nil
}
cred, err := google.FindDefaultCredentials(ctx, ds.Scopes...)
if err != nil {
return nil, err
}
if len(cred.JSON) > 0 {
return credentialsFromJSON(ctx, cred.JSON, ds.Endpoint, ds.Scopes, ds.Audiences)
}
// For GAE and GCE, the JSON is empty so return the default credentials directly.
return cred, nil
}
// JSON key file type.
const (
serviceAccountKey = "service_account"
)
// credentialsFromJSON returns a google.Credentials based on the input.
//
// - If the JSON is a service account and no scopes provided, returns self-signed JWT auth flow
// - Otherwise, returns OAuth 2.0 flow.
func credentialsFromJSON(ctx context.Context, data []byte, endpoint string, scopes []string, audiences []string) (*google.Credentials, error) {
cred, err := google.CredentialsFromJSON(ctx, data, scopes...)
if err != nil {
return nil, err
}
if len(data) > 0 && len(scopes) == 0 {
var f struct {
Type string `json:"type"`
// The rest JSON fields are omitted because they are not used.
}
if err := json.Unmarshal(cred.JSON, &f); err != nil {
return nil, err
}
if f.Type == serviceAccountKey {
ts, err := selfSignedJWTTokenSource(data, endpoint, audiences)
if err != nil {
return nil, err
}
cred.TokenSource = ts
}
}
return cred, err
}
func selfSignedJWTTokenSource(data []byte, endpoint string, audiences []string) (oauth2.TokenSource, error) {
// Use the API endpoint as the default audience
audience := endpoint
if len(audiences) > 0 {
// TODO(shinfan): Update golang oauth to support multiple audiences.
if len(audiences) > 1 {
return nil, fmt.Errorf("multiple audiences support is not implemented")
}
audience = audiences[0]
}
return google.JWTAccessTokenSourceFromJSON(data, audience)
}

61
vendor/google.golang.org/api/internal/pool.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package internal
import (
"errors"
"google.golang.org/grpc/naming"
)
// PoolResolver provides a fixed list of addresses to load balance between
// and does not provide further updates.
type PoolResolver struct {
poolSize int
dialOpt *DialSettings
ch chan []*naming.Update
}
// NewPoolResolver returns a PoolResolver
// This is an EXPERIMENTAL API and may be changed or removed in the future.
func NewPoolResolver(size int, o *DialSettings) *PoolResolver {
return &PoolResolver{poolSize: size, dialOpt: o}
}
// Resolve returns a Watcher for the endpoint defined by the DialSettings
// provided to NewPoolResolver.
func (r *PoolResolver) Resolve(target string) (naming.Watcher, error) {
if r.dialOpt.Endpoint == "" {
return nil, errors.New("no endpoint configured")
}
addrs := make([]*naming.Update, 0, r.poolSize)
for i := 0; i < r.poolSize; i++ {
addrs = append(addrs, &naming.Update{Op: naming.Add, Addr: r.dialOpt.Endpoint, Metadata: i})
}
r.ch = make(chan []*naming.Update, 1)
r.ch <- addrs
return r, nil
}
// Next returns a static list of updates on the first call,
// and blocks indefinitely until Close is called on subsequent calls.
func (r *PoolResolver) Next() ([]*naming.Update, error) {
return <-r.ch, nil
}
// Close releases resources associated with the pool and causes Next to unblock.
func (r *PoolResolver) Close() {
close(r.ch)
}

View File

@ -0,0 +1,12 @@
{
"type": "service_account",
"project_id": "project_id",
"private_key_id": "private_key_id",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzd9ZdbPLAR4/g\nj+Rodu15kEasMpxf/Mz+gKRb2fmgR2Y18Y/iRBYZ4SkmF2pBSfzvwE/aTCzSPBGl\njHhPzohXnSN029eWoItmxVONlqCbR29pD07aLzv08LGeIGdHIEdhVjhvRwTkYZIF\ndXmlHNDRUU/EbJN9D+3ahw22BNnC4PaDgfIWTs3xIlTCSf2rL39I4DSNLTS/LzxK\n/XrQfBMtfwMWwyQaemXbc7gRgzOy8L56wa1W1zyXx99th97j1bLnoAXBGplhB4Co\n25ohyDAuhxRm+XGMEaO0Mzo7u97kvhj48a569RH1QRhOf7EBf60jO4h5eOmfi5P5\nPV3l7041AgMBAAECggEAEZ0RTNoEeRqM5F067YW+iM/AH+ZXspP9Cn1VpC4gcbqQ\nLXsnw+0qvh97CmIB66Z3TJBzRdl0DK4YjUbcB/kdKHwjnrR01DOtesijCqJd4N+B\n762w73jzSXbV9872U+S3HLZ5k3JE6KUqz55X8fyCAgkY6w4862lEzs2yasrPFHEV\nRoQp3PM0Miif8R3hGDhOWcHxcobullthG6JHAQFfc1ctwEjZI4TK0iWqlzfWGyKN\nT9UgvjUDud5cGvS9el0AiLN6keAf77tcPn1zetUVhxN1KN4bVAm1Q+6O8esl63Rj\n7JXpHzxaRnit9S6/aH/twHsGGtLg5Puw6jey6xs4AQKBgQD2JNy1wzewCRkD+jug\n8CHbJ+LIJVRNIaWa/RK1QD8/UjmFPkIzRQSF3AKC5mRAWSa2FL3yVK3N/DD7hazW\n85XSBB7IDcnoJnA9SkUeWwqQGkDx3EntlU3gX8Kn/+ofF8O9jLXxAa901MAVXVuf\n5YDzrl4PNE3bFnPCdiNmSdRfhQKBgQC6p4DsCpwqbeTu9f5ak9VW/fQP47Fgt+Mf\nwGjBnKP5PbbNJpHCfamF7jqSRH83Xy0KNssH7jD/NZ2oT594sMmiQPUC5ni9VYY6\nsuYB0JbD5Mq+EjKIVhYtxaQJ76LzHreEI+G4z6k3H7/hRpr3/C48n9G/uVkT9DbJ\noplxxEx68QKBgQCdJ23vcwO0Firtmi/GEmtbVHz70rGfSXNFoHz4UlvPXv0wsE5u\nE4vOt2i3EMhDOWh46odYGG6bzH+tp2xyFTW70Dui+QLHgPs6dpfoyLHWzZxXj5F3\n6lK9hgZvYvqk/XRRKmzjwnK2wjsdqOyeC1covlR5mqh20D/6kZkKbur0TQKBgAwy\nCZBimRWEnKKoW/gbFKNccGfhXqONID/g2Hdd/rC4QYth68AjacIgcJ9B7nX1uAGk\n1tsryvPB0w0+NpMyKdp6GAgaeuUUA3MuYSzZLiCagEyu77JMvaI7+Z3UlHcCGMd/\neK4Uk1/QqT7U2Cc/yN2ZK6E1QQa2vCWshA4U31JhAoGAbtbSSSsul1c+PsJ13Cfk\n6qVnqYzPqt23QTyOZmGAvUHH/M4xRiQpOE0cDF4t/r5PwenAQPQzTvMmWRzj6uAY\n3eaU0eAK7ZfoweCoOIAPnpFbbRLrXfoY46H7MYh7euWGXOKEpxz5yzuEkd9ByNUE\n86vSEidqbMIiXVgEgnu/k08=\n-----END PRIVATE KEY-----\n",
"client_email": "xyz@developer.gserviceaccount.com",
"client_id": "123",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xyz%40developer.gserviceaccount.com"
}

96
vendor/google.golang.org/api/internal/settings.go generated vendored Normal file
View File

@ -0,0 +1,96 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package internal supports the options and transport packages.
package internal
import (
"errors"
"net/http"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/grpc"
)
// DialSettings holds information needed to establish a connection with a
// Google API service.
type DialSettings struct {
Endpoint string
Scopes []string
TokenSource oauth2.TokenSource
Credentials *google.Credentials
CredentialsFile string // if set, Token Source is ignored.
CredentialsJSON []byte
UserAgent string
APIKey string
Audiences []string
HTTPClient *http.Client
GRPCDialOpts []grpc.DialOption
GRPCConn *grpc.ClientConn
NoAuth bool
// Google API system parameters. For more information please read:
// https://cloud.google.com/apis/docs/system-parameters
QuotaProject string
RequestReason string
}
// Validate reports an error if ds is invalid.
func (ds *DialSettings) Validate() error {
hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil
if ds.NoAuth && hasCreds {
return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials")
}
// Credentials should not appear with other options.
// We currently allow TokenSource and CredentialsFile to coexist.
// TODO(jba): make TokenSource & CredentialsFile an error (breaking change).
nCreds := 0
if ds.Credentials != nil {
nCreds++
}
if ds.CredentialsJSON != nil {
nCreds++
}
if ds.CredentialsFile != "" {
nCreds++
}
if ds.APIKey != "" {
nCreds++
}
if ds.TokenSource != nil {
nCreds++
}
if len(ds.Scopes) > 0 && len(ds.Audiences) > 0 {
return errors.New("WithScopes is incompatible with WithAudience")
}
// Accept only one form of credentials, except we allow TokenSource and CredentialsFile for backwards compatibility.
if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") {
return errors.New("multiple credential options provided")
}
if ds.HTTPClient != nil && ds.GRPCConn != nil {
return errors.New("WithHTTPClient is incompatible with WithGRPCConn")
}
if ds.HTTPClient != nil && ds.GRPCDialOpts != nil {
return errors.New("WithHTTPClient is incompatible with gRPC dial options")
}
if ds.HTTPClient != nil && ds.QuotaProject != "" {
return errors.New("WithHTTPClient is incompatible with QuotaProject")
}
if ds.HTTPClient != nil && ds.RequestReason != "" {
return errors.New("WithHTTPClient is incompatible with RequestReason")
}
return nil
}

View File

@ -0,0 +1,33 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build go1.9
package option
import (
"golang.org/x/oauth2/google"
"google.golang.org/api/internal"
)
type withCreds google.Credentials
func (w *withCreds) Apply(o *internal.DialSettings) {
o.Credentials = (*google.Credentials)(w)
}
// WithCredentials returns a ClientOption that authenticates API calls.
func WithCredentials(creds *google.Credentials) ClientOption {
return (*withCreds)(creds)
}

View File

@ -0,0 +1,32 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !go1.9
package option
import (
"golang.org/x/oauth2/google"
"google.golang.org/api/internal"
)
type withCreds google.DefaultCredentials
func (w *withCreds) Apply(o *internal.DialSettings) {
o.Credentials = (*google.DefaultCredentials)(w)
}
func WithCredentials(creds *google.DefaultCredentials) ClientOption {
return (*withCreds)(creds)
}

235
vendor/google.golang.org/api/option/option.go generated vendored Normal file
View File

@ -0,0 +1,235 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package option contains options for Google API clients.
package option
import (
"net/http"
"golang.org/x/oauth2"
"google.golang.org/api/internal"
"google.golang.org/grpc"
)
// A ClientOption is an option for a Google API client.
type ClientOption interface {
Apply(*internal.DialSettings)
}
// WithTokenSource returns a ClientOption that specifies an OAuth2 token
// source to be used as the basis for authentication.
func WithTokenSource(s oauth2.TokenSource) ClientOption {
return withTokenSource{s}
}
type withTokenSource struct{ ts oauth2.TokenSource }
func (w withTokenSource) Apply(o *internal.DialSettings) {
o.TokenSource = w.ts
}
type withCredFile string
func (w withCredFile) Apply(o *internal.DialSettings) {
o.CredentialsFile = string(w)
}
// WithCredentialsFile returns a ClientOption that authenticates
// API calls with the given service account or refresh token JSON
// credentials file.
func WithCredentialsFile(filename string) ClientOption {
return withCredFile(filename)
}
// WithServiceAccountFile returns a ClientOption that uses a Google service
// account credentials file to authenticate.
//
// Deprecated: Use WithCredentialsFile instead.
func WithServiceAccountFile(filename string) ClientOption {
return WithCredentialsFile(filename)
}
// WithCredentialsJSON returns a ClientOption that authenticates
// API calls with the given service account or refresh token JSON
// credentials.
func WithCredentialsJSON(p []byte) ClientOption {
return withCredentialsJSON(p)
}
type withCredentialsJSON []byte
func (w withCredentialsJSON) Apply(o *internal.DialSettings) {
o.CredentialsJSON = make([]byte, len(w))
copy(o.CredentialsJSON, w)
}
// WithEndpoint returns a ClientOption that overrides the default endpoint
// to be used for a service.
func WithEndpoint(url string) ClientOption {
return withEndpoint(url)
}
type withEndpoint string
func (w withEndpoint) Apply(o *internal.DialSettings) {
o.Endpoint = string(w)
}
// WithScopes returns a ClientOption that overrides the default OAuth2 scopes
// to be used for a service.
func WithScopes(scope ...string) ClientOption {
return withScopes(scope)
}
type withScopes []string
func (w withScopes) Apply(o *internal.DialSettings) {
o.Scopes = make([]string, len(w))
copy(o.Scopes, w)
}
// WithUserAgent returns a ClientOption that sets the User-Agent.
func WithUserAgent(ua string) ClientOption {
return withUA(ua)
}
type withUA string
func (w withUA) Apply(o *internal.DialSettings) { o.UserAgent = string(w) }
// WithHTTPClient returns a ClientOption that specifies the HTTP client to use
// as the basis of communications. This option may only be used with services
// that support HTTP as their communication transport. When used, the
// WithHTTPClient option takes precedent over all other supplied options.
func WithHTTPClient(client *http.Client) ClientOption {
return withHTTPClient{client}
}
type withHTTPClient struct{ client *http.Client }
func (w withHTTPClient) Apply(o *internal.DialSettings) {
o.HTTPClient = w.client
}
// WithGRPCConn returns a ClientOption that specifies the gRPC client
// connection to use as the basis of communications. This option many only be
// used with services that support gRPC as their communication transport. When
// used, the WithGRPCConn option takes precedent over all other supplied
// options.
func WithGRPCConn(conn *grpc.ClientConn) ClientOption {
return withGRPCConn{conn}
}
type withGRPCConn struct{ conn *grpc.ClientConn }
func (w withGRPCConn) Apply(o *internal.DialSettings) {
o.GRPCConn = w.conn
}
// WithGRPCDialOption returns a ClientOption that appends a new grpc.DialOption
// to an underlying gRPC dial. It does not work with WithGRPCConn.
func WithGRPCDialOption(opt grpc.DialOption) ClientOption {
return withGRPCDialOption{opt}
}
type withGRPCDialOption struct{ opt grpc.DialOption }
func (w withGRPCDialOption) Apply(o *internal.DialSettings) {
o.GRPCDialOpts = append(o.GRPCDialOpts, w.opt)
}
// WithGRPCConnectionPool returns a ClientOption that creates a pool of gRPC
// connections that requests will be balanced between.
// This is an EXPERIMENTAL API and may be changed or removed in the future.
func WithGRPCConnectionPool(size int) ClientOption {
return withGRPCConnectionPool(size)
}
type withGRPCConnectionPool int
func (w withGRPCConnectionPool) Apply(o *internal.DialSettings) {
balancer := grpc.RoundRobin(internal.NewPoolResolver(int(w), o))
o.GRPCDialOpts = append(o.GRPCDialOpts, grpc.WithBalancer(balancer))
}
// WithAPIKey returns a ClientOption that specifies an API key to be used
// as the basis for authentication.
//
// API Keys can only be used for JSON-over-HTTP APIs, including those under
// the import path google.golang.org/api/....
func WithAPIKey(apiKey string) ClientOption {
return withAPIKey(apiKey)
}
type withAPIKey string
func (w withAPIKey) Apply(o *internal.DialSettings) { o.APIKey = string(w) }
// WithAudiences returns a ClientOption that specifies an audience to be used
// as the audience field ("aud") for the JWT token authentication.
func WithAudiences(audience ...string) ClientOption {
return withAudiences(audience)
}
type withAudiences []string
func (w withAudiences) Apply(o *internal.DialSettings) {
o.Audiences = make([]string, len(w))
copy(o.Audiences, w)
}
// WithoutAuthentication returns a ClientOption that specifies that no
// authentication should be used. It is suitable only for testing and for
// accessing public resources, like public Google Cloud Storage buckets.
// It is an error to provide both WithoutAuthentication and any of WithAPIKey,
// WithTokenSource, WithCredentialsFile or WithServiceAccountFile.
func WithoutAuthentication() ClientOption {
return withoutAuthentication{}
}
type withoutAuthentication struct{}
func (w withoutAuthentication) Apply(o *internal.DialSettings) { o.NoAuth = true }
// WithQuotaProject returns a ClientOption that specifies the project used
// for quota and billing purposes.
//
// For more information please read:
// https://cloud.google.com/apis/docs/system-parameters
func WithQuotaProject(quotaProject string) ClientOption {
return withQuotaProject(quotaProject)
}
type withQuotaProject string
func (w withQuotaProject) Apply(o *internal.DialSettings) {
o.QuotaProject = string(w)
}
// WithRequestReason returns a ClientOption that specifies a reason for
// making the request, which is intended to be recorded in audit logging.
// An example reason would be a support-case ticket number.
//
// For more information please read:
// https://cloud.google.com/apis/docs/system-parameters
func WithRequestReason(requestReason string) ClientOption {
return withRequestReason(requestReason)
}
type withRequestReason string
func (w withRequestReason) Apply(o *internal.DialSettings) {
o.RequestReason = string(w)
}

161
vendor/google.golang.org/api/transport/http/dial.go generated vendored Normal file
View File

@ -0,0 +1,161 @@
// Copyright 2015 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package http supports network connections to HTTP servers.
// This package is not intended for use by end developers. Use the
// google.golang.org/api/option package to configure API clients.
package http
import (
"context"
"errors"
"net/http"
"go.opencensus.io/plugin/ochttp"
"golang.org/x/oauth2"
"google.golang.org/api/googleapi/transport"
"google.golang.org/api/internal"
"google.golang.org/api/option"
"google.golang.org/api/transport/http/internal/propagation"
)
// NewClient returns an HTTP client for use communicating with a Google cloud
// service, configured with the given ClientOptions. It also returns the endpoint
// for the service as specified in the options.
func NewClient(ctx context.Context, opts ...option.ClientOption) (*http.Client, string, error) {
settings, err := newSettings(opts)
if err != nil {
return nil, "", err
}
// TODO(cbro): consider injecting the User-Agent even if an explicit HTTP client is provided?
if settings.HTTPClient != nil {
return settings.HTTPClient, settings.Endpoint, nil
}
trans, err := newTransport(ctx, defaultBaseTransport(ctx), settings)
if err != nil {
return nil, "", err
}
return &http.Client{Transport: trans}, settings.Endpoint, nil
}
// NewTransport creates an http.RoundTripper for use communicating with a Google
// cloud service, configured with the given ClientOptions. Its RoundTrip method delegates to base.
func NewTransport(ctx context.Context, base http.RoundTripper, opts ...option.ClientOption) (http.RoundTripper, error) {
settings, err := newSettings(opts)
if err != nil {
return nil, err
}
if settings.HTTPClient != nil {
return nil, errors.New("transport/http: WithHTTPClient passed to NewTransport")
}
return newTransport(ctx, base, settings)
}
func newTransport(ctx context.Context, base http.RoundTripper, settings *internal.DialSettings) (http.RoundTripper, error) {
trans := base
trans = parameterTransport{
base: trans,
userAgent: settings.UserAgent,
quotaProject: settings.QuotaProject,
requestReason: settings.RequestReason,
}
trans = addOCTransport(trans)
switch {
case settings.NoAuth:
// Do nothing.
case settings.APIKey != "":
trans = &transport.APIKey{
Transport: trans,
Key: settings.APIKey,
}
default:
creds, err := internal.Creds(ctx, settings)
if err != nil {
return nil, err
}
trans = &oauth2.Transport{
Base: trans,
Source: creds.TokenSource,
}
}
return trans, nil
}
func newSettings(opts []option.ClientOption) (*internal.DialSettings, error) {
var o internal.DialSettings
for _, opt := range opts {
opt.Apply(&o)
}
if err := o.Validate(); err != nil {
return nil, err
}
if o.GRPCConn != nil {
return nil, errors.New("unsupported gRPC connection specified")
}
return &o, nil
}
type parameterTransport struct {
userAgent string
quotaProject string
requestReason string
base http.RoundTripper
}
func (t parameterTransport) RoundTrip(req *http.Request) (*http.Response, error) {
rt := t.base
if rt == nil {
return nil, errors.New("transport: no Transport specified")
}
if t.userAgent == "" {
return rt.RoundTrip(req)
}
newReq := *req
newReq.Header = make(http.Header)
for k, vv := range req.Header {
newReq.Header[k] = vv
}
// TODO(cbro): append to existing User-Agent header?
newReq.Header.Set("User-Agent", t.userAgent)
// Attach system parameters into the header
if t.quotaProject != "" {
newReq.Header.Set("X-Goog-User-Project", t.quotaProject)
}
if t.requestReason != "" {
newReq.Header.Set("X-Goog-Request-Reason", t.requestReason)
}
return rt.RoundTrip(&newReq)
}
// Set at init time by dial_appengine.go. If nil, we're not on App Engine.
var appengineUrlfetchHook func(context.Context) http.RoundTripper
// defaultBaseTransport returns the base HTTP transport.
// On App Engine, this is urlfetch.Transport, otherwise it's http.DefaultTransport.
func defaultBaseTransport(ctx context.Context) http.RoundTripper {
if appengineUrlfetchHook != nil {
return appengineUrlfetchHook(ctx)
}
return http.DefaultTransport
}
func addOCTransport(trans http.RoundTripper) http.RoundTripper {
return &ochttp.Transport{
Base: trans,
Propagation: &propagation.HTTPFormat{},
}
}

View File

@ -0,0 +1,30 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build appengine
package http
import (
"context"
"net/http"
"google.golang.org/appengine/urlfetch"
)
func init() {
appengineUrlfetchHook = func(ctx context.Context) http.RoundTripper {
return &urlfetch.Transport{Context: ctx}
}
}

View File

@ -0,0 +1,96 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build go1.8
// Package propagation implements X-Cloud-Trace-Context header propagation used
// by Google Cloud products.
package propagation
import (
"encoding/binary"
"encoding/hex"
"fmt"
"net/http"
"strconv"
"strings"
"go.opencensus.io/trace"
"go.opencensus.io/trace/propagation"
)
const (
httpHeaderMaxSize = 200
httpHeader = `X-Cloud-Trace-Context`
)
var _ propagation.HTTPFormat = (*HTTPFormat)(nil)
// HTTPFormat implements propagation.HTTPFormat to propagate
// traces in HTTP headers for Google Cloud Platform and Stackdriver Trace.
type HTTPFormat struct{}
// SpanContextFromRequest extracts a Stackdriver Trace span context from incoming requests.
func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) {
h := req.Header.Get(httpHeader)
// See https://cloud.google.com/trace/docs/faq for the header HTTPFormat.
// Return if the header is empty or missing, or if the header is unreasonably
// large, to avoid making unnecessary copies of a large string.
if h == "" || len(h) > httpHeaderMaxSize {
return trace.SpanContext{}, false
}
// Parse the trace id field.
slash := strings.Index(h, `/`)
if slash == -1 {
return trace.SpanContext{}, false
}
tid, h := h[:slash], h[slash+1:]
buf, err := hex.DecodeString(tid)
if err != nil {
return trace.SpanContext{}, false
}
copy(sc.TraceID[:], buf)
// Parse the span id field.
spanstr := h
semicolon := strings.Index(h, `;`)
if semicolon != -1 {
spanstr, h = h[:semicolon], h[semicolon+1:]
}
sid, err := strconv.ParseUint(spanstr, 10, 64)
if err != nil {
return trace.SpanContext{}, false
}
binary.BigEndian.PutUint64(sc.SpanID[:], sid)
// Parse the options field, options field is optional.
if !strings.HasPrefix(h, "o=") {
return sc, true
}
o, err := strconv.ParseUint(h[2:], 10, 64)
if err != nil {
return trace.SpanContext{}, false
}
sc.TraceOptions = trace.TraceOptions(o)
return sc, true
}
// SpanContextToRequest modifies the given request to include a Stackdriver Trace header.
func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) {
sid := binary.BigEndian.Uint64(sc.SpanID[:])
header := fmt.Sprintf("%s/%d;o=%d", hex.EncodeToString(sc.TraceID[:]), sid, int64(sc.TraceOptions))
req.Header.Set(httpHeader, header)
}