Skip to content

Commit 1a5ce97

Browse files
authored
Merge pull request #223 from avast/fix/gcs_null_metadata
fix: GCS backend - Correctly handle missing (null) Blob metadata
2 parents b000303 + 1b2f0c2 commit 1a5ce97

File tree

2 files changed

+11
-8
lines changed

2 files changed

+11
-8
lines changed

gcs/src/main/scala/com/avast/clients/storage/gcs/GcsStorageBackend.scala

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import cats.effect.implicits.catsEffectSyntaxBracket
55
import cats.effect.{Blocker, ContextShift, Resource, Sync}
66
import cats.syntax.all._
77
import com.avast.clients.storage.compression.ZstdDecompressOutputStream
8-
import com.avast.clients.storage.gcs.GcsStorageBackend.composeBlobPath
8+
import com.avast.clients.storage.gcs.GcsStorageBackend.{composeBlobPath, getMetadataValue, CompressionTypeHeader, OriginalSizeHeader}
99
import com.avast.clients.storage.{ConfigurationException, GetResult, HeadResult, StorageBackend, StorageException}
1010
import com.avast.scala.hashes.Sha256
1111
import com.google.auth.oauth2.ServiceAccountCredentials
@@ -35,10 +35,10 @@ class GcsStorageBackend[F[_]: Sync: ContextShift](storageClient: Storage, bucket
3535
blob <- getBlob(sha256)
3636
result = blob match {
3737
case Some(blob) =>
38-
blob.getMetadata.get(GcsStorageBackend.OriginalSizeHeader) match {
39-
case null =>
38+
getMetadataValue(blob, OriginalSizeHeader) match {
39+
case None =>
4040
HeadResult.Exists(blob.getSize)
41-
case originalSize =>
41+
case Some(originalSize) =>
4242
HeadResult.Exists(originalSize.toLong)
4343
}
4444
case None =>
@@ -108,9 +108,6 @@ class GcsStorageBackend[F[_]: Sync: ContextShift](storageClient: Storage, bucket
108108
}
109109

110110
private def downloadBlobToFile(blob: Blob, fileStream: OutputStream): F[(Long, Sha256)] = {
111-
def getCompressionType: Option[String] = {
112-
Option(blob.getMetadata.get(GcsStorageBackend.CompressionTypeHeader)).map(_.toLowerCase)
113-
}
114111

115112
Sync[F]
116113
.delay {
@@ -120,7 +117,7 @@ class GcsStorageBackend[F[_]: Sync: ContextShift](storageClient: Storage, bucket
120117
}
121118
.bracket {
122119
case (countingStream, hashingStream) => {
123-
getCompressionType match {
120+
getMetadataValue(blob, CompressionTypeHeader) match {
124121
case None =>
125122
downloadBlobToStream(blob, hashingStream)
126123
case Some("zstd") =>
@@ -196,6 +193,10 @@ object GcsStorageBackend {
196193
String.join("/", sha256Hex.substring(0, 2), sha256Hex.substring(2, 4), sha256Hex.substring(4, 6), sha256Hex)
197194
}
198195

196+
private[gcs] def getMetadataValue(blob: Blob, key: String): Option[String] = {
197+
Option(blob.getMetadata).flatMap(m => Option(m.get(key)))
198+
}
199+
199200
private[gcs] class CountingOutputStream(target: OutputStream) extends OutputStream {
200201
private var count: Long = 0
201202

gcs/src/test/scala/com/avast/clients/storage/gcs/GcsStorageBackendTest.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class GcsStorageBackendTest extends FunSuite with ScalaFutures with MockitoSugar
3232

3333
val blob = mock[Blob]
3434
when(blob.getSize).thenReturn(fileSize.toLong)
35+
when(blob.getMetadata).thenReturn(null)
3536

3637
val storageClient = mock[Storage]
3738
when(storageClient.get(any[BlobId]())).thenAnswer { call =>
@@ -100,6 +101,7 @@ class GcsStorageBackendTest extends FunSuite with ScalaFutures with MockitoSugar
100101
val bucketName = "bucket-tst"
101102

102103
val blob = mock[Blob]
104+
when(blob.getMetadata).thenReturn(null)
103105
when(blob.downloadTo(any[OutputStream]())).thenAnswer { call =>
104106
val outputStream = call.getArgument[OutputStream](0)
105107
outputStream.write(content.getBytes())

0 commit comments

Comments
 (0)