GetObject retrieves an object from Azure cloud
( ctx context.Context, reqHeader http.Header, bucket, key, query string, )
| 18 | |
| 19 | // GetObject retrieves an object from Azure cloud |
| 20 | func (s *Storage) GetObject( |
| 21 | ctx context.Context, |
| 22 | reqHeader http.Header, |
| 23 | bucket, key, query string, |
| 24 | ) (*storage.ObjectReader, error) { |
| 25 | // If either bucket or object key is empty, return 404 |
| 26 | if len(bucket) == 0 || len(key) == 0 { |
| 27 | return storage.NewObjectNotFound( |
| 28 | "invalid GCS Storage URL: bucket name or object key are empty", |
| 29 | ), nil |
| 30 | } |
| 31 | |
| 32 | // Check if access to the bucket is allowed |
| 33 | if !common.IsBucketAllowed(bucket, s.config.AllowedBuckets, s.config.DeniedBuckets) { |
| 34 | return nil, fmt.Errorf("access to the GCS bucket %s is denied", bucket) |
| 35 | } |
| 36 | |
| 37 | var ( |
| 38 | reader *gcs.Reader |
| 39 | size int64 |
| 40 | ) |
| 41 | |
| 42 | bkt := s.client.Bucket(bucket) |
| 43 | obj := bkt.Object(key) |
| 44 | |
| 45 | if g, err := strconv.ParseInt(query, 10, 64); err == nil && g > 0 { |
| 46 | obj = obj.Generation(g) |
| 47 | } |
| 48 | |
| 49 | header := make(http.Header) |
| 50 | |
| 51 | // Try respond with partial: if that was a partial request, |
| 52 | // we either return error or Object |
| 53 | if r, err := s.tryRespondWithPartial(ctx, obj, reqHeader, header); r != nil || err != nil { |
| 54 | return r, err |
| 55 | } |
| 56 | |
| 57 | var err error |
| 58 | reader, err = obj.NewReader(ctx) |
| 59 | if err != nil { |
| 60 | return handleError(err) |
| 61 | } |
| 62 | |
| 63 | // Generate artificial ETag from CRC32 and LastModified |
| 64 | var etag [12]byte |
| 65 | binary.LittleEndian.PutUint32(etag[:4], reader.Attrs.CRC32C) |
| 66 | binary.LittleEndian.PutUint64(etag[4:], uint64(reader.Attrs.LastModified.UnixNano())) |
| 67 | |
| 68 | header.Set(httpheaders.Etag, hex.EncodeToString(etag[:])) |
| 69 | header.Set(httpheaders.LastModified, reader.Attrs.LastModified.Format(http.TimeFormat)) |
| 70 | |
| 71 | if common.IsNotModified(reqHeader, header) { |
| 72 | reader.Close() |
| 73 | return storage.NewObjectNotModified(header), nil |
| 74 | } |
| 75 | |
| 76 | size = reader.Attrs.Size |
| 77 | setHeadersFromReader(header, reader, size) |
nothing calls this directly
no test coverage detected