storage.go 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package storage
  15. import (
  16. "bytes"
  17. "crypto"
  18. "crypto/rand"
  19. "crypto/rsa"
  20. "crypto/sha256"
  21. "crypto/x509"
  22. "encoding/base64"
  23. "encoding/pem"
  24. "errors"
  25. "fmt"
  26. "io"
  27. "io/ioutil"
  28. "net/http"
  29. "net/url"
  30. "reflect"
  31. "strconv"
  32. "strings"
  33. "time"
  34. "unicode/utf8"
  35. "google.golang.org/api/option"
  36. htransport "google.golang.org/api/transport/http"
  37. "cloud.google.com/go/internal/optional"
  38. "cloud.google.com/go/internal/version"
  39. "golang.org/x/net/context"
  40. "google.golang.org/api/googleapi"
  41. raw "google.golang.org/api/storage/v1"
  42. )
  43. var (
  44. ErrBucketNotExist = errors.New("storage: bucket doesn't exist")
  45. ErrObjectNotExist = errors.New("storage: object doesn't exist")
  46. )
  47. const userAgent = "gcloud-golang-storage/20151204"
  48. const (
  49. // ScopeFullControl grants permissions to manage your
  50. // data and permissions in Google Cloud Storage.
  51. ScopeFullControl = raw.DevstorageFullControlScope
  52. // ScopeReadOnly grants permissions to
  53. // view your data in Google Cloud Storage.
  54. ScopeReadOnly = raw.DevstorageReadOnlyScope
  55. // ScopeReadWrite grants permissions to manage your
  56. // data in Google Cloud Storage.
  57. ScopeReadWrite = raw.DevstorageReadWriteScope
  58. )
  59. var xGoogHeader = fmt.Sprintf("gl-go/%s gccl/%s", version.Go(), version.Repo)
  60. func setClientHeader(headers http.Header) {
  61. headers.Set("x-goog-api-client", xGoogHeader)
  62. }
  63. // Client is a client for interacting with Google Cloud Storage.
  64. //
  65. // Clients should be reused instead of created as needed.
  66. // The methods of Client are safe for concurrent use by multiple goroutines.
  67. type Client struct {
  68. hc *http.Client
  69. raw *raw.Service
  70. }
  71. // NewClient creates a new Google Cloud Storage client.
  72. // The default scope is ScopeFullControl. To use a different scope, like ScopeReadOnly, use option.WithScopes.
  73. func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
  74. o := []option.ClientOption{
  75. option.WithScopes(ScopeFullControl),
  76. option.WithUserAgent(userAgent),
  77. }
  78. opts = append(o, opts...)
  79. hc, ep, err := htransport.NewClient(ctx, opts...)
  80. if err != nil {
  81. return nil, fmt.Errorf("dialing: %v", err)
  82. }
  83. rawService, err := raw.New(hc)
  84. if err != nil {
  85. return nil, fmt.Errorf("storage client: %v", err)
  86. }
  87. if ep != "" {
  88. rawService.BasePath = ep
  89. }
  90. return &Client{
  91. hc: hc,
  92. raw: rawService,
  93. }, nil
  94. }
  95. // Close closes the Client.
  96. //
  97. // Close need not be called at program exit.
  98. func (c *Client) Close() error {
  99. c.hc = nil
  100. return nil
  101. }
  102. // SignedURLOptions allows you to restrict the access to the signed URL.
  103. type SignedURLOptions struct {
  104. // GoogleAccessID represents the authorizer of the signed URL generation.
  105. // It is typically the Google service account client email address from
  106. // the Google Developers Console in the form of "xxx@developer.gserviceaccount.com".
  107. // Required.
  108. GoogleAccessID string
  109. // PrivateKey is the Google service account private key. It is obtainable
  110. // from the Google Developers Console.
  111. // At https://console.developers.google.com/project/<your-project-id>/apiui/credential,
  112. // create a service account client ID or reuse one of your existing service account
  113. // credentials. Click on the "Generate new P12 key" to generate and download
  114. // a new private key. Once you download the P12 file, use the following command
  115. // to convert it into a PEM file.
  116. //
  117. // $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
  118. //
  119. // Provide the contents of the PEM file as a byte slice.
  120. // Exactly one of PrivateKey or SignBytes must be non-nil.
  121. PrivateKey []byte
  122. // SignBytes is a function for implementing custom signing.
  123. // If your application is running on Google App Engine, you can use appengine's internal signing function:
  124. // ctx := appengine.NewContext(request)
  125. // acc, _ := appengine.ServiceAccount(ctx)
  126. // url, err := SignedURL("bucket", "object", &SignedURLOptions{
  127. // GoogleAccessID: acc,
  128. // SignBytes: func(b []byte) ([]byte, error) {
  129. // _, signedBytes, err := appengine.SignBytes(ctx, b)
  130. // return signedBytes, err
  131. // },
  132. // // etc.
  133. // })
  134. //
  135. // Exactly one of PrivateKey or SignBytes must be non-nil.
  136. SignBytes func([]byte) ([]byte, error)
  137. // Method is the HTTP method to be used with the signed URL.
  138. // Signed URLs can be used with GET, HEAD, PUT, and DELETE requests.
  139. // Required.
  140. Method string
  141. // Expires is the expiration time on the signed URL. It must be
  142. // a datetime in the future.
  143. // Required.
  144. Expires time.Time
  145. // ContentType is the content type header the client must provide
  146. // to use the generated signed URL.
  147. // Optional.
  148. ContentType string
  149. // Headers is a list of extention headers the client must provide
  150. // in order to use the generated signed URL.
  151. // Optional.
  152. Headers []string
  153. // MD5 is the base64 encoded MD5 checksum of the file.
  154. // If provided, the client should provide the exact value on the request
  155. // header in order to use the signed URL.
  156. // Optional.
  157. MD5 string
  158. }
  159. // SignedURL returns a URL for the specified object. Signed URLs allow
  160. // the users access to a restricted resource for a limited time without having a
  161. // Google account or signing in. For more information about the signed
  162. // URLs, see https://cloud.google.com/storage/docs/accesscontrol#Signed-URLs.
  163. func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
  164. if opts == nil {
  165. return "", errors.New("storage: missing required SignedURLOptions")
  166. }
  167. if opts.GoogleAccessID == "" {
  168. return "", errors.New("storage: missing required GoogleAccessID")
  169. }
  170. if (opts.PrivateKey == nil) == (opts.SignBytes == nil) {
  171. return "", errors.New("storage: exactly one of PrivateKey or SignedBytes must be set")
  172. }
  173. if opts.Method == "" {
  174. return "", errors.New("storage: missing required method option")
  175. }
  176. if opts.Expires.IsZero() {
  177. return "", errors.New("storage: missing required expires option")
  178. }
  179. if opts.MD5 != "" {
  180. md5, err := base64.StdEncoding.DecodeString(opts.MD5)
  181. if err != nil || len(md5) != 16 {
  182. return "", errors.New("storage: invalid MD5 checksum")
  183. }
  184. }
  185. signBytes := opts.SignBytes
  186. if opts.PrivateKey != nil {
  187. key, err := parseKey(opts.PrivateKey)
  188. if err != nil {
  189. return "", err
  190. }
  191. signBytes = func(b []byte) ([]byte, error) {
  192. sum := sha256.Sum256(b)
  193. return rsa.SignPKCS1v15(
  194. rand.Reader,
  195. key,
  196. crypto.SHA256,
  197. sum[:],
  198. )
  199. }
  200. }
  201. u := &url.URL{
  202. Path: fmt.Sprintf("/%s/%s", bucket, name),
  203. }
  204. buf := &bytes.Buffer{}
  205. fmt.Fprintf(buf, "%s\n", opts.Method)
  206. fmt.Fprintf(buf, "%s\n", opts.MD5)
  207. fmt.Fprintf(buf, "%s\n", opts.ContentType)
  208. fmt.Fprintf(buf, "%d\n", opts.Expires.Unix())
  209. if len(opts.Headers) > 0 {
  210. fmt.Fprintf(buf, "%s\n", strings.Join(opts.Headers, "\n"))
  211. }
  212. fmt.Fprintf(buf, "%s", u.String())
  213. b, err := signBytes(buf.Bytes())
  214. if err != nil {
  215. return "", err
  216. }
  217. encoded := base64.StdEncoding.EncodeToString(b)
  218. u.Scheme = "https"
  219. u.Host = "storage.googleapis.com"
  220. q := u.Query()
  221. q.Set("GoogleAccessId", opts.GoogleAccessID)
  222. q.Set("Expires", fmt.Sprintf("%d", opts.Expires.Unix()))
  223. q.Set("Signature", string(encoded))
  224. u.RawQuery = q.Encode()
  225. return u.String(), nil
  226. }
  227. // ObjectHandle provides operations on an object in a Google Cloud Storage bucket.
  228. // Use BucketHandle.Object to get a handle.
  229. type ObjectHandle struct {
  230. c *Client
  231. bucket string
  232. object string
  233. acl ACLHandle
  234. gen int64 // a negative value indicates latest
  235. conds *Conditions
  236. encryptionKey []byte // AES-256 key
  237. userProject string // for requester-pays buckets
  238. }
  239. // ACL provides access to the object's access control list.
  240. // This controls who can read and write this object.
  241. // This call does not perform any network operations.
  242. func (o *ObjectHandle) ACL() *ACLHandle {
  243. return &o.acl
  244. }
  245. // Generation returns a new ObjectHandle that operates on a specific generation
  246. // of the object.
  247. // By default, the handle operates on the latest generation. Not
  248. // all operations work when given a specific generation; check the API
  249. // endpoints at https://cloud.google.com/storage/docs/json_api/ for details.
  250. func (o *ObjectHandle) Generation(gen int64) *ObjectHandle {
  251. o2 := *o
  252. o2.gen = gen
  253. return &o2
  254. }
  255. // If returns a new ObjectHandle that applies a set of preconditions.
  256. // Preconditions already set on the ObjectHandle are ignored.
  257. // Operations on the new handle will only occur if the preconditions are
  258. // satisfied. See https://cloud.google.com/storage/docs/generations-preconditions
  259. // for more details.
  260. func (o *ObjectHandle) If(conds Conditions) *ObjectHandle {
  261. o2 := *o
  262. o2.conds = &conds
  263. return &o2
  264. }
  265. // Key returns a new ObjectHandle that uses the supplied encryption
  266. // key to encrypt and decrypt the object's contents.
  267. //
  268. // Encryption key must be a 32-byte AES-256 key.
  269. // See https://cloud.google.com/storage/docs/encryption for details.
  270. func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle {
  271. o2 := *o
  272. o2.encryptionKey = encryptionKey
  273. return &o2
  274. }
  275. // Attrs returns meta information about the object.
  276. // ErrObjectNotExist will be returned if the object is not found.
  277. func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
  278. if err := o.validate(); err != nil {
  279. return nil, err
  280. }
  281. call := o.c.raw.Objects.Get(o.bucket, o.object).Projection("full").Context(ctx)
  282. if err := applyConds("Attrs", o.gen, o.conds, call); err != nil {
  283. return nil, err
  284. }
  285. if o.userProject != "" {
  286. call.UserProject(o.userProject)
  287. }
  288. if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
  289. return nil, err
  290. }
  291. var obj *raw.Object
  292. var err error
  293. setClientHeader(call.Header())
  294. err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
  295. if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
  296. return nil, ErrObjectNotExist
  297. }
  298. if err != nil {
  299. return nil, err
  300. }
  301. return newObject(obj), nil
  302. }
  303. // Update updates an object with the provided attributes.
  304. // All zero-value attributes are ignored.
  305. // ErrObjectNotExist will be returned if the object is not found.
  306. func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (*ObjectAttrs, error) {
  307. if err := o.validate(); err != nil {
  308. return nil, err
  309. }
  310. var attrs ObjectAttrs
  311. // Lists of fields to send, and set to null, in the JSON.
  312. var forceSendFields, nullFields []string
  313. if uattrs.ContentType != nil {
  314. attrs.ContentType = optional.ToString(uattrs.ContentType)
  315. forceSendFields = append(forceSendFields, "ContentType")
  316. }
  317. if uattrs.ContentLanguage != nil {
  318. attrs.ContentLanguage = optional.ToString(uattrs.ContentLanguage)
  319. // For ContentLanguage It's an error to send the empty string.
  320. // Instead we send a null.
  321. if attrs.ContentLanguage == "" {
  322. nullFields = append(nullFields, "ContentLanguage")
  323. } else {
  324. forceSendFields = append(forceSendFields, "ContentLanguage")
  325. }
  326. }
  327. if uattrs.ContentEncoding != nil {
  328. attrs.ContentEncoding = optional.ToString(uattrs.ContentEncoding)
  329. forceSendFields = append(forceSendFields, "ContentEncoding")
  330. }
  331. if uattrs.ContentDisposition != nil {
  332. attrs.ContentDisposition = optional.ToString(uattrs.ContentDisposition)
  333. forceSendFields = append(forceSendFields, "ContentDisposition")
  334. }
  335. if uattrs.CacheControl != nil {
  336. attrs.CacheControl = optional.ToString(uattrs.CacheControl)
  337. forceSendFields = append(forceSendFields, "CacheControl")
  338. }
  339. if uattrs.Metadata != nil {
  340. attrs.Metadata = uattrs.Metadata
  341. if len(attrs.Metadata) == 0 {
  342. // Sending the empty map is a no-op. We send null instead.
  343. nullFields = append(nullFields, "Metadata")
  344. } else {
  345. forceSendFields = append(forceSendFields, "Metadata")
  346. }
  347. }
  348. if uattrs.ACL != nil {
  349. attrs.ACL = uattrs.ACL
  350. // It's an error to attempt to delete the ACL, so
  351. // we don't append to nullFields here.
  352. forceSendFields = append(forceSendFields, "Acl")
  353. }
  354. rawObj := attrs.toRawObject(o.bucket)
  355. rawObj.ForceSendFields = forceSendFields
  356. rawObj.NullFields = nullFields
  357. call := o.c.raw.Objects.Patch(o.bucket, o.object, rawObj).Projection("full").Context(ctx)
  358. if err := applyConds("Update", o.gen, o.conds, call); err != nil {
  359. return nil, err
  360. }
  361. if o.userProject != "" {
  362. call.UserProject(o.userProject)
  363. }
  364. if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
  365. return nil, err
  366. }
  367. var obj *raw.Object
  368. var err error
  369. setClientHeader(call.Header())
  370. err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
  371. if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
  372. return nil, ErrObjectNotExist
  373. }
  374. if err != nil {
  375. return nil, err
  376. }
  377. return newObject(obj), nil
  378. }
  379. // ObjectAttrsToUpdate is used to update the attributes of an object.
  380. // Only fields set to non-nil values will be updated.
  381. // Set a field to its zero value to delete it.
  382. //
  383. // For example, to change ContentType and delete ContentEncoding and
  384. // Metadata, use
  385. // ObjectAttrsToUpdate{
  386. // ContentType: "text/html",
  387. // ContentEncoding: "",
  388. // Metadata: map[string]string{},
  389. // }
  390. type ObjectAttrsToUpdate struct {
  391. ContentType optional.String
  392. ContentLanguage optional.String
  393. ContentEncoding optional.String
  394. ContentDisposition optional.String
  395. CacheControl optional.String
  396. Metadata map[string]string // set to map[string]string{} to delete
  397. ACL []ACLRule
  398. }
  399. // Delete deletes the single specified object.
  400. func (o *ObjectHandle) Delete(ctx context.Context) error {
  401. if err := o.validate(); err != nil {
  402. return err
  403. }
  404. call := o.c.raw.Objects.Delete(o.bucket, o.object).Context(ctx)
  405. if err := applyConds("Delete", o.gen, o.conds, call); err != nil {
  406. return err
  407. }
  408. if o.userProject != "" {
  409. call.UserProject(o.userProject)
  410. }
  411. // Encryption doesn't apply to Delete.
  412. setClientHeader(call.Header())
  413. err := runWithRetry(ctx, func() error { return call.Do() })
  414. switch e := err.(type) {
  415. case nil:
  416. return nil
  417. case *googleapi.Error:
  418. if e.Code == http.StatusNotFound {
  419. return ErrObjectNotExist
  420. }
  421. }
  422. return err
  423. }
  424. // NewReader creates a new Reader to read the contents of the
  425. // object.
  426. // ErrObjectNotExist will be returned if the object is not found.
  427. //
  428. // The caller must call Close on the returned Reader when done reading.
  429. func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
  430. return o.NewRangeReader(ctx, 0, -1)
  431. }
  432. // NewRangeReader reads part of an object, reading at most length bytes
  433. // starting at the given offset. If length is negative, the object is read
  434. // until the end.
  435. func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (*Reader, error) {
  436. if err := o.validate(); err != nil {
  437. return nil, err
  438. }
  439. if offset < 0 {
  440. return nil, fmt.Errorf("storage: invalid offset %d < 0", offset)
  441. }
  442. if o.conds != nil {
  443. if err := o.conds.validate("NewRangeReader"); err != nil {
  444. return nil, err
  445. }
  446. }
  447. u := &url.URL{
  448. Scheme: "https",
  449. Host: "storage.googleapis.com",
  450. Path: fmt.Sprintf("/%s/%s", o.bucket, o.object),
  451. RawQuery: conditionsQuery(o.gen, o.conds),
  452. }
  453. verb := "GET"
  454. if length == 0 {
  455. verb = "HEAD"
  456. }
  457. req, err := http.NewRequest(verb, u.String(), nil)
  458. if err != nil {
  459. return nil, err
  460. }
  461. req = withContext(req, ctx)
  462. if length < 0 && offset > 0 {
  463. req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
  464. } else if length > 0 {
  465. req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1))
  466. }
  467. if o.userProject != "" {
  468. req.Header.Set("X-Goog-User-Project", o.userProject)
  469. }
  470. if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
  471. return nil, err
  472. }
  473. var res *http.Response
  474. err = runWithRetry(ctx, func() error {
  475. res, err = o.c.hc.Do(req)
  476. if err != nil {
  477. return err
  478. }
  479. if res.StatusCode == http.StatusNotFound {
  480. res.Body.Close()
  481. return ErrObjectNotExist
  482. }
  483. if res.StatusCode < 200 || res.StatusCode > 299 {
  484. body, _ := ioutil.ReadAll(res.Body)
  485. res.Body.Close()
  486. return &googleapi.Error{
  487. Code: res.StatusCode,
  488. Header: res.Header,
  489. Body: string(body),
  490. }
  491. }
  492. if offset > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
  493. res.Body.Close()
  494. return errors.New("storage: partial request not satisfied")
  495. }
  496. return nil
  497. })
  498. if err != nil {
  499. return nil, err
  500. }
  501. var size int64 // total size of object, even if a range was requested.
  502. if res.StatusCode == http.StatusPartialContent {
  503. cr := strings.TrimSpace(res.Header.Get("Content-Range"))
  504. if !strings.HasPrefix(cr, "bytes ") || !strings.Contains(cr, "/") {
  505. return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
  506. }
  507. size, err = strconv.ParseInt(cr[strings.LastIndex(cr, "/")+1:], 10, 64)
  508. if err != nil {
  509. return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
  510. }
  511. } else {
  512. size = res.ContentLength
  513. }
  514. remain := res.ContentLength
  515. body := res.Body
  516. if length == 0 {
  517. remain = 0
  518. body.Close()
  519. body = emptyBody
  520. }
  521. var (
  522. checkCRC bool
  523. crc uint32
  524. )
  525. // Even if there is a CRC header, we can't compute the hash on partial data.
  526. if remain == size {
  527. crc, checkCRC = parseCRC32c(res)
  528. }
  529. return &Reader{
  530. body: body,
  531. size: size,
  532. remain: remain,
  533. contentType: res.Header.Get("Content-Type"),
  534. wantCRC: crc,
  535. checkCRC: checkCRC,
  536. }, nil
  537. }
  538. func parseCRC32c(res *http.Response) (uint32, bool) {
  539. const prefix = "crc32c="
  540. for _, spec := range res.Header["X-Goog-Hash"] {
  541. if strings.HasPrefix(spec, prefix) {
  542. c, err := decodeUint32(spec[len(prefix):])
  543. if err == nil {
  544. return c, true
  545. }
  546. }
  547. }
  548. return 0, false
  549. }
  550. var emptyBody = ioutil.NopCloser(strings.NewReader(""))
  551. // NewWriter returns a storage Writer that writes to the GCS object
  552. // associated with this ObjectHandle.
  553. //
  554. // A new object will be created unless an object with this name already exists.
  555. // Otherwise any previous object with the same name will be replaced.
  556. // The object will not be available (and any previous object will remain)
  557. // until Close has been called.
  558. //
  559. // Attributes can be set on the object by modifying the returned Writer's
  560. // ObjectAttrs field before the first call to Write. If no ContentType
  561. // attribute is specified, the content type will be automatically sniffed
  562. // using net/http.DetectContentType.
  563. //
  564. // It is the caller's responsibility to call Close when writing is done.
  565. func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer {
  566. return &Writer{
  567. ctx: ctx,
  568. o: o,
  569. donec: make(chan struct{}),
  570. ObjectAttrs: ObjectAttrs{Name: o.object},
  571. ChunkSize: googleapi.DefaultUploadChunkSize,
  572. }
  573. }
  574. func (o *ObjectHandle) validate() error {
  575. if o.bucket == "" {
  576. return errors.New("storage: bucket name is empty")
  577. }
  578. if o.object == "" {
  579. return errors.New("storage: object name is empty")
  580. }
  581. if !utf8.ValidString(o.object) {
  582. return fmt.Errorf("storage: object name %q is not valid UTF-8", o.object)
  583. }
  584. return nil
  585. }
  586. // parseKey converts the binary contents of a private key file
  587. // to an *rsa.PrivateKey. It detects whether the private key is in a
  588. // PEM container or not. If so, it extracts the the private key
  589. // from PEM container before conversion. It only supports PEM
  590. // containers with no passphrase.
  591. func parseKey(key []byte) (*rsa.PrivateKey, error) {
  592. if block, _ := pem.Decode(key); block != nil {
  593. key = block.Bytes
  594. }
  595. parsedKey, err := x509.ParsePKCS8PrivateKey(key)
  596. if err != nil {
  597. parsedKey, err = x509.ParsePKCS1PrivateKey(key)
  598. if err != nil {
  599. return nil, err
  600. }
  601. }
  602. parsed, ok := parsedKey.(*rsa.PrivateKey)
  603. if !ok {
  604. return nil, errors.New("oauth2: private key is invalid")
  605. }
  606. return parsed, nil
  607. }
  608. func toRawObjectACL(oldACL []ACLRule) []*raw.ObjectAccessControl {
  609. var acl []*raw.ObjectAccessControl
  610. if len(oldACL) > 0 {
  611. acl = make([]*raw.ObjectAccessControl, len(oldACL))
  612. for i, rule := range oldACL {
  613. acl[i] = &raw.ObjectAccessControl{
  614. Entity: string(rule.Entity),
  615. Role: string(rule.Role),
  616. }
  617. }
  618. }
  619. return acl
  620. }
  621. // toRawObject copies the editable attributes from o to the raw library's Object type.
  622. func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object {
  623. acl := toRawObjectACL(o.ACL)
  624. return &raw.Object{
  625. Bucket: bucket,
  626. Name: o.Name,
  627. ContentType: o.ContentType,
  628. ContentEncoding: o.ContentEncoding,
  629. ContentLanguage: o.ContentLanguage,
  630. CacheControl: o.CacheControl,
  631. ContentDisposition: o.ContentDisposition,
  632. StorageClass: o.StorageClass,
  633. Acl: acl,
  634. Metadata: o.Metadata,
  635. }
  636. }
  637. // ObjectAttrs represents the metadata for a Google Cloud Storage (GCS) object.
  638. type ObjectAttrs struct {
  639. // Bucket is the name of the bucket containing this GCS object.
  640. // This field is read-only.
  641. Bucket string
  642. // Name is the name of the object within the bucket.
  643. // This field is read-only.
  644. Name string
  645. // ContentType is the MIME type of the object's content.
  646. ContentType string
  647. // ContentLanguage is the content language of the object's content.
  648. ContentLanguage string
  649. // CacheControl is the Cache-Control header to be sent in the response
  650. // headers when serving the object data.
  651. CacheControl string
  652. // ACL is the list of access control rules for the object.
  653. ACL []ACLRule
  654. // Owner is the owner of the object. This field is read-only.
  655. //
  656. // If non-zero, it is in the form of "user-<userId>".
  657. Owner string
  658. // Size is the length of the object's content. This field is read-only.
  659. Size int64
  660. // ContentEncoding is the encoding of the object's content.
  661. ContentEncoding string
  662. // ContentDisposition is the optional Content-Disposition header of the object
  663. // sent in the response headers.
  664. ContentDisposition string
  665. // MD5 is the MD5 hash of the object's content. This field is read-only.
  666. MD5 []byte
  667. // CRC32C is the CRC32 checksum of the object's content using
  668. // the Castagnoli93 polynomial. This field is read-only.
  669. CRC32C uint32
  670. // MediaLink is an URL to the object's content. This field is read-only.
  671. MediaLink string
  672. // Metadata represents user-provided metadata, in key/value pairs.
  673. // It can be nil if no metadata is provided.
  674. Metadata map[string]string
  675. // Generation is the generation number of the object's content.
  676. // This field is read-only.
  677. Generation int64
  678. // Metageneration is the version of the metadata for this
  679. // object at this generation. This field is used for preconditions
  680. // and for detecting changes in metadata. A metageneration number
  681. // is only meaningful in the context of a particular generation
  682. // of a particular object. This field is read-only.
  683. Metageneration int64
  684. // StorageClass is the storage class of the object.
  685. // This value defines how objects in the bucket are stored and
  686. // determines the SLA and the cost of storage. Typical values are
  687. // "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD"
  688. // and "DURABLE_REDUCED_AVAILABILITY".
  689. // It defaults to "STANDARD", which is equivalent to "MULTI_REGIONAL"
  690. // or "REGIONAL" depending on the bucket's location settings.
  691. StorageClass string
  692. // Created is the time the object was created. This field is read-only.
  693. Created time.Time
  694. // Deleted is the time the object was deleted.
  695. // If not deleted, it is the zero value. This field is read-only.
  696. Deleted time.Time
  697. // Updated is the creation or modification time of the object.
  698. // For buckets with versioning enabled, changing an object's
  699. // metadata does not change this property. This field is read-only.
  700. Updated time.Time
  701. // CustomerKeySHA256 is the base64-encoded SHA-256 hash of the
  702. // customer-supplied encryption key for the object. It is empty if there is
  703. // no customer-supplied encryption key.
  704. // See // https://cloud.google.com/storage/docs/encryption for more about
  705. // encryption in Google Cloud Storage.
  706. CustomerKeySHA256 string
  707. // Prefix is set only for ObjectAttrs which represent synthetic "directory
  708. // entries" when iterating over buckets using Query.Delimiter. See
  709. // ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
  710. // populated.
  711. Prefix string
  712. }
  713. // convertTime converts a time in RFC3339 format to time.Time.
  714. // If any error occurs in parsing, the zero-value time.Time is silently returned.
  715. func convertTime(t string) time.Time {
  716. var r time.Time
  717. if t != "" {
  718. r, _ = time.Parse(time.RFC3339, t)
  719. }
  720. return r
  721. }
  722. func newObject(o *raw.Object) *ObjectAttrs {
  723. if o == nil {
  724. return nil
  725. }
  726. acl := make([]ACLRule, len(o.Acl))
  727. for i, rule := range o.Acl {
  728. acl[i] = ACLRule{
  729. Entity: ACLEntity(rule.Entity),
  730. Role: ACLRole(rule.Role),
  731. }
  732. }
  733. owner := ""
  734. if o.Owner != nil {
  735. owner = o.Owner.Entity
  736. }
  737. md5, _ := base64.StdEncoding.DecodeString(o.Md5Hash)
  738. crc32c, _ := decodeUint32(o.Crc32c)
  739. var sha256 string
  740. if o.CustomerEncryption != nil {
  741. sha256 = o.CustomerEncryption.KeySha256
  742. }
  743. return &ObjectAttrs{
  744. Bucket: o.Bucket,
  745. Name: o.Name,
  746. ContentType: o.ContentType,
  747. ContentLanguage: o.ContentLanguage,
  748. CacheControl: o.CacheControl,
  749. ACL: acl,
  750. Owner: owner,
  751. ContentEncoding: o.ContentEncoding,
  752. Size: int64(o.Size),
  753. MD5: md5,
  754. CRC32C: crc32c,
  755. MediaLink: o.MediaLink,
  756. Metadata: o.Metadata,
  757. Generation: o.Generation,
  758. Metageneration: o.Metageneration,
  759. StorageClass: o.StorageClass,
  760. CustomerKeySHA256: sha256,
  761. Created: convertTime(o.TimeCreated),
  762. Deleted: convertTime(o.TimeDeleted),
  763. Updated: convertTime(o.Updated),
  764. }
  765. }
  766. // Decode a uint32 encoded in Base64 in big-endian byte order.
  767. func decodeUint32(b64 string) (uint32, error) {
  768. d, err := base64.StdEncoding.DecodeString(b64)
  769. if err != nil {
  770. return 0, err
  771. }
  772. if len(d) != 4 {
  773. return 0, fmt.Errorf("storage: %q does not encode a 32-bit value", d)
  774. }
  775. return uint32(d[0])<<24 + uint32(d[1])<<16 + uint32(d[2])<<8 + uint32(d[3]), nil
  776. }
  777. // Encode a uint32 as Base64 in big-endian byte order.
  778. func encodeUint32(u uint32) string {
  779. b := []byte{byte(u >> 24), byte(u >> 16), byte(u >> 8), byte(u)}
  780. return base64.StdEncoding.EncodeToString(b)
  781. }
  782. // Query represents a query to filter objects from a bucket.
  783. type Query struct {
  784. // Delimiter returns results in a directory-like fashion.
  785. // Results will contain only objects whose names, aside from the
  786. // prefix, do not contain delimiter. Objects whose names,
  787. // aside from the prefix, contain delimiter will have their name,
  788. // truncated after the delimiter, returned in prefixes.
  789. // Duplicate prefixes are omitted.
  790. // Optional.
  791. Delimiter string
  792. // Prefix is the prefix filter to query objects
  793. // whose names begin with this prefix.
  794. // Optional.
  795. Prefix string
  796. // Versions indicates whether multiple versions of the same
  797. // object will be included in the results.
  798. Versions bool
  799. }
  800. // contentTyper implements ContentTyper to enable an
  801. // io.ReadCloser to specify its MIME type.
  802. type contentTyper struct {
  803. io.Reader
  804. t string
  805. }
  806. func (c *contentTyper) ContentType() string {
  807. return c.t
  808. }
  809. // Conditions constrain methods to act on specific generations of
  810. // objects.
  811. //
  812. // The zero value is an empty set of constraints. Not all conditions or
  813. // combinations of conditions are applicable to all methods.
  814. // See https://cloud.google.com/storage/docs/generations-preconditions
  815. // for details on how these operate.
  816. type Conditions struct {
  817. // Generation constraints.
  818. // At most one of the following can be set to a non-zero value.
  819. // GenerationMatch specifies that the object must have the given generation
  820. // for the operation to occur.
  821. // If GenerationMatch is zero, it has no effect.
  822. // Use DoesNotExist to specify that the object does not exist in the bucket.
  823. GenerationMatch int64
  824. // GenerationNotMatch specifies that the object must not have the given
  825. // generation for the operation to occur.
  826. // If GenerationNotMatch is zero, it has no effect.
  827. GenerationNotMatch int64
  828. // DoesNotExist specifies that the object must not exist in the bucket for
  829. // the operation to occur.
  830. // If DoesNotExist is false, it has no effect.
  831. DoesNotExist bool
  832. // Metadata generation constraints.
  833. // At most one of the following can be set to a non-zero value.
  834. // MetagenerationMatch specifies that the object must have the given
  835. // metageneration for the operation to occur.
  836. // If MetagenerationMatch is zero, it has no effect.
  837. MetagenerationMatch int64
  838. // MetagenerationNotMatch specifies that the object must not have the given
  839. // metageneration for the operation to occur.
  840. // If MetagenerationNotMatch is zero, it has no effect.
  841. MetagenerationNotMatch int64
  842. }
  843. func (c *Conditions) validate(method string) error {
  844. if *c == (Conditions{}) {
  845. return fmt.Errorf("storage: %s: empty conditions", method)
  846. }
  847. if !c.isGenerationValid() {
  848. return fmt.Errorf("storage: %s: multiple conditions specified for generation", method)
  849. }
  850. if !c.isMetagenerationValid() {
  851. return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
  852. }
  853. return nil
  854. }
  855. func (c *Conditions) isGenerationValid() bool {
  856. n := 0
  857. if c.GenerationMatch != 0 {
  858. n++
  859. }
  860. if c.GenerationNotMatch != 0 {
  861. n++
  862. }
  863. if c.DoesNotExist {
  864. n++
  865. }
  866. return n <= 1
  867. }
  868. func (c *Conditions) isMetagenerationValid() bool {
  869. return c.MetagenerationMatch == 0 || c.MetagenerationNotMatch == 0
  870. }
  871. // applyConds modifies the provided call using the conditions in conds.
  872. // call is something that quacks like a *raw.WhateverCall.
  873. func applyConds(method string, gen int64, conds *Conditions, call interface{}) error {
  874. cval := reflect.ValueOf(call)
  875. if gen >= 0 {
  876. if !setConditionField(cval, "Generation", gen) {
  877. return fmt.Errorf("storage: %s: generation not supported", method)
  878. }
  879. }
  880. if conds == nil {
  881. return nil
  882. }
  883. if err := conds.validate(method); err != nil {
  884. return err
  885. }
  886. switch {
  887. case conds.GenerationMatch != 0:
  888. if !setConditionField(cval, "IfGenerationMatch", conds.GenerationMatch) {
  889. return fmt.Errorf("storage: %s: ifGenerationMatch not supported", method)
  890. }
  891. case conds.GenerationNotMatch != 0:
  892. if !setConditionField(cval, "IfGenerationNotMatch", conds.GenerationNotMatch) {
  893. return fmt.Errorf("storage: %s: ifGenerationNotMatch not supported", method)
  894. }
  895. case conds.DoesNotExist:
  896. if !setConditionField(cval, "IfGenerationMatch", int64(0)) {
  897. return fmt.Errorf("storage: %s: DoesNotExist not supported", method)
  898. }
  899. }
  900. switch {
  901. case conds.MetagenerationMatch != 0:
  902. if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
  903. return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
  904. }
  905. case conds.MetagenerationNotMatch != 0:
  906. if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
  907. return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
  908. }
  909. }
  910. return nil
  911. }
  912. func applySourceConds(gen int64, conds *Conditions, call *raw.ObjectsRewriteCall) error {
  913. if gen >= 0 {
  914. call.SourceGeneration(gen)
  915. }
  916. if conds == nil {
  917. return nil
  918. }
  919. if err := conds.validate("CopyTo source"); err != nil {
  920. return err
  921. }
  922. switch {
  923. case conds.GenerationMatch != 0:
  924. call.IfSourceGenerationMatch(conds.GenerationMatch)
  925. case conds.GenerationNotMatch != 0:
  926. call.IfSourceGenerationNotMatch(conds.GenerationNotMatch)
  927. case conds.DoesNotExist:
  928. call.IfSourceGenerationMatch(0)
  929. }
  930. switch {
  931. case conds.MetagenerationMatch != 0:
  932. call.IfSourceMetagenerationMatch(conds.MetagenerationMatch)
  933. case conds.MetagenerationNotMatch != 0:
  934. call.IfSourceMetagenerationNotMatch(conds.MetagenerationNotMatch)
  935. }
  936. return nil
  937. }
  938. // setConditionField sets a field on a *raw.WhateverCall.
  939. // We can't use anonymous interfaces because the return type is
  940. // different, since the field setters are builders.
  941. func setConditionField(call reflect.Value, name string, value interface{}) bool {
  942. m := call.MethodByName(name)
  943. if !m.IsValid() {
  944. return false
  945. }
  946. m.Call([]reflect.Value{reflect.ValueOf(value)})
  947. return true
  948. }
  949. // conditionsQuery returns the generation and conditions as a URL query
  950. // string suitable for URL.RawQuery. It assumes that the conditions
  951. // have been validated.
  952. func conditionsQuery(gen int64, conds *Conditions) string {
  953. // URL escapes are elided because integer strings are URL-safe.
  954. var buf []byte
  955. appendParam := func(s string, n int64) {
  956. if len(buf) > 0 {
  957. buf = append(buf, '&')
  958. }
  959. buf = append(buf, s...)
  960. buf = strconv.AppendInt(buf, n, 10)
  961. }
  962. if gen >= 0 {
  963. appendParam("generation=", gen)
  964. }
  965. if conds == nil {
  966. return string(buf)
  967. }
  968. switch {
  969. case conds.GenerationMatch != 0:
  970. appendParam("ifGenerationMatch=", conds.GenerationMatch)
  971. case conds.GenerationNotMatch != 0:
  972. appendParam("ifGenerationNotMatch=", conds.GenerationNotMatch)
  973. case conds.DoesNotExist:
  974. appendParam("ifGenerationMatch=", 0)
  975. }
  976. switch {
  977. case conds.MetagenerationMatch != 0:
  978. appendParam("ifMetagenerationMatch=", conds.MetagenerationMatch)
  979. case conds.MetagenerationNotMatch != 0:
  980. appendParam("ifMetagenerationNotMatch=", conds.MetagenerationNotMatch)
  981. }
  982. return string(buf)
  983. }
  984. // composeSourceObj wraps a *raw.ComposeRequestSourceObjects, but adds the methods
  985. // that modifyCall searches for by name.
  986. type composeSourceObj struct {
  987. src *raw.ComposeRequestSourceObjects
  988. }
  989. func (c composeSourceObj) Generation(gen int64) {
  990. c.src.Generation = gen
  991. }
  992. func (c composeSourceObj) IfGenerationMatch(gen int64) {
  993. // It's safe to overwrite ObjectPreconditions, since its only field is
  994. // IfGenerationMatch.
  995. c.src.ObjectPreconditions = &raw.ComposeRequestSourceObjectsObjectPreconditions{
  996. IfGenerationMatch: gen,
  997. }
  998. }
  999. func setEncryptionHeaders(headers http.Header, key []byte, copySource bool) error {
  1000. if key == nil {
  1001. return nil
  1002. }
  1003. // TODO(jbd): Ask the API team to return a more user-friendly error
  1004. // and avoid doing this check at the client level.
  1005. if len(key) != 32 {
  1006. return errors.New("storage: not a 32-byte AES-256 key")
  1007. }
  1008. var cs string
  1009. if copySource {
  1010. cs = "copy-source-"
  1011. }
  1012. headers.Set("x-goog-"+cs+"encryption-algorithm", "AES256")
  1013. headers.Set("x-goog-"+cs+"encryption-key", base64.StdEncoding.EncodeToString(key))
  1014. keyHash := sha256.Sum256(key)
  1015. headers.Set("x-goog-"+cs+"encryption-key-sha256", base64.StdEncoding.EncodeToString(keyHash[:]))
  1016. return nil
  1017. }
  1018. // TODO(jbd): Add storage.objects.watch.