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