diff --git a/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs b/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs index 62f094ef..98a683dc 100644 --- a/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs +++ b/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs @@ -3,6 +3,7 @@ using System; using Amazon; +using Amazon.Runtime; using Amazon.S3; namespace SixLabors.ImageSharp.Web @@ -25,6 +26,7 @@ public static AmazonS3Client CreateClient(IAWSS3BucketClientOptions options) // AccessSecret can be empty. // PathStyle endpoint doesn't support AccelerateEndpoint. AmazonS3Config config = new() { ServiceURL = options.Endpoint, ForcePathStyle = true, AuthenticationRegion = options.Region }; + SetTimeout(config, options.Timeout); return new AmazonS3Client(options.AccessKey, options.AccessSecret, config); } else if (!string.IsNullOrWhiteSpace(options.AccessKey)) @@ -33,12 +35,14 @@ public static AmazonS3Client CreateClient(IAWSS3BucketClientOptions options) Guard.NotNullOrWhiteSpace(options.Region, nameof(options.Region)); var region = RegionEndpoint.GetBySystemName(options.Region); AmazonS3Config config = new() { RegionEndpoint = region, UseAccelerateEndpoint = options.UseAccelerateEndpoint }; + SetTimeout(config, options.Timeout); return new AmazonS3Client(options.AccessKey, options.AccessSecret, config); } else if (!string.IsNullOrWhiteSpace(options.Region)) { var region = RegionEndpoint.GetBySystemName(options.Region); AmazonS3Config config = new() { RegionEndpoint = region, UseAccelerateEndpoint = options.UseAccelerateEndpoint }; + SetTimeout(config, options.Timeout); return new AmazonS3Client(config); } else @@ -46,5 +50,14 @@ public static AmazonS3Client CreateClient(IAWSS3BucketClientOptions options) throw new ArgumentException("Invalid configuration.", nameof(options)); } } + + private static void SetTimeout(ClientConfig config, TimeSpan? timeout) + { + // We don't want to override the default timeout if it's not set. + if (timeout.HasValue) + { + config.Timeout = timeout.Value; + } + } } } diff --git a/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs b/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs index 692d9af1..865f4c00 100644 --- a/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs +++ b/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs @@ -1,5 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; namespace SixLabors.ImageSharp.Web.Caching.AWS { @@ -25,5 +26,8 @@ public class AWSS3StorageCacheOptions : IAWSS3BucketClientOptions /// public bool UseAccelerateEndpoint { get; set; } + + /// + public TimeSpan? Timeout { get; set; } } } diff --git a/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs b/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs index e28560b8..6ef40a40 100644 --- a/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs +++ b/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; + namespace SixLabors.ImageSharp.Web { /// @@ -43,5 +45,11 @@ internal interface IAWSS3BucketClientOptions /// The feature must be enabled on the bucket. Follow AWS instruction on . /// bool UseAccelerateEndpoint { get; set; } + + /// + /// Gets or sets a value indicating the timeout for the S3 client. + /// If the value is set, the value is assigned to the Timeout property of the HttpWebRequest/HttpClient object used to send requests. + /// + TimeSpan? Timeout { get; set; } } } diff --git a/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs b/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs index 57f09fe6..6fcf4f06 100644 --- a/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs +++ b/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; using System.Collections.Generic; namespace SixLabors.ImageSharp.Web.Providers.AWS @@ -38,5 +39,8 @@ public class AWSS3BucketClientOptions : IAWSS3BucketClientOptions /// public bool UseAccelerateEndpoint { get; set; } + + /// + public TimeSpan? Timeout { get; set; } } } diff --git a/tests/ImageSharp.Web.Tests/TestUtilities/AWSS3StorageCacheTestServerFixture.cs b/tests/ImageSharp.Web.Tests/TestUtilities/AWSS3StorageCacheTestServerFixture.cs index b6c4adf8..ab95d5bd 100644 --- a/tests/ImageSharp.Web.Tests/TestUtilities/AWSS3StorageCacheTestServerFixture.cs +++ b/tests/ImageSharp.Web.Tests/TestUtilities/AWSS3StorageCacheTestServerFixture.cs @@ -21,7 +21,8 @@ protected override void ConfigureCustomServices(IServiceCollection services, IIm BucketName = TestConstants.AWSBucketName, AccessKey = TestConstants.AWSAccessKey, AccessSecret = TestConstants.AWSAccessSecret, - Region = TestConstants.AWSRegion + Region = TestConstants.AWSRegion, + Timeout = TestConstants.AWSTimeout, })) .AddProvider(AWSS3StorageImageProviderFactory.Create) .Configure(o => @@ -31,6 +32,7 @@ protected override void ConfigureCustomServices(IServiceCollection services, IIm o.AccessKey = TestConstants.AWSAccessKey; o.AccessSecret = TestConstants.AWSAccessSecret; o.Region = TestConstants.AWSRegion; + o.Timeout = TestConstants.AWSTimeout; AWSS3StorageCache.CreateIfNotExists(o, S3CannedACL.Private); }) diff --git a/tests/ImageSharp.Web.Tests/TestUtilities/TestConstants.cs b/tests/ImageSharp.Web.Tests/TestUtilities/TestConstants.cs index b43ba8cc..9c764d7e 100644 --- a/tests/ImageSharp.Web.Tests/TestUtilities/TestConstants.cs +++ b/tests/ImageSharp.Web.Tests/TestUtilities/TestConstants.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; + namespace SixLabors.ImageSharp.Web.Tests.TestUtilities { public static class TestConstants @@ -18,5 +20,6 @@ public static class TestConstants public const string PhysicalTestImage = "http://localhost/" + ImagePath; public const string AzureTestImage = "http://localhost/" + AzureContainerName + "/" + ImagePath; public const string AWSTestImage = "http://localhost/" + AWSBucketName + "/" + ImagePath; + public static readonly TimeSpan AWSTimeout = TimeSpan.FromSeconds(10); } }