Skip to content

Commit

Permalink
Merge pull request #317 from mdupras/mdupras/cached-metadata-query
Browse files Browse the repository at this point in the history
Updated the `KeyExists` from aws to keep the response metadata in the image resolver
  • Loading branch information
JimBobSquarePants authored Mar 18, 2023
2 parents fb8b334 + 2acb001 commit e13e8af
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,13 @@ public async Task<IImageResolver> GetAsync(HttpContext context)
return null;
}

if (!await KeyExists(s3Client, bucketName, key))
KeyExistsResult keyExists = await KeyExists(s3Client, bucketName, key);
if (!keyExists.Exists)
{
return null;
}

return new AWSS3StorageImageResolver(s3Client, bucketName, key);
return new AWSS3StorageImageResolver(s3Client, bucketName, key, keyExists.Metadata);
}

private bool IsMatch(HttpContext context)
Expand All @@ -133,39 +134,40 @@ private bool IsMatch(HttpContext context)
}

// ref https://github.com/aws/aws-sdk-net/blob/master/sdk/src/Services/S3/Custom/_bcl/IO/S3FileInfo.cs#L118
private static async Task<bool> KeyExists(IAmazonS3 s3Client, string bucketName, string key)
private static async Task<KeyExistsResult> KeyExists(IAmazonS3 s3Client, string bucketName, string key)
{
try
{
GetObjectMetadataRequest request = new()
{
BucketName = bucketName,
Key = key
};
GetObjectMetadataRequest request = new() { BucketName = bucketName, Key = key };

// If the object doesn't exist then a "NotFound" will be thrown
await s3Client.GetObjectMetadataAsync(request);
return true;
GetObjectMetadataResponse metadata = await s3Client.GetObjectMetadataAsync(request);
return new KeyExistsResult(metadata);
}
catch (AmazonS3Exception e)
{
if (string.Equals(e.ErrorCode, "NoSuchBucket", StringComparison.Ordinal))
{
return false;
return default;
}

if (string.Equals(e.ErrorCode, "NotFound", StringComparison.Ordinal))
{
return false;
return default;
}

// If the object exists but the client is not authorized to access it, then a "Forbidden" will be thrown.
if (string.Equals(e.ErrorCode, "Forbidden", StringComparison.Ordinal))
{
return false;
return default;
}

throw;
}
}

private readonly record struct KeyExistsResult(GetObjectMetadataResponse Metadata)
{
public bool Exists => this.Metadata is not null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,27 @@ public class AWSS3StorageImageResolver : IImageResolver
private readonly IAmazonS3 amazonS3;
private readonly string bucketName;
private readonly string imagePath;
private readonly GetObjectMetadataResponse metadataResponse;

/// <summary>
/// Initializes a new instance of the <see cref="AWSS3StorageImageResolver"/> class.
/// </summary>
/// <param name="amazonS3">The Amazon S3 Client</param>
/// <param name="bucketName">The bucket name.</param>
/// <param name="imagePath">The image path.</param>
public AWSS3StorageImageResolver(IAmazonS3 amazonS3, string bucketName, string imagePath)
/// <param name="metadataResponse">Optional metadata response.</param>
public AWSS3StorageImageResolver(IAmazonS3 amazonS3, string bucketName, string imagePath, GetObjectMetadataResponse metadataResponse = null)
{
this.amazonS3 = amazonS3;
this.bucketName = bucketName;
this.imagePath = imagePath;
this.metadataResponse = metadataResponse;
}

/// <inheritdoc />
public async Task<ImageMetadata> GetMetaDataAsync()
{
GetObjectMetadataResponse metadata = await this.amazonS3.GetObjectMetadataAsync(this.bucketName, this.imagePath);
GetObjectMetadataResponse metadata = this.metadataResponse ?? await this.amazonS3.GetObjectMetadataAsync(this.bucketName, this.imagePath);

// Try to parse the max age from the source. If it's not zero then we pass it along
// to set the cache control headers for the response.
Expand Down

0 comments on commit e13e8af

Please sign in to comment.