github.com/chasestarr/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/Godeps/_workspace/src/google.golang.org/api/googleapi/googleapi.go (about)

     1  // Copyright 2011 Google Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package googleapi contains the common code shared by all Google API
     6  // libraries.
     7  package googleapi
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/json"
    12  	"fmt"
    13  	"io"
    14  	"io/ioutil"
    15  	"net/http"
    16  	"net/url"
    17  	"strings"
    18  
    19  	"google.golang.org/api/googleapi/internal/uritemplates"
    20  )
    21  
    22  // ContentTyper is an interface for Readers which know (or would like
    23  // to override) their Content-Type. If a media body doesn't implement
    24  // ContentTyper, the type is sniffed from the content using
    25  // http.DetectContentType.
    26  type ContentTyper interface {
    27  	ContentType() string
    28  }
    29  
    30  // A SizeReaderAt is a ReaderAt with a Size method.
    31  // An io.SectionReader implements SizeReaderAt.
    32  type SizeReaderAt interface {
    33  	io.ReaderAt
    34  	Size() int64
    35  }
    36  
    37  // ServerResponse is embedded in each Do response and
    38  // provides the HTTP status code and header sent by the server.
    39  type ServerResponse struct {
    40  	// HTTPStatusCode is the server's response status code.
    41  	// When using a resource method's Do call, this will always be in the 2xx range.
    42  	HTTPStatusCode int
    43  	// Header contains the response header fields from the server.
    44  	Header http.Header
    45  }
    46  
    47  const (
    48  	Version = "0.5"
    49  
    50  	// UserAgent is the header string used to identify this package.
    51  	UserAgent = "google-api-go-client/" + Version
    52  
    53  	// The default chunk size to use for resumable uplods if not specified by the user.
    54  	DefaultUploadChunkSize = 8 * 1024 * 1024
    55  
    56  	// The minimum chunk size that can be used for resumable uploads.  All
    57  	// user-specified chunk sizes must be multiple of this value.
    58  	MinUploadChunkSize = 256 * 1024
    59  )
    60  
    61  // Error contains an error response from the server.
    62  type Error struct {
    63  	// Code is the HTTP response status code and will always be populated.
    64  	Code int `json:"code"`
    65  	// Message is the server response message and is only populated when
    66  	// explicitly referenced by the JSON server response.
    67  	Message string `json:"message"`
    68  	// Body is the raw response returned by the server.
    69  	// It is often but not always JSON, depending on how the request fails.
    70  	Body string
    71  	// Header contains the response header fields from the server.
    72  	Header http.Header
    73  
    74  	Errors []ErrorItem
    75  }
    76  
    77  // ErrorItem is a detailed error code & message from the Google API frontend.
    78  type ErrorItem struct {
    79  	// Reason is the typed error code. For example: "some_example".
    80  	Reason string `json:"reason"`
    81  	// Message is the human-readable description of the error.
    82  	Message string `json:"message"`
    83  }
    84  
    85  func (e *Error) Error() string {
    86  	if len(e.Errors) == 0 && e.Message == "" {
    87  		return fmt.Sprintf("googleapi: got HTTP response code %d with body: %v", e.Code, e.Body)
    88  	}
    89  	var buf bytes.Buffer
    90  	fmt.Fprintf(&buf, "googleapi: Error %d: ", e.Code)
    91  	if e.Message != "" {
    92  		fmt.Fprintf(&buf, "%s", e.Message)
    93  	}
    94  	if len(e.Errors) == 0 {
    95  		return strings.TrimSpace(buf.String())
    96  	}
    97  	if len(e.Errors) == 1 && e.Errors[0].Message == e.Message {
    98  		fmt.Fprintf(&buf, ", %s", e.Errors[0].Reason)
    99  		return buf.String()
   100  	}
   101  	fmt.Fprintln(&buf, "\nMore details:")
   102  	for _, v := range e.Errors {
   103  		fmt.Fprintf(&buf, "Reason: %s, Message: %s\n", v.Reason, v.Message)
   104  	}
   105  	return buf.String()
   106  }
   107  
   108  type errorReply struct {
   109  	Error *Error `json:"error"`
   110  }
   111  
   112  // CheckResponse returns an error (of type *Error) if the response
   113  // status code is not 2xx.
   114  func CheckResponse(res *http.Response) error {
   115  	if res.StatusCode >= 200 && res.StatusCode <= 299 {
   116  		return nil
   117  	}
   118  	slurp, err := ioutil.ReadAll(res.Body)
   119  	if err == nil {
   120  		jerr := new(errorReply)
   121  		err = json.Unmarshal(slurp, jerr)
   122  		if err == nil && jerr.Error != nil {
   123  			if jerr.Error.Code == 0 {
   124  				jerr.Error.Code = res.StatusCode
   125  			}
   126  			jerr.Error.Body = string(slurp)
   127  			return jerr.Error
   128  		}
   129  	}
   130  	return &Error{
   131  		Code:   res.StatusCode,
   132  		Body:   string(slurp),
   133  		Header: res.Header,
   134  	}
   135  }
   136  
   137  // IsNotModified reports whether err is the result of the
   138  // server replying with http.StatusNotModified.
   139  // Such error values are sometimes returned by "Do" methods
   140  // on calls when If-None-Match is used.
   141  func IsNotModified(err error) bool {
   142  	if err == nil {
   143  		return false
   144  	}
   145  	ae, ok := err.(*Error)
   146  	return ok && ae.Code == http.StatusNotModified
   147  }
   148  
   149  // CheckMediaResponse returns an error (of type *Error) if the response
   150  // status code is not 2xx. Unlike CheckResponse it does not assume the
   151  // body is a JSON error document.
   152  func CheckMediaResponse(res *http.Response) error {
   153  	if res.StatusCode >= 200 && res.StatusCode <= 299 {
   154  		return nil
   155  	}
   156  	slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20))
   157  	res.Body.Close()
   158  	return &Error{
   159  		Code: res.StatusCode,
   160  		Body: string(slurp),
   161  	}
   162  }
   163  
   164  type MarshalStyle bool
   165  
   166  var WithDataWrapper = MarshalStyle(true)
   167  var WithoutDataWrapper = MarshalStyle(false)
   168  
   169  func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) {
   170  	buf := new(bytes.Buffer)
   171  	if wrap {
   172  		buf.Write([]byte(`{"data": `))
   173  	}
   174  	err := json.NewEncoder(buf).Encode(v)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  	if wrap {
   179  		buf.Write([]byte(`}`))
   180  	}
   181  	return buf, nil
   182  }
   183  
   184  // endingWithErrorReader from r until it returns an error.  If the
   185  // final error from r is io.EOF and e is non-nil, e is used instead.
   186  type endingWithErrorReader struct {
   187  	r io.Reader
   188  	e error
   189  }
   190  
   191  func (er endingWithErrorReader) Read(p []byte) (n int, err error) {
   192  	n, err = er.r.Read(p)
   193  	if err == io.EOF && er.e != nil {
   194  		err = er.e
   195  	}
   196  	return
   197  }
   198  
   199  // countingWriter counts the number of bytes it receives to write, but
   200  // discards them.
   201  type countingWriter struct {
   202  	n *int64
   203  }
   204  
   205  func (w countingWriter) Write(p []byte) (int, error) {
   206  	*w.n += int64(len(p))
   207  	return len(p), nil
   208  }
   209  
   210  // ProgressUpdater is a function that is called upon every progress update of a resumable upload.
   211  // This is the only part of a resumable upload (from googleapi) that is usable by the developer.
   212  // The remaining usable pieces of resumable uploads is exposed in each auto-generated API.
   213  type ProgressUpdater func(current, total int64)
   214  
   215  type MediaOption interface {
   216  	setOptions(o *MediaOptions)
   217  }
   218  
   219  type contentTypeOption string
   220  
   221  func (ct contentTypeOption) setOptions(o *MediaOptions) {
   222  	o.ContentType = string(ct)
   223  }
   224  
   225  // ContentType returns a MediaOption which sets the content type of data to be uploaded.
   226  func ContentType(ctype string) MediaOption {
   227  	return contentTypeOption(ctype)
   228  }
   229  
   230  type chunkSizeOption int
   231  
   232  func (cs chunkSizeOption) setOptions(o *MediaOptions) {
   233  	size := int(cs)
   234  	if size%MinUploadChunkSize != 0 {
   235  		size += MinUploadChunkSize - (size % MinUploadChunkSize)
   236  	}
   237  	o.ChunkSize = size
   238  }
   239  
   240  // ChunkSize returns a MediaOption which sets the chunk size for media uploads.
   241  // size will be rounded up to the nearest multiple of 256K.
   242  // Media which contains fewer than size bytes will be uploaded in a single request.
   243  // Media which contains size bytes or more will be uploaded in separate chunks.
   244  // If size is zero, media will be uploaded in a single request.
   245  func ChunkSize(size int) MediaOption {
   246  	return chunkSizeOption(size)
   247  }
   248  
   249  // MediaOptions stores options for customizing media upload.  It is not used by developers directly.
   250  type MediaOptions struct {
   251  	ContentType string
   252  	ChunkSize   int
   253  }
   254  
   255  // ProcessMediaOptions stores options from opts in a MediaOptions.
   256  // It is not used by developers directly.
   257  func ProcessMediaOptions(opts []MediaOption) *MediaOptions {
   258  	mo := &MediaOptions{ChunkSize: DefaultUploadChunkSize}
   259  	for _, o := range opts {
   260  		o.setOptions(mo)
   261  	}
   262  	return mo
   263  }
   264  
   265  func ResolveRelative(basestr, relstr string) string {
   266  	u, _ := url.Parse(basestr)
   267  	rel, _ := url.Parse(relstr)
   268  	u = u.ResolveReference(rel)
   269  	us := u.String()
   270  	us = strings.Replace(us, "%7B", "{", -1)
   271  	us = strings.Replace(us, "%7D", "}", -1)
   272  	return us
   273  }
   274  
   275  // has4860Fix is whether this Go environment contains the fix for
   276  // http://golang.org/issue/4860
   277  var has4860Fix bool
   278  
   279  // init initializes has4860Fix by checking the behavior of the net/http package.
   280  func init() {
   281  	r := http.Request{
   282  		URL: &url.URL{
   283  			Scheme: "http",
   284  			Opaque: "//opaque",
   285  		},
   286  	}
   287  	b := &bytes.Buffer{}
   288  	r.Write(b)
   289  	has4860Fix = bytes.HasPrefix(b.Bytes(), []byte("GET http"))
   290  }
   291  
   292  // SetOpaque sets u.Opaque from u.Path such that HTTP requests to it
   293  // don't alter any hex-escaped characters in u.Path.
   294  func SetOpaque(u *url.URL) {
   295  	u.Opaque = "//" + u.Host + u.Path
   296  	if !has4860Fix {
   297  		u.Opaque = u.Scheme + ":" + u.Opaque
   298  	}
   299  }
   300  
   301  // Expand subsitutes any {encoded} strings in the URL passed in using
   302  // the map supplied.
   303  //
   304  // This calls SetOpaque to avoid encoding of the parameters in the URL path.
   305  func Expand(u *url.URL, expansions map[string]string) {
   306  	expanded, err := uritemplates.Expand(u.Path, expansions)
   307  	if err == nil {
   308  		u.Path = expanded
   309  		SetOpaque(u)
   310  	}
   311  }
   312  
   313  // CloseBody is used to close res.Body.
   314  // Prior to calling Close, it also tries to Read a small amount to see an EOF.
   315  // Not seeing an EOF can prevent HTTP Transports from reusing connections.
   316  func CloseBody(res *http.Response) {
   317  	if res == nil || res.Body == nil {
   318  		return
   319  	}
   320  	// Justification for 3 byte reads: two for up to "\r\n" after
   321  	// a JSON/XML document, and then 1 to see EOF if we haven't yet.
   322  	// TODO(bradfitz): detect Go 1.3+ and skip these reads.
   323  	// See https://codereview.appspot.com/58240043
   324  	// and https://codereview.appspot.com/49570044
   325  	buf := make([]byte, 1)
   326  	for i := 0; i < 3; i++ {
   327  		_, err := res.Body.Read(buf)
   328  		if err != nil {
   329  			break
   330  		}
   331  	}
   332  	res.Body.Close()
   333  
   334  }
   335  
   336  // VariantType returns the type name of the given variant.
   337  // If the map doesn't contain the named key or the value is not a []interface{}, "" is returned.
   338  // This is used to support "variant" APIs that can return one of a number of different types.
   339  func VariantType(t map[string]interface{}) string {
   340  	s, _ := t["type"].(string)
   341  	return s
   342  }
   343  
   344  // ConvertVariant uses the JSON encoder/decoder to fill in the struct 'dst' with the fields found in variant 'v'.
   345  // This is used to support "variant" APIs that can return one of a number of different types.
   346  // It reports whether the conversion was successful.
   347  func ConvertVariant(v map[string]interface{}, dst interface{}) bool {
   348  	var buf bytes.Buffer
   349  	err := json.NewEncoder(&buf).Encode(v)
   350  	if err != nil {
   351  		return false
   352  	}
   353  	return json.Unmarshal(buf.Bytes(), dst) == nil
   354  }
   355  
   356  // A Field names a field to be retrieved with a partial response.
   357  // See https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
   358  //
   359  // Partial responses can dramatically reduce the amount of data that must be sent to your application.
   360  // In order to request partial responses, you can specify the full list of fields
   361  // that your application needs by adding the Fields option to your request.
   362  //
   363  // Field strings use camelCase with leading lower-case characters to identify fields within the response.
   364  //
   365  // For example, if your response has a "NextPageToken" and a slice of "Items" with "Id" fields,
   366  // you could request just those fields like this:
   367  //
   368  //     svc.Events.List().Fields("nextPageToken", "items/id").Do()
   369  //
   370  // or if you were also interested in each Item's "Updated" field, you can combine them like this:
   371  //
   372  //     svc.Events.List().Fields("nextPageToken", "items(id,updated)").Do()
   373  //
   374  // More information about field formatting can be found here:
   375  // https://developers.google.com/+/api/#fields-syntax
   376  //
   377  // Another way to find field names is through the Google API explorer:
   378  // https://developers.google.com/apis-explorer/#p/
   379  type Field string
   380  
   381  // CombineFields combines fields into a single string.
   382  func CombineFields(s []Field) string {
   383  	r := make([]string, len(s))
   384  	for i, v := range s {
   385  		r[i] = string(v)
   386  	}
   387  	return strings.Join(r, ",")
   388  }
   389  
   390  // A CallOption is an optional argument to an API call.
   391  // It should be treated as an opaque value by users of Google APIs.
   392  //
   393  // A CallOption is something that configures an API call in a way that is
   394  // not specific to that API; for instance, controlling the quota user for
   395  // an API call is common across many APIs, and is thus a CallOption.
   396  type CallOption interface {
   397  	Get() (key, value string)
   398  }
   399  
   400  // QuotaUser returns a CallOption that will set the quota user for a call.
   401  // The quota user can be used by server-side applications to control accounting.
   402  // It can be an arbitrary string up to 40 characters, and will override UserIP
   403  // if both are provided.
   404  func QuotaUser(u string) CallOption { return quotaUser(u) }
   405  
   406  type quotaUser string
   407  
   408  func (q quotaUser) Get() (string, string) { return "quotaUser", string(q) }
   409  
   410  // UserIP returns a CallOption that will set the "userIp" parameter of a call.
   411  // This should be the IP address of the originating request.
   412  func UserIP(ip string) CallOption { return userIP(ip) }
   413  
   414  type userIP string
   415  
   416  func (i userIP) Get() (string, string) { return "userIp", string(i) }
   417  
   418  // TODO: Fields too