├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── generic-build.yml │ └── nuget-release.yml ├── .gitignore ├── .globalconfig ├── Config.json ├── Imports ├── Benchmarks.props ├── Console.props ├── Examples.props ├── Library.props └── Tests.props ├── LICENSE.txt ├── Locals ├── Benchmarks.props ├── Console.props ├── Directory.Build.props ├── Directory.Packages.props ├── Examples.props ├── Library.props └── Tests.props ├── README.md ├── SECURITY.md ├── SimpleS3.sln ├── SimpleS3.sln.DotSettings └── Src ├── Directory.Build.props ├── Directory.Build.targets ├── Directory.Packages.Analyzers.props ├── Directory.Packages.props ├── ProviderTests ├── .globalconfig ├── Buckets │ ├── BucketAccelerateConfigurationTests.cs │ ├── BucketLifecycleConfigurationTests.cs │ ├── BucketLockConfigurationTests.cs │ ├── BucketPolicyTests.cs │ ├── BucketTaggingTests.cs │ ├── BucketVersioningTests.cs │ ├── CreateBucketTests.cs │ ├── DeleteBucketTests.cs │ ├── HeadBucketTests.cs │ ├── ListBucketsTests.cs │ ├── MiscTests.cs │ └── PutPublicAccessBlockTests.cs ├── Code │ ├── MultipleProvidersAttribute.cs │ ├── ProviderSetup.cs │ ├── TestBase.cs │ └── TestConstants.cs ├── Issues │ ├── AmazonIssues.cs │ └── BackBlazeIssues.cs ├── Misc │ └── GetObjectTests.cs ├── Multipart │ ├── AbortMultipartTests.cs │ ├── ListMultipartUploadsTests.cs │ ├── ListPartsTests.cs │ └── MultipartTests.cs ├── Objects │ ├── CopyObjectTests.cs │ ├── DeleteObjectTests.cs │ ├── DeleteObjectsTests.cs │ ├── GetObjectTests.cs │ ├── HeadObjectTests.cs │ ├── ListObjectVersionsTests.cs │ ├── ListObjectsTests.cs │ ├── ObjectAclTests.cs │ ├── ObjectLegalHoldTests.cs │ ├── PutObjectTests.cs │ └── RestoreObjectTests.cs ├── ProviderTests.csproj ├── README.md └── Signed │ └── SignedTests.cs ├── SimpleS3.AmazonS3.Tests ├── SimpleS3.AmazonS3.Tests.csproj └── StaticCreatorTests.cs ├── SimpleS3.AmazonS3 ├── AmazonS3Client.cs ├── Extensions │ └── ServiceCollectionExtensions.cs └── SimpleS3.AmazonS3.csproj ├── SimpleS3.BackBlazeB2.Tests ├── SimpleS3.BackBlazeB2.Tests.csproj └── StaticCreatorTests.cs ├── SimpleS3.BackBlazeB2 ├── BackBlazeB2Client.cs ├── Extensions │ └── ServiceCollectionExtensions.cs └── SimpleS3.BackBlazeB2.csproj ├── SimpleS3.Core.Abstracts ├── Authentication │ ├── IAccessKey.cs │ ├── IAccessKeyProtector.cs │ ├── IAuthorizationBuilder.cs │ ├── IChunkedSignatureBuilder.cs │ ├── IScopeBuilder.cs │ ├── ISignatureBuilder.cs │ └── ISigningKeyBuilder.cs ├── Enums │ ├── BucketNameValidationMode.cs │ ├── ErrorCode.cs │ ├── HttpMethodType.cs │ ├── NamingMode.cs │ ├── ObjectKeyValidationMode.cs │ ├── SignatureMode.cs │ └── ValidationStatus.cs ├── Factories │ ├── IMarshalFactory.cs │ ├── IPostMapperFactory.cs │ └── IRequestValidatorFactory.cs ├── ICoreBuilder.cs ├── Provider │ ├── IEndpointBuilder.cs │ ├── IEndpointData.cs │ └── IInputValidator.cs ├── Region │ ├── IRegionConverter.cs │ ├── IRegionData.cs │ ├── IRegionInfo.cs │ └── RegionInfo.cs ├── Request │ ├── INetworkDriver.cs │ ├── IRequest.cs │ ├── IRequestHandler.cs │ ├── IRequestMarshal.cs │ ├── IResponseHandler.cs │ └── ISignedRequestHandler.cs ├── Response │ ├── HttpResponse.cs │ ├── IError.cs │ ├── IPostMapper.cs │ ├── IResponse.cs │ └── IResponseMarshal.cs ├── ServiceBuilderBase.cs ├── SimpleS3.Core.Abstracts.csproj ├── SimpleS3Config.cs └── Wrappers │ ├── IRequestStreamWrapper.cs │ ├── IRequestWrapper.cs │ ├── IResponseStreamWrapper.cs │ └── IResponseWrapper.cs ├── SimpleS3.Core.Benchmarks ├── .globalconfig ├── Benchmarks │ ├── AwsSignatureVersion4Benchmarks.cs │ ├── CharHelperBenchmarks.cs │ ├── EndpointBuilderBenchmarks.cs │ ├── GenericsBenchmarks.cs │ ├── KeyValueTupleBenchmarks.cs │ ├── SignatureBenchmarks.cs │ ├── StringBuilderBenchmarks.cs │ ├── TypeLookupBenchmarks.cs │ ├── XmlReaderBenchmarks.cs │ └── XmlWriterBenchmarks.cs ├── Misc │ └── DummyRequest.cs ├── Program.cs └── SimpleS3.Core.Benchmarks.csproj ├── SimpleS3.Core.Common.Tests ├── Code │ ├── TestEnum.cs │ ├── TestInputValidator.cs │ ├── TestRegion.cs │ └── TestRegionData.cs ├── InputValidatorTests.cs ├── PropertyHelperTests.cs ├── RegionConverterTests.cs ├── SimpleS3.Core.Common.Tests.csproj └── ValidatorTests.cs ├── SimpleS3.Core.Common ├── Authentication │ ├── AccessKey.cs │ ├── AccessKeyBase.cs │ └── StringAccessKey.cs ├── Exceptions │ ├── S3Exception.cs │ └── S3RequestException.cs ├── Extensions │ ├── RegionConverterExtensions.cs │ ├── ServiceCollectionExtensions.cs │ ├── StringExtensions.cs │ └── ValidatorExtensions.cs ├── Helpers │ ├── CharHelper.cs │ ├── CryptoHelper.cs │ ├── KeyHelper.cs │ ├── ParallelHelper.cs │ ├── PropertyHelper.cs │ ├── TypeHelper.cs │ └── UrlHelper.cs ├── HttpVersion.cs ├── Internal │ └── Compat │ │ ├── CallerArgumentExpressionAttribute.cs │ │ ├── DoesNotReturnIfAttribute.cs │ │ └── NotNullAttribute.cs ├── Marshal │ ├── IHasBucketName.cs │ └── IHasObjectKey.cs ├── Misc │ ├── AmzHeaders.cs │ ├── AmzParameters.cs │ ├── Constants.cs │ └── HttpHeaders.cs ├── Pools │ └── StringBuilderPool.cs ├── RegionConverter.cs ├── SimpleS3.Core.Common.csproj └── Validation │ ├── InputValidatorBase.cs │ ├── RequireException.cs │ ├── ValidationMessages.cs │ └── Validator.cs ├── SimpleS3.Core.TestBase ├── Code │ └── NullNetworkDriver.cs ├── Helpers │ └── ResourceHelper.cs ├── OfflineTestBase.cs ├── SimpleS3.Core.TestBase.csproj └── UnitTestBase.cs ├── SimpleS3.Core.Tests ├── Code │ ├── EndpointBuilderTests.cs │ ├── Handlers │ │ ├── BaseFailingHttpHandler.cs │ │ ├── NetworkFailingHttpHandler.cs │ │ ├── NonTransientFailingHttpHandler.cs │ │ ├── SlowHttpHandler.cs │ │ └── TransientFailingHttpHandler.cs │ └── Streams │ │ └── NonSeekableStream.cs ├── GenericTests │ ├── Builders │ │ ├── AclBuilderTests.cs │ │ ├── KmsContextBuilderTests.cs │ │ └── MetadataBuilderTests.cs │ ├── FastXmlWriterTests.cs │ ├── JsonHelperTests.cs │ ├── PoolTypeTests.cs │ ├── ProviderTests.cs │ └── UrlHelperTests.cs ├── OfflineTests │ ├── AuthenticationTests.cs │ ├── NetworkErrorTests.cs │ ├── NonSeekableStreamTests.cs │ ├── NonTransientServerErrorTests.cs │ ├── ReuseRequestTests.cs │ ├── TimeoutTests.cs │ └── TransientNetworkErrorTests.cs └── SimpleS3.Core.Tests.csproj ├── SimpleS3.Core ├── Abstracts │ ├── Clients │ │ ├── IBucketClient.cs │ │ ├── IMultipartClient.cs │ │ ├── IObjectClient.cs │ │ └── ISignedClient.cs │ ├── Features │ │ ├── IAutoMapConfig.cs │ │ ├── IContainSensitiveMaterial.cs │ │ ├── IContentMd5Config.cs │ │ └── ISupportStreaming.cs │ ├── IDownload.cs │ ├── ISimpleClient.cs │ ├── IUpload.cs │ ├── Operations │ │ ├── IBucketOperations.cs │ │ ├── IMultipartOperations.cs │ │ ├── IObjectOperations.cs │ │ └── ISignedOperations.cs │ └── Transfer │ │ ├── IMultipartTransfer.cs │ │ └── ITransfer.cs ├── Authentication │ └── HeaderWhitelist.cs ├── Builders │ ├── AclBuilder.cs │ ├── KmsContextBuilder.cs │ ├── MetadataBuilder.cs │ ├── MfaAuthenticationBuilder.cs │ ├── ObjectAclBuilder.cs │ └── TagBuilder.cs ├── Enums │ ├── BucketCannedAcl.cs │ ├── ChecksumAlgorithm.cs │ ├── ChecksumType.cs │ ├── CompressionType.cs │ ├── EncodingType.cs │ ├── ExpressionType.cs │ ├── GrantType.cs │ ├── HeaderUsage.cs │ ├── JsonType.cs │ ├── LockMode.cs │ ├── MetadataDirective.cs │ ├── ObjectCannedAcl.cs │ ├── ObjectOwnership.cs │ ├── ObjectPermissions.cs │ ├── Payer.cs │ ├── PredefinedGroup.cs │ ├── QuoteField.cs │ ├── ReplicationStatus.cs │ ├── RestoreRequestType.cs │ ├── RetrievalTier.cs │ ├── S3Permission.cs │ ├── SseAlgorithm.cs │ ├── SseCustomerAlgorithm.cs │ ├── StorageClass.cs │ └── TaggingDirective.cs ├── Extensions │ ├── BucketClientExtensions.cs │ ├── CoreBuilderExtensions.cs │ ├── MultipartClientExtensions.cs │ ├── ObjectClientExtensions.cs │ ├── SimpleS3CoreServices.cs │ └── StreamExtensions.cs ├── Internals │ ├── Authentication │ │ ├── ChunkedSignatureBuilder.cs │ │ ├── ChunkedStream.cs │ │ ├── ScopeBuilder.cs │ │ ├── SignatureBuilder.cs │ │ ├── SigningConstants.cs │ │ └── SigningKeyBuilder.cs │ ├── Builders │ │ ├── HeaderAuthorizationBuilder.cs │ │ └── QueryParameterAuthorizationBuilder.cs │ ├── Clients │ │ ├── BucketClient.cs │ │ ├── MultipartClient.cs │ │ ├── ObjectClient.cs │ │ ├── PooledBucketClient.cs │ │ ├── PooledMultipartClient.cs │ │ ├── PooledObjectClient.cs │ │ └── SignedClient.cs │ ├── Compat │ │ └── NotNullWhenAttribute.cs │ ├── CoreBuilder.cs │ ├── Enums │ │ ├── BinaryEncoding.cs │ │ └── DateTimeFormat.cs │ ├── Errors │ │ └── ErrorHandler.cs │ ├── Extensions │ │ ├── DictionaryExtensions.cs │ │ ├── HexExtensions.cs │ │ ├── QueueExtensions.cs │ │ ├── RequestExtensions.cs │ │ ├── StreamExtensions.cs │ │ └── TypeExtensions.cs │ ├── Fluent │ │ ├── Download.cs │ │ ├── MultipartTransfer.cs │ │ ├── Transfer.cs │ │ └── Upload.cs │ ├── Helpers │ │ ├── CopyHelper.cs │ │ ├── JsonHelper.cs │ │ ├── ParserHelper.cs │ │ ├── RequestHelper.cs │ │ ├── ValueHelper.cs │ │ └── XmlHelper.cs │ ├── Marshallers │ │ ├── Requests │ │ │ ├── Buckets │ │ │ │ ├── CreateBucketRequestMarshal.cs │ │ │ │ ├── DeleteBucketPolicyRequestMarshal.cs │ │ │ │ ├── DeleteBucketTaggingRequestMarshal.cs │ │ │ │ ├── GetBucketAccelerateConfigurationRequestMarshal.cs │ │ │ │ ├── GetBucketLifecycleConfigurationRequestMarshal.cs │ │ │ │ ├── GetBucketLockConfigurationRequestMarshal.cs │ │ │ │ ├── GetBucketPolicyRequestMarshal.cs │ │ │ │ ├── GetBucketTaggingRequestMarshal.cs │ │ │ │ ├── GetBucketVersioningRequestMarshal.cs │ │ │ │ ├── PutBucketAccelerateConfigurationRequestMarshal.cs │ │ │ │ ├── PutBucketLifecycleConfigurationRequestMarshal.cs │ │ │ │ ├── PutBucketLockConfigurationRequestMarshal.cs │ │ │ │ ├── PutBucketPolicyRequestMarshal.cs │ │ │ │ ├── PutBucketTaggingRequestMarshal.cs │ │ │ │ ├── PutBucketVersioningRequestMarshal.cs │ │ │ │ └── PutPublicAccessBlockRequestMarshal.cs │ │ │ ├── GenericRequestMapper.cs │ │ │ ├── Multipart │ │ │ │ ├── CompleteMultipartUploadRequestMarshal.cs │ │ │ │ ├── CreateMultipartUploadRequestMarshal.cs │ │ │ │ ├── ListMultipartUploadsRequestMarshal.cs │ │ │ │ └── ListPartsRequestMarshal.cs │ │ │ └── Objects │ │ │ │ ├── CopyObjectRequestMarshal.cs │ │ │ │ ├── DeleteObjectsRequestMarshal.cs │ │ │ │ ├── GetObjectAclRequestMarshal.cs │ │ │ │ ├── GetObjectLegalHoldRequestMarshal.cs │ │ │ │ ├── GetObjectRequestMarshal.cs │ │ │ │ ├── HeadObjectRequestMarshal.cs │ │ │ │ ├── ListObjectVersionsRequestMarshal.cs │ │ │ │ ├── ListObjectsRequestMarshal.cs │ │ │ │ ├── PutObjectAclRequestMarshal.cs │ │ │ │ ├── PutObjectLegalHoldRequestMarshal.cs │ │ │ │ └── RestoreObjectRequestMarshal.cs │ │ └── Responses │ │ │ ├── Buckets │ │ │ ├── GetBucketAccelerateConfigurationResponseMarshal.cs │ │ │ ├── GetBucketLifecycleConfigurationResponseMarshal.cs │ │ │ ├── GetBucketLockConfigurationResponseMarshal.cs │ │ │ ├── GetBucketPolicyResponseMarshal.cs │ │ │ ├── GetBucketTaggingResponseMarshal.cs │ │ │ ├── GetBucketVersioningResponseMarshal.cs │ │ │ ├── ListBucketsResponseMarshal.cs │ │ │ ├── PutBucketLockConfigurationResponseMarshal.cs │ │ │ └── PutBucketVersioningResponseMarshal.cs │ │ │ ├── Multipart │ │ │ ├── AbortMultipartUploadResponseMarshal.cs │ │ │ ├── CompleteMultipartUploadResponseMarshal.cs │ │ │ ├── CreateMultipartUploadResponseMarshal.cs │ │ │ ├── ListMultipartUploadsResponseMarshal.cs │ │ │ ├── ListPartsResponseMarshal.cs │ │ │ └── UploadPartResponseMarshal.cs │ │ │ └── Objects │ │ │ ├── CopyObjectResponseMarshal.cs │ │ │ ├── DeleteObjectResponseMarshal.cs │ │ │ ├── DeleteObjectsResponseMarshal.cs │ │ │ ├── GetObjectAclResponseMarshal.cs │ │ │ ├── GetObjectLegalHoldResponseMarshal.cs │ │ │ ├── GetObjectResponseMarshal.cs │ │ │ ├── HeadObjectResponseMarshal.cs │ │ │ ├── ListObjectVersionsResponseMarshal.cs │ │ │ ├── ListObjectsResponseMarshal.cs │ │ │ ├── PutObjectAclResponseMarshal.cs │ │ │ ├── PutObjectLegalHoldResponseMarshal.cs │ │ │ ├── PutObjectResponseMarshal.cs │ │ │ └── RestoreObjectResponseMarshal.cs │ ├── Misc │ │ ├── DateTimeFormats.cs │ │ └── OrderedDictionary.cs │ ├── Network │ │ ├── ChunkedContentRequestStreamWrapper.cs │ │ ├── DefaultRequestHandler.cs │ │ ├── DefaultResponseHandler.cs │ │ ├── DefaultSignedRequestHandler.cs │ │ ├── EndpointBuilder.cs │ │ ├── EndpointData.cs │ │ ├── MarshalFactory.cs │ │ ├── PostMapperFactory.cs │ │ └── SignedRequest.cs │ ├── NullInputValidator.cs │ ├── Operations │ │ ├── BucketOperations.cs │ │ ├── MultipartOperations.cs │ │ ├── ObjectOperations.cs │ │ └── SignedOperations.cs │ ├── Pools │ │ ├── IPooledObject.cs │ │ └── ObjectPool.cs │ ├── PostMappers │ │ └── UploadPartPostMapper.cs │ ├── Validation │ │ ├── ValidatorFactory.cs │ │ └── Validators │ │ │ ├── ConfigValidatorBase.cs │ │ │ ├── Configs │ │ │ ├── AccessKeyValidator.cs │ │ │ └── ConfigValidator.cs │ │ │ ├── RequestValidatorBase.cs │ │ │ ├── Requests │ │ │ ├── Bucket │ │ │ │ └── PutBucketLifecycleConfigurationRequestValidator.cs │ │ │ ├── Multipart │ │ │ │ ├── CompleteMultipartUploadRequestValidator.cs │ │ │ │ └── ListMultipartUploadsRequestValidator.cs │ │ │ └── Objects │ │ │ │ ├── DeleteObjectsRequestValidator.cs │ │ │ │ └── ListObjectsRequestValidator.cs │ │ │ └── ValidatorBase.cs │ └── Xml │ │ ├── FastXmlWriter.cs │ │ ├── XmlCharMode.cs │ │ └── XmlStandard.cs ├── Network │ ├── Requests │ │ ├── BaseRequest.cs │ │ ├── Buckets │ │ │ ├── CreateBucketRequest.cs │ │ │ ├── DeleteBucketPolicyRequest.cs │ │ │ ├── DeleteBucketRequest.cs │ │ │ ├── DeleteBucketTaggingRequest.cs │ │ │ ├── GetBucketAccelerateConfigurationRequest.cs │ │ │ ├── GetBucketLifecycleConfigurationRequest.cs │ │ │ ├── GetBucketLockConfigurationRequest.cs │ │ │ ├── GetBucketPolicyRequest.cs │ │ │ ├── GetBucketTaggingRequest.cs │ │ │ ├── GetBucketVersioningRequest.cs │ │ │ ├── HeadBucketRequest.cs │ │ │ ├── ListBucketsRequest.cs │ │ │ ├── PutBucketAccelerateConfigurationRequest.cs │ │ │ ├── PutBucketLifecycleConfigurationRequest.cs │ │ │ ├── PutBucketLockConfigurationRequest.cs │ │ │ ├── PutBucketPolicyRequest.cs │ │ │ ├── PutBucketTaggingRequest.cs │ │ │ ├── PutBucketVersioningRequest.cs │ │ │ └── PutPublicAccessBlockRequest.cs │ │ ├── Interfaces │ │ │ ├── IHasBucketAcl.cs │ │ │ ├── IHasBypassGovernanceRetention.cs │ │ │ ├── IHasCache.cs │ │ │ ├── IHasCacheControl.cs │ │ │ ├── IHasChecksum.cs │ │ │ ├── IHasChecksumProperties.cs │ │ │ ├── IHasContent.cs │ │ │ ├── IHasContentMd5.cs │ │ │ ├── IHasContentProps.cs │ │ │ ├── IHasExpectedBucketOwner.cs │ │ │ ├── IHasExpiresOn.cs │ │ │ ├── IHasLegalHold.cs │ │ │ ├── IHasLock.cs │ │ │ ├── IHasMetadata.cs │ │ │ ├── IHasMfa.cs │ │ │ ├── IHasObjectAcl.cs │ │ │ ├── IHasPartNumber.cs │ │ │ ├── IHasRange.cs │ │ │ ├── IHasRequestPayer.cs │ │ │ ├── IHasResponseHeader.cs │ │ │ ├── IHasSse.cs │ │ │ ├── IHasSseCustomerKey.cs │ │ │ ├── IHasStorageClass.cs │ │ │ ├── IHasTags.cs │ │ │ ├── IHasUploadId.cs │ │ │ ├── IHasVersionId.cs │ │ │ └── IHasWebsiteRedirect.cs │ │ ├── Multipart │ │ │ ├── AbortMultipartUploadRequest.cs │ │ │ ├── CompleteMultipartUploadRequest.cs │ │ │ ├── CreateMultipartUploadRequest.cs │ │ │ ├── ListMultipartUploadsRequest.cs │ │ │ ├── ListPartsRequest.cs │ │ │ └── UploadPartRequest.cs │ │ ├── Objects │ │ │ ├── CopyObjectRequest.cs │ │ │ ├── DeleteObjectRequest.cs │ │ │ ├── DeleteObjectsRequest.cs │ │ │ ├── GetObjectAclRequest.cs │ │ │ ├── GetObjectLegalHoldRequest.cs │ │ │ ├── GetObjectRequest.cs │ │ │ ├── HeadObjectRequest.cs │ │ │ ├── ListObjectVersionsRequest.cs │ │ │ ├── ListObjectsRequest.cs │ │ │ ├── PutObjectAclRequest.cs │ │ │ ├── PutObjectLegalHoldRequest.cs │ │ │ ├── PutObjectRequest.cs │ │ │ └── RestoreObjectRequest.cs │ │ └── S3Types │ │ │ ├── S3AndCondition.cs │ │ │ ├── S3CsvInputFormat.cs │ │ │ ├── S3CsvOutputFormat.cs │ │ │ ├── S3DeleteInfo.cs │ │ │ ├── S3Expiration.cs │ │ │ ├── S3Filter.cs │ │ │ ├── S3InputFormat.cs │ │ │ ├── S3JsonInputFormat.cs │ │ │ ├── S3JsonOutputFormat.cs │ │ │ ├── S3NonCurrentVersionTransition.cs │ │ │ ├── S3OutputFormat.cs │ │ │ ├── S3OutputLocation.cs │ │ │ ├── S3ParquetInputFormat.cs │ │ │ ├── S3PartInfo.cs │ │ │ ├── S3Rule.cs │ │ │ ├── S3SelectParameters.cs │ │ │ └── S3Transition.cs │ └── Responses │ │ ├── BaseResponse.cs │ │ ├── Buckets │ │ ├── CreateBucketResponse.cs │ │ ├── DeleteBucketPolicyResponse.cs │ │ ├── DeleteBucketResponse.cs │ │ ├── DeleteBucketTaggingResponse.cs │ │ ├── GetBucketAccelerateConfigurationResponse.cs │ │ ├── GetBucketLifecycleConfigurationResponse.cs │ │ ├── GetBucketLockConfigurationResponse.cs │ │ ├── GetBucketPolicyResponse.cs │ │ ├── GetBucketTaggingResponse.cs │ │ ├── GetBucketVersioningResponse.cs │ │ ├── HeadBucketResponse.cs │ │ ├── ListBucketsResponse.cs │ │ ├── PutBucketAccelerateConfigurationResponse.cs │ │ ├── PutBucketLifecycleConfigurationResponse.cs │ │ ├── PutBucketLockConfigurationResponse.cs │ │ ├── PutBucketPolicyResponse.cs │ │ ├── PutBucketTaggingResponse.cs │ │ ├── PutBucketVersioningResponse.cs │ │ └── PutPublicAccessBlockResponse.cs │ │ ├── Errors │ │ ├── BucketAlreadyExistsError.cs │ │ ├── BucketNotEmptyError.cs │ │ ├── GenericError.cs │ │ ├── HeadersNotSignedError.cs │ │ ├── InvalidArgumentError.cs │ │ ├── InvalidBucketNameError.cs │ │ ├── MethodNotAllowedError.cs │ │ ├── NoSuchBucketError.cs │ │ ├── PreconditionFailedError.cs │ │ ├── TooManyBucketsError.cs │ │ └── XAmzContentSha256MismatchError.cs │ │ ├── Interfaces │ │ ├── IHasAbort.cs │ │ ├── IHasCache.cs │ │ ├── IHasContent.cs │ │ ├── IHasDeleteMarker.cs │ │ ├── IHasETag.cs │ │ ├── IHasExpiration.cs │ │ ├── IHasExpiresOn.cs │ │ ├── IHasLastModified.cs │ │ ├── IHasLegalHold.cs │ │ ├── IHasLock.cs │ │ ├── IHasMetadata.cs │ │ ├── IHasReplicationStatus.cs │ │ ├── IHasRequestCharged.cs │ │ ├── IHasResponseContent.cs │ │ ├── IHasRestoration.cs │ │ ├── IHasSse.cs │ │ ├── IHasSseContext.cs │ │ ├── IHasSseCustomerKey.cs │ │ ├── IHasStorageClass.cs │ │ ├── IHasTruncated.cs │ │ ├── IHasTruncatedExt.cs │ │ ├── IHasUploadId.cs │ │ ├── IHasVersionId.cs │ │ └── IHasWebsiteRedirect.cs │ │ ├── Multipart │ │ ├── AbortMultipartUploadResponse.cs │ │ ├── CompleteMultipartUploadResponse.cs │ │ ├── CreateMultipartUploadResponse.cs │ │ ├── ListMultipartUploadsResponse.cs │ │ ├── ListPartsResponse.cs │ │ └── UploadPartResponse.cs │ │ ├── Objects │ │ ├── CopyObjectResponse.cs │ │ ├── DeleteObjectResponse.cs │ │ ├── DeleteObjectsResponse.cs │ │ ├── GetObjectAclResponse.cs │ │ ├── GetObjectLegalHoldResponse.cs │ │ ├── GetObjectResponse.cs │ │ ├── HeadObjectResponse.cs │ │ ├── ListObjectVersionsResponse.cs │ │ ├── ListObjectsResponse.cs │ │ ├── PutObjectAclResponse.cs │ │ ├── PutObjectLegalHoldResponse.cs │ │ ├── PutObjectResponse.cs │ │ └── RestoreObjectResponse.cs │ │ └── S3Types │ │ ├── S3Bucket.cs │ │ ├── S3DeleteError.cs │ │ ├── S3DeleteMarker.cs │ │ ├── S3DeletedObject.cs │ │ ├── S3Grant.cs │ │ ├── S3Grantee.cs │ │ ├── S3Identity.cs │ │ ├── S3Object.cs │ │ ├── S3Part.cs │ │ ├── S3Upload.cs │ │ └── S3Version.cs ├── Properties │ └── AssemblyInfo.cs ├── SimpleClient.cs └── SimpleS3.Core.csproj ├── SimpleS3.Examples.Advanced ├── ClientSetup.cs ├── NetworkProxy.cs ├── NetworkRetryAndTimeout.cs ├── SetupDependencyInjection.cs ├── SimpleS3.Examples.Advanced.csproj ├── UsingCustomerKey.cs └── UsingProfileManager.cs ├── SimpleS3.Examples ├── Program.cs └── SimpleS3.Examples.csproj ├── SimpleS3.Extensions.AmazonS3.Tests ├── AmazonS3InputValidatorTests.cs ├── CanonicalRequestFileTests.cs ├── ChunkedSignatureTests.cs ├── Helpers │ └── HttpHelper.cs ├── HttpHandler.cs ├── Resources │ ├── README.md │ ├── get-query-casing │ │ ├── get-query-casing.creq │ │ ├── get-query-casing.req.disabled │ │ └── get-query-casing.sts │ ├── get-query-order │ │ ├── get-query-order.creq │ │ ├── get-query-order.req │ │ └── get-query-order.sts │ ├── get-query-reserved │ │ ├── get-query-reserved.creq │ │ ├── get-query-reserved.req │ │ └── get-query-reserved.sts │ ├── get-query-utf8 │ │ ├── get-query-utf8.creq │ │ ├── get-query-utf8.req │ │ └── get-query-utf8.sts │ ├── get-query │ │ ├── get-query.creq │ │ ├── get-query.req │ │ └── get-query.sts │ ├── get-reserved │ │ ├── get-reserved.creq │ │ ├── get-reserved.req │ │ └── get-reserved.sts │ ├── get-utf8 │ │ ├── get-utf8.creq │ │ ├── get-utf8.req │ │ └── get-utf8.sts │ └── get │ │ ├── get.creq │ │ ├── get.req │ │ └── get.sts ├── SignedUrlTests.cs └── SimpleS3.Extensions.AmazonS3.Tests.csproj ├── SimpleS3.Extensions.AmazonS3 ├── AmazonS3Config.cs ├── AmazonS3InputValidator.cs ├── AmazonS3Region.cs ├── AmazonS3RegionData.cs ├── Extensions │ └── CoreBuilderExtensions.cs ├── Properties │ └── AssemblyInfo.cs ├── README.md └── SimpleS3.Extensions.AmazonS3.csproj ├── SimpleS3.Extensions.BackBlazeB2.Tests ├── BackblazeB2InputValidatorTests.cs └── SimpleS3.Extensions.BackBlazeB2.Tests.csproj ├── SimpleS3.Extensions.BackBlazeB2 ├── BackBlazeB2Config.cs ├── BackBlazeB2Region.cs ├── BackblazeB2InputValidator.cs ├── BackblazeB2RegionData.cs ├── Extensions │ └── CoreBuilderExtensions.cs ├── Properties │ └── AssemblyInfo.cs ├── README.md └── SimpleS3.Extensions.BackBlazeB2.csproj ├── SimpleS3.Extensions.GenericS3.Tests ├── GenericS3InputValidatorTests.cs ├── GenericS3IssueTests.cs └── SimpleS3.Extensions.GenericS3.Tests.csproj ├── SimpleS3.Extensions.GenericS3 ├── Extensions │ └── CoreBuilderExtensions.cs ├── GenericS3Config.cs ├── GenericS3InputValidator.cs ├── GenericS3RegionData.cs ├── README.md └── SimpleS3.Extensions.GenericS3.csproj ├── SimpleS3.Extensions.GoogleCloudStorage.Tests ├── GoogleCloudStorageInputValidatorTests.cs └── SimpleS3.Extensions.GoogleCloudStorage.Tests.csproj ├── SimpleS3.Extensions.GoogleCloudStorage ├── Extensions │ └── CoreBuilderExtensions.cs ├── GoogleCloudStorageConfig.cs ├── GoogleCloudStorageInputValidator.cs ├── GoogleCloudStorageRegion.cs ├── GoogleCloudStorageRegionData.cs ├── Properties │ └── AssemblyInfo.cs ├── README.md └── SimpleS3.Extensions.GoogleCloudStorage.csproj ├── SimpleS3.Extensions.HttpClient ├── Extensions │ ├── CoreBuilderExtensions.cs │ └── HttpClientBuilderExtensions.cs ├── HttpBuilderActions.cs ├── HttpClientConfig.cs ├── HttpClientNetworkDriver.cs ├── IHttpClientBuilder.cs ├── Internal │ ├── CustomHttpClientBuilder.cs │ └── HttpRequestMessageExtensions.cs ├── README.md └── SimpleS3.Extensions.HttpClient.csproj ├── SimpleS3.Extensions.HttpClientFactory.Polly ├── Extensions │ └── HttpClientBuilderExtensions.cs ├── Internal │ └── PollyHttpMessageHandler.cs ├── PollyConfig.cs ├── README.md ├── Retry │ ├── RetryableBufferingStream.cs │ └── RetryableBufferingStreamWrapper.cs ├── RetryMode.cs └── SimpleS3.Extensions.HttpClientFactory.Polly.csproj ├── SimpleS3.Extensions.HttpClientFactory ├── Extensions │ ├── CoreBuilderExtensions.cs │ └── HttpClientBuilderExtensions.cs ├── HttpBuilderActions.cs ├── HttpClientFactoryConfig.cs ├── HttpClientFactoryNetworkDriver.cs ├── Internal │ ├── CustomHttpClientFactoryBuilder.cs │ └── HttpRequestMessageExtensions.cs ├── README.md └── SimpleS3.Extensions.HttpClientFactory.csproj ├── SimpleS3.Extensions.ProfileManager ├── Abstracts │ ├── IProfile.cs │ ├── IProfileManager.cs │ ├── IProfileManagerBuilder.cs │ ├── IProfileSerializer.cs │ ├── IProfileSetup.cs │ └── IStorage.cs ├── DiskStorageOptions.cs ├── Extensions │ ├── ConfigExtensions.cs │ ├── CoreBuilderExtensions.cs │ ├── ProfileAccessKey.cs │ ├── ProfileManagerBuilderExtensions.cs │ ├── ProfileManagerExtensions.cs │ └── ProfileSetupExtensions.cs ├── Internal │ ├── DataProtection │ │ └── DataProtectionKeyProtector.cs │ ├── Helpers │ │ └── ConsoleHelper.cs │ ├── Profile.cs │ └── ProfileManagerBuilder.cs ├── ProfileManager.cs ├── ProfileManagerOptions.cs ├── README.md ├── Serializers │ └── DefaultProfileSerializer.cs ├── Setup │ └── ConsoleProfileSetup.cs ├── SimpleS3.Extensions.ProfileManager.csproj └── Storage │ └── DiskStorage.cs ├── SimpleS3.Extensions.Wasabi.Tests ├── SimpleS3.Extensions.Wasabi.Tests.csproj └── WasabiInputValidatorTests.cs ├── SimpleS3.Extensions.Wasabi ├── Extensions │ └── CoreBuilderExtensions.cs ├── Properties │ └── AssemblyInfo.cs ├── README.md ├── SimpleS3.Extensions.Wasabi.csproj ├── WasabiConfig.cs ├── WasabiInputValidator.cs ├── WasabiRegion.cs └── WasabiRegionData.cs ├── SimpleS3.GenericS3.Tests ├── SimpleS3.GenericS3.Tests.csproj └── StaticCreatorTests.cs ├── SimpleS3.GenericS3 ├── Extensions │ └── ServiceCollectionExtensions.cs ├── GenericS3Client.cs └── SimpleS3.GenericS3.csproj ├── SimpleS3.GoogleCloudStorage.Tests ├── SimpleS3.GoogleCloudStorage.Tests.csproj └── StaticCreatorTests.cs ├── SimpleS3.GoogleCloudStorage ├── Extensions │ └── ServiceCollectionExtensions.cs ├── GoogleCloudStorageClient.cs └── SimpleS3.GoogleCloudStorage.csproj ├── SimpleS3.ProviderBase ├── Abstracts │ └── IClientBuilder.cs ├── ClientBase.cs ├── ClientBuilder.cs ├── ErrorMessages.cs ├── NetworkConfig.cs └── SimpleS3.ProviderBase.csproj ├── SimpleS3.Utility.S3Template ├── Api.txt ├── Enums │ ├── ApiType.cs │ └── DataType.cs ├── Program.cs ├── SimpleS3.Utility.S3Template.csproj └── Templates │ ├── RequestMarshalTemplate.txt │ ├── RequestTemplate.txt │ ├── ResponseMarshalTemplate.txt │ └── ResponseTemplate.txt ├── SimpleS3.Utility.Shared ├── S3Provider.cs ├── SimpleS3.Utility.Shared.csproj └── UtilityHelper.cs ├── SimpleS3.Utility.TestCleanup ├── Program.cs └── SimpleS3.Utility.TestCleanup.csproj ├── SimpleS3.Utility.TestSetup ├── Program.cs └── SimpleS3.Utility.TestSetup.csproj ├── SimpleS3.Wasabi.Tests ├── SimpleS3.Wasabi.Tests.csproj └── StaticCreatorTests.cs └── SimpleS3.Wasabi ├── Extensions └── ServiceCollectionExtensions.cs ├── SimpleS3.Wasabi.csproj └── WasabiClient.cs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [ Genbox ] 2 | custom: http://paypal.me/IanQvist 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | What is the bug about? 12 | 13 | **How to reproduce?** 14 | Describe steps to reproduce the bug. Please include code to reproduce if possible. 15 | 16 | **Expected behavior** 17 | Describe what you expected to happen. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest a feature for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | * [ ] I hereby verify that I am a sponsor. 11 | 12 | Sponsorship is required before you can submit feature requests. See https://github.com/sponsors/Genbox 13 | 14 | **Describe the feature** 15 | Provide a short description of the feature. Why would you like the feature? 16 | If the feature makes changes to an existing or new API please provide an example. 17 | -------------------------------------------------------------------------------- /.github/workflows/generic-build.yml: -------------------------------------------------------------------------------- 1 | name: Generic build 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'master' 7 | tags-ignore: 8 | - '**' 9 | 10 | env: 11 | DOTNET_EnableDiagnostics: 0 12 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 13 | DOTNET_NOLOGO: true 14 | DOTNET_CLI_TELEMETRY_OPTOUT: true 15 | DOTNET_GENERATE_ASPNET_CERTIFICATE: false 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v4.2.2 23 | - name: Setup .NET Core 9.0 24 | uses: actions/setup-dotnet@v4.3.1 25 | with: 26 | dotnet-version: '9.0.x' 27 | - name: Build 28 | run: dotnet build -c Release SimpleS3.sln -------------------------------------------------------------------------------- /.github/workflows/nuget-release.yml: -------------------------------------------------------------------------------- 1 | name: Nuget release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '[0-9]+.[0-9]+.[0-9]+**' 7 | 8 | env: 9 | DOTNET_EnableDiagnostics: 0 10 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 11 | DOTNET_NOLOGO: true 12 | DOTNET_CLI_TELEMETRY_OPTOUT: true 13 | DOTNET_GENERATE_ASPNET_CERTIFICATE: false 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v4.2.2 21 | - name: Setup .NET Core 9.0 22 | uses: actions/setup-dotnet@v4.3.1 23 | with: 24 | dotnet-version: '9.0.x' 25 | - name: Pack release 26 | run: dotnet pack -c Release -o tmp SimpleS3.sln 27 | - name: Upload to nuget 28 | run: dotnet nuget push --skip-duplicate -k ${{secrets.NUGET_KEY}} -s https://api.nuget.org/v3/index.json tmp/* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | [Bb]in/ 3 | [Oo]bj/ 4 | [Ll]og/ 5 | 6 | # NuGet Packages 7 | *.nupkg 8 | *.snupkg 9 | 10 | # Others 11 | *.pfx 12 | *.publishsettings 13 | 14 | # SQL Server files 15 | *.mdf 16 | *.ldf 17 | *.ndf 18 | 19 | # Visual Studio cache folder 20 | .vs/ 21 | 22 | # Jetbrains Rider cache folder 23 | .idea/ 24 | *.sln.DotSettings.user 25 | -------------------------------------------------------------------------------- /Config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Proxy": { 3 | "UseProxy": false, 4 | "ProxyAddress": "http://127.0.0.1:8888" 5 | }, 6 | 7 | "Logging": { 8 | "LogLevel": { 9 | "Default": "Information" //Critical, Error, Warning, Information, Debug, Trace 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Imports/Benchmarks.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Imports/Console.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | false 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Imports/Examples.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Locals/Benchmarks.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /Locals/Console.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /Locals/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A simple, secure and high-performance library to communicate with Amazon S3 compatible APIs. 5 | AmazonS3 BackBlaze Wasabi GCS GoogleCloudStorage 6 | false 7 | 8 | 9 | -------------------------------------------------------------------------------- /Locals/Examples.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /Locals/Library.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /Locals/Tests.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | If you find a security vulnerability, please report it as an issue with [SECURITY] in the issue name. 6 | If the vulnerability is sensitive in nature, send an e-mail to qvistian@gmail.com 7 | -------------------------------------------------------------------------------- /Src/Directory.Packages.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Src/ProviderTests/.globalconfig: -------------------------------------------------------------------------------- 1 | dotnet_diagnostic.CA1515.severity = none # Consider making public types internal 2 | dotnet_diagnostic.CS8618.severity = none # Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. 3 | dotnet_diagnostic.CA1822.severity = none # Mark members as static 4 | -------------------------------------------------------------------------------- /Src/ProviderTests/Buckets/HeadBucketTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.ProviderTests.Code; 2 | using Genbox.ProviderTests.Misc; 3 | using Genbox.SimpleS3.Core.Abstracts; 4 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 5 | using Genbox.SimpleS3.Utility.Shared; 6 | 7 | namespace Genbox.ProviderTests.Buckets; 8 | 9 | public class HeadBucketTests : TestBase 10 | { 11 | [Theory] 12 | [MultipleProviders(S3Provider.All)] 13 | public async Task HeadBucket(S3Provider _, string bucket, ISimpleClient client) 14 | { 15 | HeadBucketResponse headResp = await client.HeadBucketAsync(bucket); 16 | Assert.Equal(200, headResp.StatusCode); 17 | 18 | headResp = await client.HeadBucketAsync(GetTemporaryBucket()); 19 | Assert.False(headResp.IsSuccess); 20 | } 21 | } -------------------------------------------------------------------------------- /Src/ProviderTests/Buckets/ListBucketsTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.ProviderTests.Code; 2 | using Genbox.ProviderTests.Misc; 3 | using Genbox.SimpleS3.Core.Abstracts; 4 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 5 | using Genbox.SimpleS3.Utility.Shared; 6 | 7 | namespace Genbox.ProviderTests.Buckets; 8 | 9 | public class ListBucketsTests : TestBase 10 | { 11 | [Theory] 12 | [MultipleProviders(S3Provider.All)] 13 | public async Task ListBuckets(S3Provider _, string bucket, ISimpleClient client) 14 | { 15 | ListBucketsResponse listResp = await client.ListBucketsAsync(); 16 | Assert.True(listResp.Buckets.Count > 0); 17 | Assert.Single(listResp.Buckets, x => x.BucketName == bucket); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/ProviderTests/Buckets/PutPublicAccessBlockTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.ProviderTests.Code; 2 | using Genbox.ProviderTests.Misc; 3 | using Genbox.SimpleS3.Core.Abstracts; 4 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 5 | using Genbox.SimpleS3.Utility.Shared; 6 | 7 | namespace Genbox.ProviderTests.Buckets; 8 | 9 | public class PutPublicAccessBlockTests : TestBase 10 | { 11 | [Theory] 12 | [MultipleProviders(S3Provider.AmazonS3)] 13 | public async Task PutPublicAccessBlockRequest(S3Provider provider, string _, ISimpleClient client) 14 | { 15 | await CreateTempBucketAsync(provider, client, async tempBucket => 16 | { 17 | PutPublicAccessBlockResponse resp = await client.PutPublicAccessBlockAsync(tempBucket); 18 | Assert.Equal(200, resp.StatusCode); 19 | }); 20 | } 21 | } -------------------------------------------------------------------------------- /Src/ProviderTests/Code/TestConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.ProviderTests.Code; 2 | 3 | internal static class TestConstants 4 | { 5 | public const string TestUsername = "qvistian"; 6 | public const string TestEmail = "qvistian@gmail.com"; 7 | public const string TestUserId = "c5c6efaa2ab5d42d85f044a90bfb0bfcfc1daa322d725a2aeff1915fb31717ce"; 8 | } -------------------------------------------------------------------------------- /Src/ProviderTests/Misc/GetObjectTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.ProviderTests.Code; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Extensions; 4 | using Genbox.SimpleS3.Utility.Shared; 5 | 6 | namespace Genbox.ProviderTests.Misc; 7 | 8 | public class MiscTests : TestBase 9 | { 10 | [Theory] 11 | [MultipleProviders(S3Provider.AmazonS3)] 12 | public async Task IsEncodingCorrect(S3Provider _, string bucket, ISimpleClient client) 13 | { 14 | //This tests if '=' is NOT encoded. S3 does not use encoding of paths in signed requests, but all other AWS APIs do 15 | var putResp = await client.PutObjectStringAsync(bucket, "a=a", "hello"); 16 | Assert.Equal(200, putResp.StatusCode); 17 | } 18 | } -------------------------------------------------------------------------------- /Src/ProviderTests/Objects/DeleteObjectTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.ProviderTests.Code; 2 | using Genbox.ProviderTests.Misc; 3 | using Genbox.SimpleS3.Core.Abstracts; 4 | using Genbox.SimpleS3.Core.Network.Responses.Objects; 5 | using Genbox.SimpleS3.Utility.Shared; 6 | 7 | namespace Genbox.ProviderTests.Objects; 8 | 9 | public class DeleteObjectTests : TestBase 10 | { 11 | [Theory] 12 | [MultipleProviders(S3Provider.All)] 13 | public async Task DeleteObject(S3Provider provider, string bucket, ISimpleClient client) 14 | { 15 | PutObjectResponse putResp = await client.PutObjectAsync(bucket, nameof(DeleteObject), null); 16 | Assert.Equal(200, putResp.StatusCode); 17 | 18 | DeleteObjectResponse delREsp = await client.DeleteObjectAsync(bucket, nameof(DeleteObject)); 19 | Assert.Equal(204, delREsp.StatusCode); 20 | 21 | if (provider == S3Provider.AmazonS3) 22 | Assert.True(delREsp.IsDeleteMarker); 23 | } 24 | } -------------------------------------------------------------------------------- /Src/ProviderTests/ProviderTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | PreserveNewest 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Src/ProviderTests/README.md: -------------------------------------------------------------------------------- 1 | To use the ProviderTests project you will need to setup the test profiles. Run the utility 'TestSetup' to create the profiles. 2 | 3 | For Amazon S3 tests to work, update the TestConstants.cs file with the values specific to your account. -------------------------------------------------------------------------------- /Src/SimpleS3.AmazonS3.Tests/SimpleS3.AmazonS3.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/SimpleS3.AmazonS3.Tests/StaticCreatorTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.TestBase.Code; 2 | using Genbox.SimpleS3.Extensions.AmazonS3; 3 | 4 | namespace Genbox.SimpleS3.AmazonS3.Tests; 5 | 6 | public class StaticCreatorTests 7 | { 8 | [Fact] 9 | public async Task StaticClient() 10 | { 11 | NullNetworkDriver driver = new NullNetworkDriver(); 12 | 13 | AmazonS3Config config = new AmazonS3Config("ExampleKeyId00000000", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", AmazonS3Region.UsEast1); 14 | using AmazonS3Client client = new AmazonS3Client(config, driver); 15 | 16 | await client.GetObjectAsync("testbucket", "GetObjectAsync"); 17 | Assert.Equal("https://testbucket.s3.us-east-1.amazonaws.com/GetObjectAsync", driver.LastUrl); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.AmazonS3/SimpleS3.AmazonS3.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Src/SimpleS3.BackBlazeB2.Tests/SimpleS3.BackBlazeB2.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/SimpleS3.BackBlazeB2.Tests/StaticCreatorTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.TestBase.Code; 2 | using Genbox.SimpleS3.Extensions.BackBlazeB2; 3 | 4 | namespace Genbox.SimpleS3.BackBlazeB2.Tests; 5 | 6 | public class StaticCreatorTests 7 | { 8 | [Fact] 9 | public async Task StaticClient() 10 | { 11 | NullNetworkDriver driver = new NullNetworkDriver(); 12 | 13 | BackBlazeB2Config config = new BackBlazeB2Config("ExampleKeyId00000000", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", BackBlazeB2Region.UsWest001); 14 | using BackBlazeB2Client client = new BackBlazeB2Client(config, driver); 15 | 16 | await client.GetObjectAsync("testbucket", "GetObjectAsync"); 17 | Assert.Equal("https://testbucket.s3.us-west-001.backblazeb2.com/GetObjectAsync", driver.LastUrl); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.BackBlazeB2/SimpleS3.BackBlazeB2.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Authentication/IAccessKey.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | 3 | public interface IAccessKey 4 | { 5 | string KeyId { get; } 6 | byte[] SecretKey { get; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Authentication/IAccessKeyProtector.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | 3 | public interface IAccessKeyProtector 4 | { 5 | byte[] ProtectKey(byte[] key); 6 | byte[] UnprotectKey(byte[] key); 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Authentication/IAuthorizationBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Authentication; 4 | 5 | public interface IAuthorizationBuilder 6 | { 7 | void BuildAuthorization(IRequest request); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Authentication/IChunkedSignatureBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Authentication; 4 | 5 | public interface IChunkedSignatureBuilder 6 | { 7 | byte[] CreateChunkSignature(IRequest request, byte[] previousSignature, byte[] content, int offset, int length); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Authentication/IScopeBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | 3 | public interface IScopeBuilder 4 | { 5 | string CreateScope(string service, DateTimeOffset date); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Authentication/ISignatureBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Authentication; 4 | 5 | public interface ISignatureBuilder 6 | { 7 | byte[] CreateSignature(IRequest request, bool enablePayloadSignature = true); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Authentication/ISigningKeyBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | 3 | public interface ISigningKeyBuilder 4 | { 5 | byte[] CreateSigningKey(DateTimeOffset dateTime); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Enums/HttpMethodType.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable InconsistentNaming 2 | namespace Genbox.SimpleS3.Core.Abstracts.Enums; 3 | 4 | public enum HttpMethodType 5 | { 6 | Unknown = 0, 7 | GET, 8 | PUT, 9 | HEAD, 10 | DELETE, 11 | POST 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Enums/NamingMode.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Enums; 2 | 3 | public enum NamingMode 4 | { 5 | Unknown = 0, 6 | VirtualHost, 7 | PathStyle 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Enums/SignatureMode.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Enums; 2 | 3 | public enum SignatureMode : byte 4 | { 5 | Unknown = 0, 6 | Unsigned, 7 | FullSignature, 8 | StreamingSignature 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Enums/ValidationStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Enums; 2 | 3 | public enum ValidationStatus 4 | { 5 | Unknown = 0, 6 | Ok, 7 | NullInput, 8 | WrongLength, 9 | WrongFormat, 10 | ReservedName 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Factories/IMarshalFactory.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | 4 | namespace Genbox.SimpleS3.Core.Abstracts.Factories; 5 | 6 | public interface IMarshalFactory 7 | { 8 | Stream? MarshalRequest(SimpleS3Config config, TRequest request) where TRequest : IRequest; 9 | void MarshalResponse(SimpleS3Config config, TResponse response, IDictionary headers, Stream responseStream) where TResponse : IResponse; 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Factories/IPostMapperFactory.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | 4 | namespace Genbox.SimpleS3.Core.Abstracts.Factories; 5 | 6 | public interface IPostMapperFactory 7 | { 8 | void PostMap(SimpleS3Config config, TRequest request, TResponse response) where TRequest : IRequest where TResponse : IResponse; 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Factories/IRequestValidatorFactory.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Factories; 4 | 5 | public interface IRequestValidatorFactory 6 | { 7 | void ValidateAndThrow(T obj) where T : IRequest; 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/ICoreBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts; 4 | 5 | public interface ICoreBuilder 6 | { 7 | IServiceCollection Services { get; } 8 | 9 | string Name { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Provider/IEndpointBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Provider; 4 | 5 | public interface IEndpointBuilder 6 | { 7 | IEndpointData GetEndpoint(IRequest request); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Provider/IEndpointData.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Provider; 2 | 3 | public interface IEndpointData 4 | { 5 | string Host { get; } 6 | string Endpoint { get; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Provider/IInputValidator.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Provider; 4 | 5 | public interface IInputValidator 6 | { 7 | bool TryValidateKeyId(string? keyId, out ValidationStatus status, out string? message); 8 | bool TryValidateAccessKey(byte[]? accessKey, out ValidationStatus status, out string? message); 9 | bool TryValidateBucketName(string? bucketName, BucketNameValidationMode mode, out ValidationStatus status, out string? message); 10 | bool TryValidateObjectKey(string? objectKey, ObjectKeyValidationMode mode, out ValidationStatus status, out string? message); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Region/IRegionConverter.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Region; 2 | 3 | public interface IRegionConverter 4 | { 5 | IRegionInfo GetRegion(int enumValue); 6 | IRegionInfo GetRegion(string regionCode); 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Region/IRegionData.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Region; 2 | 3 | public interface IRegionData 4 | { 5 | IEnumerable GetRegions(); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Region/IRegionInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Region; 2 | 3 | public interface IRegionInfo 4 | { 5 | Enum EnumValue { get; } 6 | string Code { get; } 7 | string Name { get; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Region/RegionInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Region; 2 | 3 | public class RegionInfo(Enum enumValue, string code, string name) : IRegionInfo 4 | { 5 | public Enum EnumValue { get; } = enumValue; 6 | public string Code { get; } = code; 7 | public string Name { get; } = name; 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Request/INetworkDriver.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Request; 4 | 5 | public interface INetworkDriver 6 | { 7 | Task SendRequestAsync(IRequest request, string url, Stream? requestStream, CancellationToken cancellationToken = default) where T : IResponse; 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Request/IRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Request; 4 | 5 | public interface IRequestHandler 6 | { 7 | Task SendRequestAsync(TReq request, CancellationToken token = default) where TReq : IRequest where TResp : IResponse, new(); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Request/IRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Request; 4 | 5 | [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] 6 | public interface IRequestMarshal; 7 | 8 | public interface IRequestMarshal : IRequestMarshal where T : IRequest 9 | { 10 | Stream? MarshalRequest(T request, SimpleS3Config config); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Request/IResponseHandler.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Request; 4 | 5 | public interface IResponseHandler 6 | { 7 | Task HandleResponseAsync(TReq request, string url, Stream? requestStream, CancellationToken token) where TReq : IRequest where TResp : IResponse, new(); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Request/ISignedRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | 4 | namespace Genbox.SimpleS3.Core.Abstracts.Request; 5 | 6 | public interface ISignedRequestHandler 7 | { 8 | string SignRequest(TReq request, TimeSpan expiresIn) where TReq : IRequest; 9 | 10 | Task SendRequestAsync(string url, HttpMethodType httpMethod, Stream? content = null, CancellationToken token = default) where TResp : IResponse, new(); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Response/HttpResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | public readonly struct HttpResponse(Stream? content, IDictionary headers, int statusCode) 4 | { 5 | public Stream? Content { get; } = content; 6 | public IDictionary Headers { get; } = headers; 7 | public int StatusCode { get; } = statusCode; 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Response/IError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Response; 4 | 5 | public interface IError 6 | { 7 | /// Contains the error code returned from AWS S3 8 | ErrorCode Code { get; } 9 | 10 | /// Contains the message returned from AWS S3 11 | string Message { get; } 12 | 13 | /// Additional info that was returned from the error 14 | IDictionary Data { get; } 15 | 16 | /// Returns a string with the most important fields. This only works if the error is a specialized subtype of the GenericError class 17 | string GetErrorDetails(); 18 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Response/IPostMapper.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Abstracts.Response; 5 | 6 | [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] 7 | public interface IPostMapper; 8 | 9 | public interface IPostMapper : IPostMapper where TRequest : IRequest where TResponse : IResponse 10 | { 11 | void PostMap(TRequest request, TResponse response); 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Response/IResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Response; 4 | 5 | [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] 6 | public interface IResponseMarshal; 7 | 8 | public interface IResponseMarshal : IResponseMarshal where TResponse : IResponse 9 | { 10 | void MarshalResponse(SimpleS3Config config, TResponse response, IDictionary headers, Stream responseStream); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/ServiceBuilderBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts; 4 | 5 | public abstract class ServiceBuilderBase(IServiceCollection services, string? name = null) 6 | { 7 | public static string DefaultName => string.Empty; 8 | 9 | public IServiceCollection Services { get; } = services; 10 | 11 | public string Name { get; } = name ?? DefaultName; 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/SimpleS3.Core.Abstracts.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Wrappers/IRequestStreamWrapper.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Wrappers; 4 | 5 | /// Interface for stateless wrappers. USe this when you want to wrap streams on a low level before sending to the S3 API. 6 | public interface IRequestStreamWrapper 7 | { 8 | bool IsSupported(IRequest request); 9 | 10 | Stream Wrap(Stream input, IRequest request); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Wrappers/IRequestWrapper.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Request; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Wrappers; 4 | 5 | /// Interface for defining stateful wrappers. This is used for when you wish to wrap the whole request stream. 6 | public interface IRequestWrapper 7 | { 8 | bool IsSupported(IRequest request); 9 | 10 | Stream Wrap(Stream input, IRequest request); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Wrappers/IResponseStreamWrapper.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Wrappers; 4 | 5 | public interface IResponseStreamWrapper 6 | { 7 | bool IsSupported(IResponse response); 8 | 9 | Stream Wrap(Stream input, IResponse response); 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Abstracts/Wrappers/IResponseWrapper.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Wrappers; 4 | 5 | public interface IResponseWrapper 6 | { 7 | bool IsSupported(IResponse response); 8 | 9 | Stream Wrap(Stream input, IResponse response); 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Benchmarks/.globalconfig: -------------------------------------------------------------------------------- 1 | dotnet_diagnostic.CA1515.severity = none # Consider making public types internal 2 | dotnet_diagnostic.CS8618.severity = none # Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. 3 | dotnet_diagnostic.CA1822.severity = none # Mark members as static 4 | -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Benchmarks/Benchmarks/CharHelperBenchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Genbox.SimpleS3.Core.Common.Helpers; 3 | 4 | namespace Genbox.SimpleS3.Core.Benchmarks.Benchmarks; 5 | 6 | [SuppressMessage("ReSharper", "ConvertToConstant.Local")] 7 | public class CharHelperBenchmarks 8 | { 9 | [Benchmark] 10 | public bool CharRangeWithOr() 11 | { 12 | char c = 'f'; 13 | return c is >= 'a' or <= '<'; 14 | } 15 | 16 | [Benchmark] 17 | public bool CharRangeWithHelper() 18 | { 19 | char c = 'f'; 20 | return CharHelper.InRange(c, 'a', 'z'); 21 | } 22 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Benchmarks/Benchmarks/TypeLookupBenchmarks.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Benchmarks.Benchmarks; 2 | 3 | public class TypeLookupBenchmarks 4 | { 5 | private readonly HashSet _stringDict = new HashSet(); 6 | private readonly Type _type = typeof(TypeLookupBenchmarks); 7 | private readonly HashSet _typeDict = new HashSet(); 8 | 9 | [IterationCleanup] 10 | public void Cleanup() 11 | { 12 | _stringDict.Clear(); 13 | _typeDict.Clear(); 14 | } 15 | 16 | [Benchmark] 17 | public void AddWithString() 18 | { 19 | _stringDict.Add(_type.Name); 20 | } 21 | 22 | [Benchmark] 23 | public bool LookupWithString() => _stringDict.Contains(_type.Name); 24 | 25 | [Benchmark] 26 | public void AddWithType() 27 | { 28 | _typeDict.Add(_type); 29 | } 30 | 31 | [Benchmark] 32 | public bool LookupWithType() => _typeDict.Contains(_type); 33 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Benchmarks/Misc/DummyRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Network.Requests; 3 | 4 | namespace Genbox.SimpleS3.Core.Benchmarks.Misc; 5 | 6 | public class DummyRequest() : BaseRequest(HttpMethodType.GET); -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Benchmarks/SimpleS3.Core.Benchmarks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common.Tests/Code/TestEnum.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Tests.Code; 4 | 5 | internal enum TestEnum 6 | { 7 | Unknown = 0, 8 | Value1 = 1, 9 | Value2 = 2, 10 | 11 | [Display(Name = "Value3-FromAttribute")] 12 | Value3 = 3 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common.Tests/Code/TestRegion.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common.Tests.Code; 2 | 3 | internal enum TestRegion 4 | { 5 | RegionOne, 6 | RegionTwo 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common.Tests/Code/TestRegionData.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Region; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Tests.Code; 4 | 5 | internal sealed class TestRegionData : IRegionData 6 | { 7 | public IEnumerable GetRegions() 8 | { 9 | yield return new RegionInfo(TestRegion.RegionOne, "Region-One", "The first region"); 10 | yield return new RegionInfo(TestRegion.RegionTwo, "Region-Two", "The second region"); 11 | } 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common.Tests/SimpleS3.Core.Common.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Authentication/AccessKey.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common.Authentication; 2 | 3 | /// Stores an access key in raw format. This is more secure than using as the backing byte array can be garbage collected. 4 | public class AccessKey(string keyId, byte[] secretKey) : AccessKeyBase(keyId, secretKey); -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Authentication/AccessKeyBase.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Authentication; 4 | 5 | /// Provides a common base for access keys 6 | public abstract class AccessKeyBase(string keyId, byte[] secretKey) : IAccessKey 7 | { 8 | public string KeyId { get; } = keyId; 9 | public byte[] SecretKey { get; } = secretKey; 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Authentication/StringAccessKey.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Authentication; 4 | 5 | /// Provides a convenient way to provide an access key as string. However, it is insecure as you store the key as a string that does not get garbage collected. 6 | public class StringAccessKey(string keyId, string secretKey) : AccessKeyBase(keyId, Encoding.UTF8.GetBytes(secretKey)); -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Exceptions/S3Exception.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common.Exceptions; 2 | 3 | public class S3Exception(string? message = null, Exception? innException = null) : Exception(message, innException); -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Exceptions/S3RequestException.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Exceptions; 4 | 5 | public class S3RequestException(IResponse response, string? message = null, Exception? innerException = null) : S3Exception(message, innerException) 6 | { 7 | public IResponse Response { get; } = response; 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Extensions/RegionConverterExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Genbox.SimpleS3.Core.Abstracts.Region; 3 | 4 | namespace Genbox.SimpleS3.Core.Common.Extensions; 5 | 6 | public static class RegionConverterExtensions 7 | { 8 | public static IRegionInfo GetRegion(this IRegionConverter converter, Enum enumValue) 9 | { 10 | int intVal = (int)Convert.ChangeType(enumValue, typeof(int), NumberFormatInfo.InvariantInfo); 11 | return converter.GetRegion(intVal); 12 | } 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common.Extensions; 2 | 3 | public static class StringExtensions 4 | { 5 | public static bool Contains(this string str, string value, StringComparison comparison) => str.IndexOf(value, comparison) >= 0; 6 | 7 | public static bool Contains(this string str, char value) => str.IndexOf(value) >= 0; 8 | 9 | public static bool EndsWith(this string str, char character) 10 | { 11 | if (str.Length == 0) 12 | return false; 13 | 14 | return str[str.Length - 1] == character; 15 | } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Helpers/CharHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Helpers; 4 | 5 | public static class CharHelper 6 | { 7 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 8 | public static bool InRange(char c, char min, char max) => unchecked((uint)(c - min) <= (uint)(max - min)); 9 | 10 | public static bool OneOf(char c, params char[] chars) 11 | { 12 | foreach (char ch in chars) 13 | { 14 | if (c == ch) 15 | return true; 16 | } 17 | 18 | return false; 19 | } 20 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Helpers/KeyHelper.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Helpers; 4 | 5 | public static class KeyHelper 6 | { 7 | public static byte[] ProtectKey(byte[] key, IAccessKeyProtector? protector, bool clearKey = true) 8 | { 9 | if (protector == null) 10 | return key; 11 | 12 | byte[] previous = key; 13 | key = protector.ProtectKey(key); 14 | 15 | if (clearKey) 16 | Array.Clear(previous, 0, previous.Length); 17 | 18 | return key; 19 | } 20 | 21 | public static byte[] UnprotectKey(byte[] key, IAccessKeyProtector? protector) 22 | { 23 | if (protector == null) 24 | return key; 25 | 26 | return protector.UnprotectKey(key); 27 | } 28 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/HttpVersion.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common; 2 | 3 | public enum HttpVersion 4 | { 5 | Unknown, 6 | Http1, 7 | Http2, 8 | Http3 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Internal/Compat/CallerArgumentExpressionAttribute.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | 3 | // ReSharper disable All 4 | namespace System.Runtime.CompilerServices; 5 | 6 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] 7 | internal sealed class CallerArgumentExpressionAttribute : Attribute 8 | { 9 | public CallerArgumentExpressionAttribute(string parameterName) 10 | { 11 | ParameterName = parameterName; 12 | } 13 | 14 | public string ParameterName { get; } 15 | } 16 | #endif -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Internal/Compat/DoesNotReturnIfAttribute.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | 3 | // ReSharper disable All 4 | namespace System.Diagnostics.CodeAnalysis; 5 | 6 | [AttributeUsage(AttributeTargets.Parameter)] 7 | internal sealed class DoesNotReturnIfAttribute : Attribute 8 | { 9 | public DoesNotReturnIfAttribute(bool notUsed) {} 10 | } 11 | #endif -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Internal/Compat/NotNullAttribute.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | 3 | // ReSharper disable All 4 | namespace System.Diagnostics.CodeAnalysis; 5 | 6 | [AttributeUsage(AttributeTargets.Parameter)] 7 | internal sealed class NotNullAttribute : Attribute 8 | { 9 | public NotNullAttribute() {} 10 | } 11 | #endif -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Marshal/IHasBucketName.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common.Marshal; 2 | 3 | public interface IHasBucketName 4 | { 5 | string BucketName { get; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Marshal/IHasObjectKey.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common.Marshal; 2 | 3 | public interface IHasObjectKey 4 | { 5 | string ObjectKey { get; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Misc/Constants.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Genbox.SimpleS3.Core.Common.Misc; 4 | 5 | public static class Constants 6 | { 7 | public const string EmptySha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; 8 | public const string AmzMetadata = "x-amz-meta-"; 9 | public static readonly string DefaultUserAgent = "SimpleS3 library " + typeof(Constants).Assembly.GetName().Version; 10 | public static readonly string EmptyMd5 = "d41d8cd98f00b204e9800998ecf8427e"; 11 | public static readonly byte[] EmptyMd5Bytes = [0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e]; 12 | public static readonly UTF8Encoding Utf8NoBom = new UTF8Encoding(false); 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/SimpleS3.Core.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Common/Validation/RequireException.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Common.Validation; 2 | 3 | public class RequireException(string callerArgument, string callerMember, int lineNumber, string? message = null) : Exception(message) 4 | { 5 | public string CallerArgument { get; } = callerArgument; 6 | public string CallerMember { get; } = callerMember; 7 | public int LineNumber { get; } = lineNumber; 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.TestBase/Code/NullNetworkDriver.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Abstracts.Response; 4 | 5 | namespace Genbox.SimpleS3.Core.TestBase.Code; 6 | 7 | [SuppressMessage("Maintainability", "CA1515:Consider making public types internal")] 8 | public class NullNetworkDriver : INetworkDriver 9 | { 10 | public string? LastUrl { get; private set; } 11 | 12 | public Task SendRequestAsync(IRequest request, string url, Stream? requestStream, CancellationToken cancellationToken = default) where T : IResponse 13 | { 14 | LastUrl = url; 15 | return Task.FromResult(new HttpResponse(null, new Dictionary(), 200)); 16 | } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Tests/GenericTests/Builders/KmsContextBuilderTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Builders; 2 | 3 | namespace Genbox.SimpleS3.Core.Tests.GenericTests.Builders; 4 | 5 | public class KmsContextBuilderTests 6 | { 7 | [Fact] 8 | public void DisallowSpecialChars() 9 | { 10 | KmsContextBuilder b = new KmsContextBuilder(); 11 | Assert.Throws(() => b.AddEntry("!", "¤")); 12 | } 13 | 14 | [Fact] 15 | public void GenericTest() 16 | { 17 | KmsContextBuilder b = new KmsContextBuilder(); 18 | Assert.Null(b.Build()); 19 | 20 | b.AddEntry("SomeKey", "SomeValue"); 21 | 22 | Assert.Equal("\"SomeKey\":\"SomeValue\"", b.Build()); 23 | 24 | b.AddEntry("SomeOtherKey", "SomeOtherValue"); 25 | 26 | Assert.Equal("\"SomeKey\":\"SomeValue\",\"SomeOtherKey\":\"SomeOtherValue\"", b.Build()); 27 | } 28 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Tests/GenericTests/Builders/MetadataBuilderTests.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Genbox.SimpleS3.Core.Builders; 3 | 4 | namespace Genbox.SimpleS3.Core.Tests.GenericTests.Builders; 5 | 6 | public class MetadataBuilderTests 7 | { 8 | [Fact] 9 | public void InvalidChars() 10 | { 11 | MetadataBuilder b = new MetadataBuilder(); 12 | 13 | foreach (char invalidChar in "\t\0\n") 14 | Assert.Throws(() => { b.Add("a", invalidChar.ToString(CultureInfo.InvariantCulture)); }); 15 | } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core.Tests/SimpleS3.Core.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/Clients/ISignedClient.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Abstracts.Response; 4 | 5 | namespace Genbox.SimpleS3.Core.Abstracts.Clients; 6 | 7 | public interface ISignedClient 8 | { 9 | string SignRequest(TReq request, TimeSpan expiresIn) where TReq : IRequest; 10 | Task SendSignedRequestAsync(string url, HttpMethodType httpMethod, Stream? content = null, CancellationToken token = default) where TResp : IResponse, new(); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/Features/IAutoMapConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Features; 2 | 3 | public interface IAutoMapConfig 4 | { 5 | Func AutoMapDisabledFor { get; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/Features/IContainSensitiveMaterial.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Features; 2 | 3 | public interface IContainSensitiveMaterial 4 | { 5 | void ClearSensitiveMaterial(); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/Features/IContentMd5Config.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Abstracts.Features; 4 | 5 | public interface IContentMd5Config : IHasContentMd5 6 | { 7 | Func ForceContentMd5 { get; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/Features/ISupportStreaming.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Features; 2 | 3 | public interface ISupportStreaming; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/ISimpleClient.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Clients; 2 | using Genbox.SimpleS3.Core.Abstracts.Transfer; 3 | 4 | namespace Genbox.SimpleS3.Core.Abstracts; 5 | 6 | public interface ISimpleClient : IBucketClient, IObjectClient, IMultipartClient, ITransfer, IMultipartTransfer, ISignedClient; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/Operations/ISignedOperations.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Abstracts.Response; 4 | 5 | namespace Genbox.SimpleS3.Core.Abstracts.Operations; 6 | 7 | public interface ISignedOperations 8 | { 9 | string SignRequest(TReq request, TimeSpan expiresIn) where TReq : IRequest; 10 | Task SendSignedRequestAsync(string url, HttpMethodType httpMethod, Stream? content = null, CancellationToken token = default) where TResp : IResponse, new(); 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Abstracts/Transfer/ITransfer.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Abstracts.Transfer; 2 | 3 | public interface ITransfer 4 | { 5 | IUpload CreateUpload(string bucket, string objectKey); 6 | IDownload CreateDownload(string bucket, string objectKey); 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Builders/MfaAuthenticationBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.HttpBuilders.Abstracts; 2 | 3 | namespace Genbox.SimpleS3.Core.Builders; 4 | 5 | public class MfaAuthenticationBuilder : IHttpHeaderBuilder 6 | { 7 | private string? _serialNumber; 8 | private string? _value; 9 | 10 | public string? HeaderName => null; 11 | 12 | public string? Build() 13 | { 14 | if (!HasData()) 15 | return null; 16 | 17 | return $"{_serialNumber} {_value}"; 18 | } 19 | 20 | public void Reset() 21 | { 22 | _serialNumber = null; 23 | _value = null; 24 | } 25 | 26 | public bool HasData() => _serialNumber != null; 27 | 28 | public void SetAuth(string serialNumber, string value) 29 | { 30 | _serialNumber = serialNumber; 31 | _value = value; 32 | } 33 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/ChecksumAlgorithm.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | /// Indicates the algorithm that you want Amazon S3 to use to create the checksum for the object. For more information, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html 7 | [FastEnum] 8 | public enum ChecksumAlgorithm 9 | { 10 | Unknown = 0, 11 | [Display(Name = "CRC32")]Crc32, 12 | [Display(Name = "CRC32C")]Crc32C, 13 | [Display(Name = "SHA1")]Sha1, 14 | [Display(Name = "SHA256")]Sha256, 15 | [Display(Name = "CRC64NVME")]Crc64Nvme, 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/ChecksumType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | /// Indicates the checksum type that you want Amazon S3 to use to calculate the object’s checksum value. For more information, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html 7 | [FastEnum] 8 | public enum ChecksumType 9 | { 10 | Unknown = 0, 11 | [Display(Name = "COMPOSITE")]Composite, 12 | [Display(Name = "FULL_OBJECT")]FullObject 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/CompressionType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum CompressionType 8 | { 9 | Unknown = 0, 10 | [Display(Name = "NONE")]None, 11 | [Display(Name = "GZIP")]Gzip, 12 | [Display(Name = "BZIP2")]Bzip 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/EncodingType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | /// Used to specify the encoding of responses when using certain APIs that are based on XML. 7 | [FastEnum] 8 | public enum EncodingType 9 | { 10 | Unknown = 0, 11 | [Display(Name = "url")]Url 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/ExpressionType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum ExpressionType 8 | { 9 | Unknown = 0, 10 | [Display(Name = "SQL")]Sql 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/GrantType.cs: -------------------------------------------------------------------------------- 1 | using Genbox.FastEnum; 2 | 3 | namespace Genbox.SimpleS3.Core.Enums; 4 | 5 | [FastEnum] 6 | public enum GrantType 7 | { 8 | Unknown = 0, 9 | Group, 10 | CanonicalUser, 11 | AmazonCustomerByEmail 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/HeaderUsage.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum HeaderUsage 8 | { 9 | Unknown = 0, 10 | [Display(Name = "NONE")]None, 11 | [Display(Name = "IGNORE")]Ignore, 12 | [Display(Name = "USE")]Use 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/JsonType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum JsonType 8 | { 9 | Unknown = 0, 10 | [Display(Name = "DOCUMENT")]Document, 11 | [Display(Name = "LINES")]Lines 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/MetadataDirective.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum MetadataDirective 8 | { 9 | Unknown = 0, 10 | [Display(Name = "COPY")]Copy, 11 | [Display(Name = "REPLACE")]Replace 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/ObjectPermissions.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Enums; 2 | 3 | [Flags] 4 | public enum ObjectPermissions 5 | { 6 | None = 0, 7 | 8 | /// Equivalent to s3:GetObject, s3:GetObjectVersion, and s3:GetObjectTorrent 9 | Read = 1, 10 | 11 | /// Equivalent to s3:GetObjectAcl and s3:GetObjectVersionAcl 12 | ReadAcl = 2, 13 | 14 | /// Equivalent to s3:PutObjectAcl and s3:PutObjectVersionAcl 15 | WriteAcl = 4, 16 | 17 | /// Equivalent to granting Read, ReadAcl, and WriteAcl permissions. 18 | FullControl = 8 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/Payer.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Enums; 2 | 3 | public enum Payer 4 | { 5 | Unknown = 0, 6 | Requester, 7 | Me 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/QuoteField.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum QuoteField 8 | { 9 | Unknown = 0, 10 | [Display(Name = "ALWAYS")]Always, 11 | [Display(Name = "ASNEEDED")]AsNeeded 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/ReplicationStatus.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum ReplicationStatus 8 | { 9 | Unknown = 0, 10 | [Display(Name = "PENDING")]Pending, 11 | [Display(Name = "COMPLETED")]Completed, 12 | [Display(Name = "FAILED")]Failed, 13 | [Display(Name = "REPLICA")]Replica 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/RestoreRequestType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum RestoreRequestType 8 | { 9 | Unknown = 0, 10 | [Display(Name = "SELECT")]Select 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/S3Permission.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum S3Permission 8 | { 9 | Unknown = 0, 10 | [Display(Name = "FULL_CONTROL")]FullControl, 11 | [Display(Name = "READ")]Read, 12 | [Display(Name = "WRITE")]Write 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/SseCustomerAlgorithm.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum SseCustomerAlgorithm 8 | { 9 | Unknown = 0, 10 | [Display(Name = "AES256")]Aes256 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Enums/TaggingDirective.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Genbox.FastEnum; 3 | 4 | namespace Genbox.SimpleS3.Core.Enums; 5 | 6 | [FastEnum] 7 | public enum TaggingDirective 8 | { 9 | Unknown = 0, 10 | [Display(Name = "COPY")]Copy, 11 | [Display(Name = "REPLACE")]Replace 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Extensions/CoreBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Clients; 3 | using Genbox.SimpleS3.Core.Internals.Clients; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.DependencyInjection.Extensions; 6 | 7 | namespace Genbox.SimpleS3.Core.Extensions; 8 | 9 | public static class CoreBuilderExtensions 10 | { 11 | public static ICoreBuilder UsePooledClients(this ICoreBuilder builder) 12 | { 13 | builder.Services.Replace(ServiceDescriptor.Singleton()); 14 | builder.Services.Replace(ServiceDescriptor.Singleton()); 15 | builder.Services.Replace(ServiceDescriptor.Singleton()); 16 | return builder; 17 | } 18 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Authentication/ScopeBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Authentication; 3 | using Genbox.SimpleS3.Core.Internals.Enums; 4 | using Genbox.SimpleS3.Core.Internals.Helpers; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Authentication; 8 | 9 | internal sealed class ScopeBuilder(IOptions options) : IScopeBuilder 10 | { 11 | private readonly SimpleS3Config _options = options.Value; 12 | 13 | public string CreateScope(string service, DateTimeOffset date) => $"{ValueHelper.DateToString(date, DateTimeFormat.Iso8601Date)}/{_options.RegionCode}/{service}/aws4_request"; 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Authentication/SigningConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Authentication; 2 | 3 | internal static class SigningConstants 4 | { 5 | public const string Scheme = "AWS4"; 6 | public const string AlgorithmTag = Scheme + "-" + Algorithm; 7 | public const string ChunkedAlgorithmTag = AlgorithmTag + "-PAYLOAD"; 8 | public const string AmazonHeaderPrefix = "x-amz-"; 9 | public const string Algorithm = "HMAC-SHA256"; 10 | public const char Colon = ':'; 11 | public const char SemiColon = ';'; 12 | public const char Newline = '\n'; 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Builders/QueryParameterAuthorizationBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Common.Validation; 5 | using Genbox.SimpleS3.Core.Internals.Extensions; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace Genbox.SimpleS3.Core.Internals.Builders; 9 | 10 | internal sealed class QueryParameterAuthorizationBuilder(ISignatureBuilder builder, ILogger logger) : IAuthorizationBuilder 11 | { 12 | public void BuildAuthorization(IRequest request) 13 | { 14 | Validator.RequireNotNull(request); 15 | 16 | logger.LogTrace("Building parameter based authorization"); 17 | request.SetQueryParameter(AmzParameters.XAmzSignature, builder.CreateSignature(request, false).HexEncode()); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Clients/SignedClient.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Clients; 2 | using Genbox.SimpleS3.Core.Abstracts.Enums; 3 | using Genbox.SimpleS3.Core.Abstracts.Operations; 4 | using Genbox.SimpleS3.Core.Abstracts.Request; 5 | using Genbox.SimpleS3.Core.Abstracts.Response; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Clients; 8 | 9 | internal class SignedClient(ISignedOperations operations) : ISignedClient 10 | { 11 | public string SignRequest(TReq request, TimeSpan expiresIn) where TReq : IRequest => operations.SignRequest(request, expiresIn); 12 | 13 | public Task SendSignedRequestAsync(string url, HttpMethodType httpMethod, Stream? content = null, CancellationToken token = default) where TResp : IResponse, new() => operations.SendSignedRequestAsync(url, httpMethod, content, token); 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Compat/NotNullWhenAttribute.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable All 2 | #if NETSTANDARD2_0 3 | namespace System.Diagnostics.CodeAnalysis; 4 | 5 | /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. 6 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] 7 | internal sealed class NotNullWhenAttribute : Attribute 8 | { 9 | /// Initializes the attribute with the specified return value condition. 10 | /// 11 | /// The return value condition. If the method returns this value, the associated parameter will not be null. 12 | /// 13 | public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; 14 | 15 | /// Gets the return value condition. 16 | public bool ReturnValue { get; } 17 | } 18 | #endif -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/CoreBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Genbox.SimpleS3.Core.Internals; 5 | 6 | internal sealed class CoreBuilder(IServiceCollection services, string? name = null) : ServiceBuilderBase(services, name), ICoreBuilder; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Enums/BinaryEncoding.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Enums; 2 | 3 | internal enum BinaryEncoding 4 | { 5 | Unknown = 0, 6 | Hex, 7 | Base64 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Enums/DateTimeFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Enums; 2 | 3 | internal enum DateTimeFormat 4 | { 5 | Unknown = 0, 6 | Iso8601Date, 7 | Iso8601DateTime, 8 | Iso8601DateTimeExt, 9 | Rfc1123 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Extensions/QueueExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Extensions; 2 | 3 | /// This class is only necessary as long as we target .NET Standard 2.0 4 | internal static class QueueExtensions 5 | { 6 | public static bool TryDequeue(this Queue queue, out T? value) where T : class 7 | { 8 | if (queue.Count > 0) 9 | { 10 | value = queue.Dequeue(); 11 | return true; 12 | } 13 | 14 | value = null; 15 | return false; 16 | } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Extensions/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Extensions; 2 | 3 | internal static class TypeExtensions 4 | { 5 | internal static Type[] GetTypeArguments(this Type type) 6 | { 7 | Type[]? args = null; 8 | 9 | foreach (Type intType in type.GetInterfaces()) 10 | { 11 | args = intType.GetGenericArguments(); 12 | 13 | if (args.Length != 0) 14 | break; 15 | } 16 | 17 | if (args == null) 18 | throw new InvalidOperationException("Unable to find generic arguments"); 19 | 20 | return args; 21 | } 22 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Fluent/Transfer.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Operations; 3 | using Genbox.SimpleS3.Core.Abstracts.Transfer; 4 | 5 | namespace Genbox.SimpleS3.Core.Internals.Fluent; 6 | 7 | internal sealed class Transfer(IObjectOperations operations, IMultipartTransfer transfer) : ITransfer 8 | { 9 | public IUpload CreateUpload(string bucket, string objectKey) => new Upload(operations, transfer, bucket, objectKey); 10 | 11 | public IDownload CreateDownload(string bucket, string objectKey) => new Download(operations, transfer, bucket, objectKey); 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Helpers/CopyHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Helpers; 2 | 3 | internal static class CopyHelper 4 | { 5 | public static byte[]? CopyWithNull(byte[]? input) 6 | { 7 | if (input == null) 8 | return null; 9 | 10 | byte[] arr = new byte[input.Length]; 11 | Array.Copy(input, 0, arr, 0, input.Length); 12 | return arr; 13 | } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Helpers/XmlHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | 3 | namespace Genbox.SimpleS3.Core.Internals.Helpers; 4 | 5 | internal static class XmlHelper 6 | { 7 | public static IEnumerable ReadElements(XmlReader xmlReader, string? tagName = null) 8 | { 9 | //Support closed tags: 10 | if (xmlReader.IsEmptyElement && xmlReader.Name == tagName) 11 | yield break; 12 | 13 | while (xmlReader.Read()) 14 | { 15 | if (tagName != null && xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == tagName) 16 | break; 17 | 18 | if (xmlReader.NodeType != XmlNodeType.Element) 19 | continue; 20 | 21 | yield return xmlReader.Name; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/DeleteBucketPolicyRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class DeleteBucketPolicyRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(DeleteBucketPolicyRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Policy, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/DeleteBucketTaggingRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class DeleteBucketTaggingRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(DeleteBucketTaggingRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Tagging, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/GetBucketAccelerateConfigurationRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class GetBucketAccelerateConfigurationRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetBucketAccelerateConfigurationRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Accelerate, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/GetBucketLifecycleConfigurationRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class GetBucketLifecycleConfigurationRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetBucketLifecycleConfigurationRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Lifecycle, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/GetBucketLockConfigurationRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class GetBucketLockConfigurationRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetBucketLockConfigurationRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.ObjectLock, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/GetBucketPolicyRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class GetBucketPolicyRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetBucketPolicyRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Policy, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/GetBucketTaggingRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class GetBucketTaggingRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetBucketTaggingRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Tagging, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/GetBucketVersioningRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 7 | 8 | internal sealed class GetBucketVersioningRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetBucketVersioningRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Versioning, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Buckets/PutBucketPolicyRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Request; 4 | using Genbox.SimpleS3.Core.Common.Misc; 5 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets; 8 | 9 | internal sealed class PutBucketPolicyRequestMarshal : IRequestMarshal 10 | { 11 | public Stream MarshalRequest(PutBucketPolicyRequest request, SimpleS3Config config) 12 | { 13 | request.SetQueryParameter(AmzParameters.Policy, string.Empty); 14 | request.SetHeader(AmzHeaders.XAmzConfirmRemoveSelfBucketAccess, request.ConfirmRemoveSelfBucketAccess ? "true" : "false"); 15 | 16 | byte[] bytes = Encoding.UTF8.GetBytes(request.Policy); 17 | return new MemoryStream(bytes); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Multipart/CreateMultipartUploadRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Multipart; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Multipart; 7 | 8 | internal sealed class CreateMultipartUploadRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(CreateMultipartUploadRequest request, SimpleS3Config config) 11 | { 12 | //This is required for multipart uploads 13 | request.SetQueryParameter(AmzParameters.Uploads, string.Empty); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Objects/GetObjectAclRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Objects; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Objects; 7 | 8 | internal sealed class GetObjectAclRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetObjectAclRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Acl, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Objects/GetObjectLegalHoldRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Objects; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Objects; 7 | 8 | internal sealed class GetObjectLegalHoldRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetObjectLegalHoldRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.LegalHold, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Objects/GetObjectRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Objects; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Objects; 7 | 8 | internal sealed class GetObjectRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(GetObjectRequest request, SimpleS3Config config) 11 | { 12 | if (request.EnableChecksum) 13 | request.SetHeader(AmzHeaders.XAmzChecksumMode, "ENABLED"); 14 | 15 | return null; 16 | } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Objects/HeadObjectRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Objects; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Objects; 7 | 8 | internal sealed class HeadObjectRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(HeadObjectRequest request, SimpleS3Config config) 11 | { 12 | if (request.EnableChecksum) 13 | request.SetHeader(AmzHeaders.XAmzChecksumMode, "ENABLED"); 14 | 15 | return null; 16 | } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Requests/Objects/PutObjectAclRequestMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Requests.Objects; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Objects; 7 | 8 | internal sealed class PutObjectAclRequestMarshal : IRequestMarshal 9 | { 10 | public Stream? MarshalRequest(PutObjectAclRequest request, SimpleS3Config config) 11 | { 12 | request.SetQueryParameter(AmzParameters.Acl, string.Empty); 13 | return null; 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Buckets/GetBucketAccelerateConfigurationResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Response; 4 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Buckets; 7 | 8 | internal sealed class GetBucketAccelerateConfigurationResponseMarshal : IResponseMarshal 9 | { 10 | public void MarshalResponse(SimpleS3Config config, GetBucketAccelerateConfigurationResponse response, IDictionary headers, Stream responseStream) 11 | { 12 | using XmlTextReader xmlReader = new XmlTextReader(responseStream); 13 | xmlReader.ReadToDescendant("AccelerateConfiguration"); 14 | 15 | if (xmlReader.Read()) 16 | response.AccelerateEnabled = xmlReader.ReadElementContentAsString() == "Enabled"; 17 | } 18 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Buckets/GetBucketPolicyResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Response; 4 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Buckets; 7 | 8 | internal sealed class GetBucketPolicyResponseMarshal : IResponseMarshal 9 | { 10 | public void MarshalResponse(SimpleS3Config config, GetBucketPolicyResponse response, IDictionary headers, Stream responseStream) 11 | { 12 | using MemoryStream ms = new MemoryStream(); 13 | responseStream.CopyTo(ms); 14 | ms.Position = 0; 15 | 16 | response.Policy = Encoding.UTF8.GetString(ms.ToArray()); 17 | } 18 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Buckets/PutBucketLockConfigurationResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Buckets; 7 | 8 | internal sealed class PutBucketLockConfigurationResponseMarshal : IResponseMarshal 9 | { 10 | public void MarshalResponse(SimpleS3Config config, PutBucketLockConfigurationResponse response, IDictionary headers, Stream responseStream) 11 | { 12 | response.RequestCharged = headers.ContainsKey(AmzHeaders.XAmzRequestCharged); 13 | } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Buckets/PutBucketVersioningResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 4 | 5 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Buckets; 6 | 7 | internal sealed class PutBucketVersioningResponseMarshal : IResponseMarshal 8 | { 9 | public void MarshalResponse(SimpleS3Config config, PutBucketVersioningResponse response, IDictionary headers, Stream responseStream) 10 | { 11 | // The docs says there is an XML response, but there is none from the API. 12 | } 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Multipart/AbortMultipartUploadResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Responses.Multipart; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Multipart; 7 | 8 | internal sealed class AbortMultipartUploadResponseMarshal : IResponseMarshal 9 | { 10 | public void MarshalResponse(SimpleS3Config config, AbortMultipartUploadResponse response, IDictionary headers, Stream responseStream) 11 | { 12 | response.RequestCharged = headers.ContainsKey(AmzHeaders.XAmzRequestCharged); 13 | } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Objects/DeleteObjectResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Internals.Extensions; 5 | using Genbox.SimpleS3.Core.Network.Responses.Objects; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Objects; 8 | 9 | internal sealed class DeleteObjectResponseMarshal : IResponseMarshal 10 | { 11 | public void MarshalResponse(SimpleS3Config config, DeleteObjectResponse response, IDictionary headers, Stream responseStream) 12 | { 13 | response.IsDeleteMarker = headers.GetHeaderBool(AmzHeaders.XAmzDeleteMarker); 14 | response.VersionId = headers.GetOptionalValue(AmzHeaders.XAmzVersionId); 15 | response.RequestCharged = headers.ContainsKey(AmzHeaders.XAmzRequestCharged); 16 | } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Objects/GetObjectLegalHoldResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Response; 4 | using Genbox.SimpleS3.Core.Common.Misc; 5 | using Genbox.SimpleS3.Core.Network.Responses.Objects; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Objects; 8 | 9 | internal sealed class GetObjectLegalHoldResponseMarshal : IResponseMarshal 10 | { 11 | public void MarshalResponse(SimpleS3Config config, GetObjectLegalHoldResponse response, IDictionary headers, Stream responseStream) 12 | { 13 | response.RequestCharged = headers.ContainsKey(AmzHeaders.XAmzRequestCharged); 14 | 15 | using XmlTextReader reader = new XmlTextReader(responseStream); 16 | reader.ReadToDescendant("Status"); 17 | reader.Read(); 18 | response.LegalHold = reader.Value == "ON"; 19 | } 20 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Objects/PutObjectAclResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Responses.Objects; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Objects; 7 | 8 | internal sealed class PutObjectAclResponseMarshal : IResponseMarshal 9 | { 10 | public void MarshalResponse(SimpleS3Config config, PutObjectAclResponse response, IDictionary headers, Stream responseStream) 11 | { 12 | response.RequestCharged = headers.ContainsKey(AmzHeaders.XAmzRequestCharged); 13 | } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Objects/PutObjectLegalHoldResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Network.Responses.Objects; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Objects; 7 | 8 | internal sealed class PutObjectLegalHoldResponseMarshal : IResponseMarshal 9 | { 10 | public void MarshalResponse(SimpleS3Config config, PutObjectLegalHoldResponse response, IDictionary headers, Stream responseStream) 11 | { 12 | response.RequestCharged = headers.ContainsKey(AmzHeaders.XAmzRequestCharged); 13 | } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Marshallers/Responses/Objects/RestoreObjectResponseMarshal.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Response; 3 | using Genbox.SimpleS3.Core.Common.Misc; 4 | using Genbox.SimpleS3.Core.Internals.Extensions; 5 | using Genbox.SimpleS3.Core.Network.Responses.Objects; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.Objects; 8 | 9 | internal sealed class RestoreObjectResponseMarshal : IResponseMarshal 10 | { 11 | public void MarshalResponse(SimpleS3Config config, RestoreObjectResponse response, IDictionary headers, Stream responseStream) 12 | { 13 | response.RequestCharged = headers.ContainsKey(AmzHeaders.XAmzRequestCharged); 14 | response.RestoreOutputPath = headers.GetOptionalValue(AmzHeaders.XAmzRestoreOutputPath); 15 | } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Misc/DateTimeFormats.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Misc; 2 | 3 | internal static class DateTimeFormats 4 | { 5 | public const string Iso8601Date = "yyyyMMdd"; 6 | public const string Iso8601DateTime = @"yyyyMMdd\THHmmssZ"; 7 | public const string Iso8601DateTimeExtended = @"yyyy-MM-dd\THH:mm:ss.FFFFFFFZ"; //F = up to N fractional seconds 8 | public const string Rfc1123 = "R"; 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Network/EndpointData.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Provider; 2 | 3 | namespace Genbox.SimpleS3.Core.Internals.Network; 4 | 5 | internal class EndpointData(string host, string? bucket, string regionCode, string endpoint) : IEndpointData 6 | { 7 | public string? Bucket { get; } = bucket; 8 | public string RegionCode { get; } = regionCode; 9 | public string Host { get; } = host; 10 | public string Endpoint { get; } = endpoint; 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Network/SignedRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Network.Requests; 3 | 4 | namespace Genbox.SimpleS3.Core.Internals.Network; 5 | 6 | internal sealed class SignedRequest(HttpMethodType method) : BaseRequest(method); -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Operations/SignedOperations.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Abstracts.Operations; 3 | using Genbox.SimpleS3.Core.Abstracts.Request; 4 | using Genbox.SimpleS3.Core.Abstracts.Response; 5 | 6 | namespace Genbox.SimpleS3.Core.Internals.Operations; 7 | 8 | internal class SignedOperations(ISignedRequestHandler handler) : ISignedOperations 9 | { 10 | public string SignRequest(TReq request, TimeSpan expiresIn) where TReq : IRequest => handler.SignRequest(request, expiresIn); 11 | public Task SendSignedRequestAsync(string url, HttpMethodType httpMethod, Stream? content = null, CancellationToken token = default) where TResp : IResponse, new() => handler.SendRequestAsync(url, httpMethod, content, token); 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Pools/IPooledObject.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Pools; 2 | 3 | internal interface IPooledObject 4 | { 5 | void Reset(); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/PostMappers/UploadPartPostMapper.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | using Genbox.SimpleS3.Core.Network.Requests.Multipart; 3 | using Genbox.SimpleS3.Core.Network.Responses.Multipart; 4 | 5 | namespace Genbox.SimpleS3.Core.Internals.PostMappers; 6 | 7 | internal sealed class UploadPartPostMapper : IPostMapper 8 | { 9 | public void PostMap(UploadPartRequest request, UploadPartResponse response) 10 | { 11 | if (request.PartNumber.HasValue) 12 | response.PartNumber = request.PartNumber.Value; 13 | } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Validation/Validators/ConfigValidatorBase.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation.Results; 2 | using Microsoft.Extensions.Options; 3 | 4 | namespace Genbox.SimpleS3.Core.Internals.Validation.Validators; 5 | 6 | internal abstract class ConfigValidatorBase : ValidatorBase, IValidateOptions where T : class 7 | { 8 | public ValidateOptionsResult Validate(string? name, T options) 9 | { 10 | ValidationResult? results = base.Validate(options); 11 | 12 | if (results.IsValid) 13 | return ValidateOptionsResult.Success; 14 | 15 | return ValidateOptionsResult.Fail(results.Errors.Select(x => x.ErrorMessage)); 16 | } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Validation/Validators/Requests/Multipart/ListMultipartUploadsRequestValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Provider; 4 | using Genbox.SimpleS3.Core.Network.Requests.Multipart; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Validation.Validators.Requests.Multipart; 8 | 9 | internal sealed class ListMultipartUploadsRequestValidator : RequestValidatorBase 10 | { 11 | public ListMultipartUploadsRequestValidator(IInputValidator validator, IOptions config) : base(validator, config) 12 | { 13 | RuleFor(x => x.MaxUploads).GreaterThan(0).LessThanOrEqualTo(1000).When(x => x.MaxUploads != null); 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Validation/Validators/Requests/Objects/DeleteObjectsRequestValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Provider; 4 | using Genbox.SimpleS3.Core.Network.Requests.Objects; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Validation.Validators.Requests.Objects; 8 | 9 | internal sealed class DeleteObjectsRequestValidator : RequestValidatorBase 10 | { 11 | public DeleteObjectsRequestValidator(IInputValidator validator, IOptions config) : base(validator, config) 12 | { 13 | RuleFor(x => x.Objects).NotEmpty(); 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Validation/Validators/Requests/Objects/ListObjectsRequestValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Provider; 4 | using Genbox.SimpleS3.Core.Network.Requests.Objects; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Validation.Validators.Requests.Objects; 8 | 9 | internal sealed class ListObjectsRequestValidator : RequestValidatorBase 10 | { 11 | public ListObjectsRequestValidator(IInputValidator validator, IOptions config) : base(validator, config) 12 | { 13 | RuleFor(x => x.MaxKeys).GreaterThan(0).LessThanOrEqualTo(1000).When(x => x.MaxKeys != null); 14 | } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Validation/Validators/ValidatorBase.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Internals.Validation.Validators; 5 | 6 | [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] 7 | internal abstract class ValidatorBase : AbstractValidator; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Xml/XmlCharMode.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Xml; 2 | 3 | internal enum XmlCharMode 4 | { 5 | Unknown = 0, 6 | EntityEncode, 7 | Omit, 8 | ThrowException 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Internals/Xml/XmlStandard.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Internals.Xml; 2 | 3 | internal enum XmlStandard 4 | { 5 | Unknown = 0, 6 | Xml10, 7 | Xml11 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/DeleteBucketPolicyRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Builders; 3 | using Genbox.SimpleS3.Core.Common.Marshal; 4 | using Genbox.SimpleS3.Core.Enums; 5 | using Genbox.SimpleS3.Core.Network.Requests.Interfaces; 6 | 7 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 8 | 9 | public class DeleteBucketPolicyRequest : BaseRequest, IHasBucketName 10 | { 11 | internal DeleteBucketPolicyRequest() : base(HttpMethodType.DELETE) {} 12 | 13 | public DeleteBucketPolicyRequest(string bucketName) : this() 14 | { 15 | Initialize(bucketName); 16 | } 17 | 18 | public string BucketName { get; set; } 19 | 20 | internal void Initialize(string bucketName) 21 | { 22 | BucketName = bucketName; 23 | } 24 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/DeleteBucketRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Common.Marshal; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | /// Deletes a bucket. All objects (including all object versions and delete markers) in the bucket must be deleted before the bucket itself can be deleted. 7 | public class DeleteBucketRequest : BaseRequest, IHasBucketName 8 | { 9 | internal DeleteBucketRequest() : base(HttpMethodType.DELETE) {} 10 | 11 | public DeleteBucketRequest(string bucketName) : this() 12 | { 13 | Initialize(bucketName); 14 | } 15 | 16 | public string BucketName { get; set; } = null!; 17 | 18 | internal void Initialize(string bucketName) 19 | { 20 | BucketName = bucketName; 21 | } 22 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/DeleteBucketTaggingRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Common.Marshal; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | /// 7 | /// Deletes the tags from the bucket. o use this operation, you must have permission to perform the s3:PutBucketTagging action. By default, the bucket owner has this 8 | /// permission and can grant this permission to others. 9 | /// 10 | public class DeleteBucketTaggingRequest : BaseRequest, IHasBucketName 11 | { 12 | internal DeleteBucketTaggingRequest() : base(HttpMethodType.DELETE) {} 13 | 14 | public DeleteBucketTaggingRequest(string bucketName) : this() 15 | { 16 | Initialize(bucketName); 17 | } 18 | 19 | public string BucketName { get; set; } = null!; 20 | 21 | internal void Initialize(string bucketName) 22 | { 23 | BucketName = bucketName; 24 | } 25 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/GetBucketLifecycleConfigurationRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Common.Marshal; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | /// Returns the lifecycle configuration information set on the bucket. 7 | public class GetBucketLifecycleConfigurationRequest : BaseRequest, IHasBucketName 8 | { 9 | internal GetBucketLifecycleConfigurationRequest() : base(HttpMethodType.GET) {} 10 | 11 | public GetBucketLifecycleConfigurationRequest(string bucketName) : this() 12 | { 13 | Initialize(bucketName); 14 | } 15 | 16 | public string BucketName { get; set; } = null!; 17 | 18 | internal void Initialize(string bucketName) 19 | { 20 | BucketName = bucketName; 21 | } 22 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/GetBucketLockConfigurationRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Common.Marshal; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | /// 7 | /// Gets the Object Lock configuration for a bucket. The rule specified in the Object Lock configuration will be applied by default to every new object placed in the 8 | /// specified bucket. 9 | /// 10 | public class GetBucketLockConfigurationRequest : BaseRequest, IHasBucketName 11 | { 12 | internal GetBucketLockConfigurationRequest() : base(HttpMethodType.GET) {} 13 | 14 | public GetBucketLockConfigurationRequest(string bucketName) : this() 15 | { 16 | Initialize(bucketName); 17 | } 18 | 19 | public string BucketName { get; set; } = null!; 20 | 21 | internal void Initialize(string bucketName) 22 | { 23 | BucketName = bucketName; 24 | } 25 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/GetBucketPolicyRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Builders; 3 | using Genbox.SimpleS3.Core.Common.Marshal; 4 | using Genbox.SimpleS3.Core.Enums; 5 | using Genbox.SimpleS3.Core.Network.Requests.Interfaces; 6 | 7 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 8 | 9 | public class GetBucketPolicyRequest : BaseRequest, IHasBucketName 10 | { 11 | internal GetBucketPolicyRequest() : base(HttpMethodType.GET) {} 12 | 13 | public GetBucketPolicyRequest(string bucketName) : this() 14 | { 15 | Initialize(bucketName); 16 | } 17 | 18 | public string BucketName { get; set; } 19 | 20 | internal void Initialize(string bucketName) 21 | { 22 | BucketName = bucketName; 23 | } 24 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/GetBucketTaggingRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Common.Marshal; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | /// 7 | /// Returns the tag set associated with the bucket. To use this operation, you must have permission to perform the s3:GetBucketTagging action. By default, the bucket owner 8 | /// has this permission and can grant this permission to others. 9 | /// 10 | public class GetBucketTaggingRequest : BaseRequest, IHasBucketName 11 | { 12 | internal GetBucketTaggingRequest() : base(HttpMethodType.GET) {} 13 | 14 | public GetBucketTaggingRequest(string bucketName) : this() 15 | { 16 | Initialize(bucketName); 17 | } 18 | 19 | public string BucketName { get; set; } = null!; 20 | 21 | internal void Initialize(string bucketName) 22 | { 23 | BucketName = bucketName; 24 | } 25 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/GetBucketVersioningRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Common.Marshal; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | 6 | public class GetBucketVersioningRequest : BaseRequest, IHasBucketName 7 | { 8 | internal GetBucketVersioningRequest() : base(HttpMethodType.GET) {} 9 | 10 | public GetBucketVersioningRequest(string bucketName) : this() 11 | { 12 | Initialize(bucketName); 13 | } 14 | 15 | public string BucketName { get; set; } = null!; 16 | 17 | internal void Initialize(string bucketName) 18 | { 19 | BucketName = bucketName; 20 | } 21 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Buckets/ListBucketsRequest.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Buckets; 4 | 5 | /// This implementation of the GET operation returns a list of all buckets owned by the authenticated sender of the request. 6 | public class ListBucketsRequest() : BaseRequest(HttpMethodType.GET); -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasBypassGovernanceRetention.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasBypassGovernanceRetention 4 | { 5 | /// Specifies whether you want to delete this object even if it has a Governance-type Object Lock in place. You must have sufficient permissions to perform this operation. 6 | bool? BypassGovernanceRetention { get; set; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasCacheControl.cs: -------------------------------------------------------------------------------- 1 | using Genbox.HttpBuilders; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 5 | 6 | [PublicAPI] 7 | public interface IHasCacheControl 8 | { 9 | /// Can be used to specify caching behavior along the request/reply chain. 10 | CacheControlBuilder CacheControl { get; } 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasChecksum.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 4 | 5 | public interface IHasChecksum 6 | { 7 | public ChecksumAlgorithm ChecksumAlgorithm { get; set; } 8 | public ChecksumType ChecksumType { get; set; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasChecksumProperties.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 4 | 5 | public interface IHasChecksumProperties 6 | { 7 | ChecksumAlgorithm ChecksumAlgorithm { get; } 8 | byte[]? Checksum { get; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasContent.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 4 | 5 | [PublicAPI] 6 | public interface IHasContent 7 | { 8 | Stream? Content { get; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasContentMd5.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasContentMd5 4 | { 5 | /// 6 | /// 128-bit MD5 digest of the data. This property can be used as a message integrity check to verify that the data is the same data that was originally sent. Although it is 7 | /// optional, we recommend using the Content-MD5 mechanism as an end-to-end integrity check. 8 | /// 9 | byte[]? ContentMd5 { get; set; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasContentProps.cs: -------------------------------------------------------------------------------- 1 | using Genbox.HttpBuilders; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 5 | 6 | [PublicAPI] 7 | public interface IHasContentProps 8 | { 9 | /// Specifies presentational information for the object. 10 | ContentDispositionBuilder ContentDisposition { get; } 11 | 12 | /// 13 | /// Specifies what content encodings have been applied to the object and thus what decoding mechanisms must be applied to obtain the media-type referenced by the Content-Type 14 | /// header field. 15 | /// 16 | ContentEncodingBuilder ContentEncoding { get; } 17 | 18 | /// A standard MIME type describing the format of the contents. 19 | ContentTypeBuilder ContentType { get; } 20 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasExpectedBucketOwner.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasExpectedBucketOwner 4 | { 5 | /// The account id of the expected bucket owner. If the bucket is owned by a different account, the request will fail with an HTTP 403 (Access Denied) error. 6 | string? ExpectedBucketOwner { get; set; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasExpiresOn.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasExpiresOn 4 | { 5 | /// The date and time at which the object is no longer able to be cached. 6 | DateTimeOffset? ExpiresOn { get; set; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasLegalHold.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasLegalHold 4 | { 5 | /// Specifies whether a legal hold will be applied to this object. 6 | bool? LockLegalHold { get; set; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasLock.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 5 | 6 | [PublicAPI] 7 | public interface IHasLock 8 | { 9 | /// The Object Lock mode, if any, that should be applied to this object. 10 | LockMode LockMode { get; set; } 11 | 12 | /// The date and time when the Object Lock retention period will expire. 13 | DateTimeOffset? LockRetainUntil { get; set; } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasMetadata.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Builders; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 4 | 5 | public interface IHasMetadata 6 | { 7 | /// 8 | /// Header starting with this prefix are user-defined metadata. Each one is stored and returned as a set of key-value pairs. Amazon S3 doesn't validate or interpret 9 | /// user-defined metadata. 10 | /// 11 | MetadataBuilder Metadata { get; } 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasMfa.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Builders; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 4 | 5 | public interface IHasMfa 6 | { 7 | /// If multi-factor approval is activated, you need to supply MFA information. 8 | MfaAuthenticationBuilder Mfa { get; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasPartNumber.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasPartNumber 4 | { 5 | /// 6 | /// Part number of the object part being read. This is a positive integer between 1 and the maximum number of parts supported. Only objects uploaded using the multipart 7 | /// upload API have part numbers. For information about multipart uploads, see Multipart Upload Overview in the Amazon Simple Storage Service Developer Guide. 8 | /// 9 | int? PartNumber { get; set; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasRange.cs: -------------------------------------------------------------------------------- 1 | using Genbox.HttpBuilders; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 5 | 6 | [PublicAPI] 7 | public interface IHasRange 8 | { 9 | /// Downloads the specified range bytes of an object. For more information about the HTTP Range header, go to http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35. 10 | RangeBuilder Range { get; } 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasRequestPayer.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 4 | 5 | public interface IHasRequestPayer 6 | { 7 | /// When true, confirms that the requester knows that she or he will be charged for the request. Bucket owners need not specify this parameter in their requests. 8 | Payer RequestPayer { get; set; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasStorageClass.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 5 | 6 | [PublicAPI] 7 | public interface IHasStorageClass 8 | { 9 | /// Provides storage class information of the object. Amazon S3 returns this header for all objects except for Standard storage class objects. 10 | StorageClass StorageClass { get; set; } 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasTags.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Builders; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 4 | 5 | public interface IHasTags 6 | { 7 | /// 8 | /// Specifies a set of one or more tags to associate with the object. These tags are stored in the tagging subresource that is associated with the object. To specify tags on 9 | /// an object, the requester must have s3:PutObjectTagging included in the list of permitted actions in their IAM policy. 10 | /// 11 | TagBuilder Tags { get; } 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasUploadId.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasUploadId 4 | { 5 | string UploadId { get; set; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasVersionId.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasVersionId 4 | { 5 | /// 6 | /// The version of the object. When you enable versioning, S3 generates a random number for objects added to a bucket. When you put an object in a bucket where versioning has 7 | /// been suspended, is always null. 8 | /// 9 | string? VersionId { get; set; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/Interfaces/IHasWebsiteRedirect.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.Interfaces; 2 | 3 | public interface IHasWebsiteRedirect 4 | { 5 | /// 6 | /// f the bucket is configured as a website, redirects requests for this object to another object in the same bucket or to an external URL. Amazon S3 stores the value of this 7 | /// header in the object metadata. 8 | /// 9 | string? WebsiteRedirectLocation { get; set; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3AndCondition.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 2 | 3 | public class S3AndCondition 4 | { 5 | public string? Prefix { get; set; } 6 | public IList> Tags { get; internal set; } = new List>(); 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3Filter.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 2 | 3 | /// The Filter is used to identify objects that a Lifecycle Rule applies to. A Filter must have exactly one of Prefix, Tag, or conditions specified. 4 | public class S3Filter 5 | { 6 | public string? Prefix { get; set; } 7 | 8 | public KeyValuePair? Tag { get; set; } 9 | 10 | public S3AndCondition? AndConditions { get; set; } 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3InputFormat.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 5 | 6 | [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors | ImplicitUseTargetFlags.WithMembers)] 7 | public abstract class S3InputFormat 8 | { 9 | public CompressionType CompressionType { get; set; } 10 | 11 | internal abstract void Reset(); 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3JsonInputFormat.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 4 | 5 | public class S3JsonInputFormat(JsonType jsonType) : S3InputFormat 6 | { 7 | public JsonType JsonType { get; set; } = jsonType; 8 | 9 | internal override void Reset() 10 | { 11 | JsonType = JsonType.Unknown; 12 | } 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3JsonOutputFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 2 | 3 | public class S3JsonOutputFormat(string recordDelimiter) : S3OutputFormat 4 | { 5 | public string RecordDelimiter { get; set; } = recordDelimiter; 6 | 7 | internal override void Reset() 8 | { 9 | RecordDelimiter = string.Empty; 10 | } 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3NonCurrentVersionTransition.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 4 | 5 | public class S3NonCurrentVersionTransition(int nonCurrentDays, StorageClass storageClass) 6 | { 7 | /// Specifies the number of days an object is noncurrent before Amazon S3 can perform the associated action. 8 | public int NonCurrentDays { get; } = nonCurrentDays; 9 | 10 | /// The class of storage used to store the object. 11 | public StorageClass StorageClass { get; } = storageClass; 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3OutputFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 2 | 3 | public abstract class S3OutputFormat 4 | { 5 | internal abstract void Reset(); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3ParquetInputFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 2 | 3 | public class S3ParquetInputFormat : S3InputFormat 4 | { 5 | internal override void Reset() {} 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3PartInfo.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 5 | 6 | [PublicAPI] 7 | public class S3PartInfo(string eTag, int partNumber, byte[]? checksum = null, ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.Unknown) 8 | { 9 | public string ETag { get; } = eTag; 10 | public int PartNumber { get; } = partNumber; 11 | public byte[]? Checksum { get; } = checksum; 12 | public ChecksumAlgorithm ChecksumAlgorithm { get; } = checksumAlgorithm; 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Requests/S3Types/S3SelectParameters.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Requests.S3Types; 4 | 5 | public class S3SelectParameters(string expression, S3InputFormat? inputFormat, S3OutputFormat outputFormat) 6 | { 7 | public string Expression { get; } = expression; 8 | public ExpressionType ExpressionType { get; set; } 9 | public S3InputFormat? InputFormat { get; } = inputFormat; 10 | public S3OutputFormat OutputFormat { get; } = outputFormat; 11 | 12 | internal void Reset() 13 | { 14 | ExpressionType = ExpressionType.Unknown; 15 | InputFormat?.Reset(); 16 | OutputFormat.Reset(); 17 | } 18 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/BaseResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Response; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses; 4 | 5 | public abstract class BaseResponse : IResponse 6 | { 7 | public int StatusCode { get; set; } 8 | 9 | public IError? Error { get; set; } 10 | 11 | public long ContentLength { get; set; } 12 | 13 | public bool ConnectionClosed { get; set; } 14 | 15 | public DateTimeOffset Date { get; set; } 16 | 17 | public string? Server { get; set; } 18 | 19 | public string? ResponseId { get; set; } 20 | 21 | public string? RequestId { get; set; } 22 | 23 | public bool IsSuccess { get; set; } 24 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/CreateBucketResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class CreateBucketResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/DeleteBucketPolicyResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class DeleteBucketPolicyResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/DeleteBucketResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class DeleteBucketResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/DeleteBucketTaggingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class DeleteBucketTaggingResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/GetBucketAccelerateConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | /// GetBucketAccelerateConfiguration 4 | public class GetBucketAccelerateConfigurationResponse : BaseResponse 5 | { 6 | public bool AccelerateEnabled { get; internal set; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/GetBucketLifecycleConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Requests.S3Types; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 4 | 5 | public class GetBucketLifecycleConfigurationResponse : BaseResponse 6 | { 7 | public IList Rules { get; } = new List(); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/GetBucketLockConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 5 | 6 | public class GetBucketLockConfigurationResponse : BaseResponse, IHasLock 7 | { 8 | public LockMode LockMode { get; internal set; } 9 | public DateTimeOffset? LockRetainUntil { get; internal set; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/GetBucketPolicyResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class GetBucketPolicyResponse : BaseResponse 4 | { 5 | public string Policy { get; internal set; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/GetBucketTaggingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class GetBucketTaggingResponse : BaseResponse 4 | { 5 | public IDictionary Tags { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/GetBucketVersioningResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class GetBucketVersioningResponse : BaseResponse 4 | { 5 | public bool Status { get; internal set; } 6 | public bool MfaDelete { get; internal set; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/HeadBucketResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class HeadBucketResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/ListBucketsResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.S3Types; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 4 | 5 | public class ListBucketsResponse : BaseResponse 6 | { 7 | public ListBucketsResponse() 8 | { 9 | Buckets = new List(); 10 | } 11 | 12 | /// The owner of the buckets inside . 13 | public S3Identity Owner { get; internal set; } 14 | 15 | /// The list of buckets 16 | public IList Buckets { get; } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/PutBucketAccelerateConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | /// PutBucketAccelerateConfiguration 4 | public class PutBucketAccelerateConfigurationResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/PutBucketLifecycleConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | /// PutBucketLifecycleConfigurationResponse 4 | public class PutBucketLifecycleConfigurationResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/PutBucketLockConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 4 | 5 | public class PutBucketLockConfigurationResponse : BaseResponse, IHasRequestCharged 6 | { 7 | public bool RequestCharged { get; internal set; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/PutBucketPolicyResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class PutBucketPolicyResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/PutBucketTaggingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class PutBucketTaggingResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/PutBucketVersioningResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | /// PutBucketVersioningResponse 4 | public class PutBucketVersioningResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Buckets/PutPublicAccessBlockResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Buckets; 2 | 3 | public class PutPublicAccessBlockResponse : BaseResponse; -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/BucketAlreadyExistsError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class BucketAlreadyExistsError : GenericError 8 | { 9 | internal BucketAlreadyExistsError(IDictionary lookup) : base(lookup) 10 | { 11 | BucketName = lookup.GetOptionalValue("BucketName"); 12 | } 13 | 14 | public string? BucketName { get; } 15 | 16 | public override string GetErrorDetails() => "BucketName: " + BucketName; 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/BucketNotEmptyError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class BucketNotEmptyError : GenericError 8 | { 9 | internal BucketNotEmptyError(IDictionary lookup) : base(lookup) 10 | { 11 | BucketName = lookup.GetOptionalValue("BucketName"); 12 | } 13 | 14 | public string? BucketName { get; } 15 | 16 | public override string GetErrorDetails() => $"BucketName: {BucketName}"; 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/HeadersNotSignedError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class HeadersNotSignedError : GenericError 8 | { 9 | internal HeadersNotSignedError(IDictionary lookup) : base(lookup) 10 | { 11 | HeadersNotSigned = lookup.GetOptionalValue("HeadersNotSigned"); 12 | } 13 | 14 | public string? HeadersNotSigned { get; } 15 | 16 | public override string GetErrorDetails() => "Headers not signed: " + HeadersNotSigned; 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/InvalidArgumentError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class InvalidArgumentError : GenericError 8 | { 9 | internal InvalidArgumentError(IDictionary lookup) : base(lookup) 10 | { 11 | ArgumentName = lookup.GetOptionalValue("ArgumentName"); 12 | ArgumentValue = lookup.GetOptionalValue("ArgumentValue"); 13 | } 14 | 15 | public string? ArgumentName { get; } 16 | public string? ArgumentValue { get; } 17 | 18 | public override string GetErrorDetails() => $"Argument: {ArgumentName} - Value: {ArgumentValue}"; 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/InvalidBucketNameError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class InvalidBucketNameError : GenericError 8 | { 9 | internal InvalidBucketNameError(IDictionary lookup) : base(lookup) 10 | { 11 | BucketName = lookup.GetOptionalValue("BucketName"); 12 | } 13 | 14 | public string? BucketName { get; } 15 | 16 | public override string GetErrorDetails() => "BucketName: " + BucketName; 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/MethodNotAllowedError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class MethodNotAllowedError : GenericError 8 | { 9 | internal MethodNotAllowedError(IDictionary lookup) : base(lookup) 10 | { 11 | Method = lookup.GetOptionalValue("Method"); 12 | ResourceType = lookup.GetOptionalValue("ResourceType"); 13 | RequestId = lookup.GetOptionalValue("RequestId"); 14 | HostId = lookup.GetOptionalValue("HostId"); 15 | } 16 | 17 | public string? Method { get; } 18 | public string? ResourceType { get; } 19 | public string? RequestId { get; } 20 | public string? HostId { get; } 21 | 22 | public override string GetErrorDetails() => $"Method: {Method} ResourceType: {ResourceType}"; 23 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/NoSuchBucketError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class NoSuchBucketError : GenericError 8 | { 9 | internal NoSuchBucketError(IDictionary lookup) : base(lookup) 10 | { 11 | BucketName = lookup.GetOptionalValue("BucketName"); 12 | } 13 | 14 | public string? BucketName { get; } 15 | 16 | public override string GetErrorDetails() => $"BucketName: {BucketName}"; 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Errors/PreconditionFailedError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Internals.Extensions; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Errors; 5 | 6 | [PublicAPI] 7 | public class PreconditionFailedError : GenericError 8 | { 9 | internal PreconditionFailedError(IDictionary lookup) : base(lookup) 10 | { 11 | //The condition field is optional since only Amazon S3 returns it 12 | Condition = lookup.GetOptionalValue("Condition"); 13 | } 14 | 15 | public string? Condition { get; } 16 | 17 | public override string GetErrorDetails() => "Condition: " + Condition; 18 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasAbort.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasAbort 4 | { 5 | /// 6 | /// If the bucket has a lifecycle rule configured with an action to abort incomplete multipart uploads and the prefix in the lifecycle rule matches the object name in the 7 | /// request, the response includes this header. The header indicates when the initiated multipart upload becomes eligible for an abort operation. 8 | /// 9 | DateTimeOffset? AbortsOn { get; } 10 | 11 | /// 12 | /// This header is returned along with the x-amz-abort-date header. It identifies the applicable lifecycle configuration rule that defines the action to abort incomplete 13 | /// multipart uploads. 14 | /// 15 | string? AbortRuleId { get; } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasCache.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 4 | 5 | [PublicAPI] 6 | public interface IHasCache : IHasETag 7 | { 8 | /// Can be used to specify caching behavior along the request/reply chain. 9 | string? CacheControl { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasContent.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 4 | 5 | [PublicAPI] 6 | public interface IHasContent : IDisposable 7 | { 8 | Stream Content { get; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasDeleteMarker.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasDeleteMarker 4 | { 5 | /// 6 | /// Specifies whether the versioned object that was permanently deleted was (true) or was not (false) a delete marker. In a simple DELETE, this header indicates whether 7 | /// (true) or not (false) a delete marker was created. 8 | /// 9 | bool IsDeleteMarker { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasETag.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasETag 4 | { 5 | /// The entity tag is a hash of the object. The ETag reflects changes only to the contents of an object, not its metadata. 6 | string? ETag { get; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasExpiration.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasExpiration 4 | { 5 | /// The datetime the object expires 6 | DateTimeOffset? LifeCycleExpiresOn { get; } 7 | 8 | /// The rule id used for expiration 9 | string? LifeCycleRuleId { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasExpiresOn.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasExpiresOn 4 | { 5 | /// A date time for when the response has expired and should no longer be cached. 6 | DateTimeOffset? ExpiresOn { get; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasLastModified.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasLastModified 4 | { 5 | DateTimeOffset? LastModified { get; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasLegalHold.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasLegalHold 4 | { 5 | /// 6 | /// Specifies whether a legal hold is in effect for this object. This header is only returned if the requester has the s3:GetObjectLegalHold permission. This header is not 7 | /// returned if the specified version of this object has never had a legal hold applied. 8 | /// 9 | bool LockLegalHold { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasLock.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 5 | 6 | [PublicAPI] 7 | public interface IHasLock 8 | { 9 | /// The Object Lock mode, if any, that's in effect for this object. This header is only returned if the requester has the s3:GetObjectRetention permission. 10 | LockMode LockMode { get; } 11 | 12 | /// The date and time when the Object Lock retention period expires. This header is only returned if the requester has the s3:GetObjectRetention permission. 13 | DateTimeOffset? LockRetainUntil { get; } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasMetadata.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 4 | 5 | [PublicAPI] 6 | public interface IHasMetadata 7 | { 8 | /// 9 | /// Header starting with this prefix are user-defined metadata. Each one is stored and returned as a set of key-value pairs. Amazon S3 doesn't validate or interpret 10 | /// user-defined metadata. 11 | /// 12 | IDictionary? Metadata { get; } 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasRequestCharged.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasRequestCharged 4 | { 5 | /// If present, indicates that the requester was successfully charged for the request. 6 | bool RequestCharged { get; } 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasRestoration.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 4 | 5 | [PublicAPI] 6 | public interface IHasRestoration 7 | { 8 | /// If the object was restored from Amazon Glacier, this value indicates when the object will expire. 9 | DateTimeOffset? RestoreExpiresOn { get; } 10 | 11 | /// If true, indicates that the object is currently being restored from Amazon Glacier. 12 | bool RestoreInProgress { get; } 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasSse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 5 | 6 | [PublicAPI] 7 | public interface IHasSse 8 | { 9 | /// 10 | /// If you specified server-side encryption either with an AWS KMS-managed or Amazon S3-managed encryption key in your PUT request, the response includes this header. It 11 | /// confirms the encryption algorithm that Amazon S3 used to encrypt the object. 12 | /// 13 | SseAlgorithm SseAlgorithm { get; } 14 | 15 | /// If present, specifies the ID of the AWS Key Management Service (KMS) customer master key (CMK) that was used for the object. 16 | string? SseKmsKeyId { get; } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasSseContext.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasSseContext 4 | { 5 | /// 6 | /// If present, specifies the AWS KMS Encryption Context to use for object encryption. The value of this header is a base64-encoded UTF-8 string holding JSON with the 7 | /// encryption context key-value pairs. 8 | /// 9 | string? SseContext { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasSseCustomerKey.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 4 | 5 | public interface IHasSseCustomerKey 6 | { 7 | /// If server-side encryption with a customer-provided encryption key was requested, the response will include this header confirming the encryption algorithm used. 8 | SseCustomerAlgorithm SseCustomerAlgorithm { get; } 9 | 10 | /// 11 | /// If server-side encryption using customer-provided encryption keys was requested, the response returns this header to verify the roundtrip message integrity of the 12 | /// customer-provided encryption key. 13 | /// 14 | byte[]? SseCustomerKeyMd5 { get; } 15 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasStorageClass.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 4 | 5 | public interface IHasStorageClass 6 | { 7 | StorageClass StorageClass { get; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasUploadId.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasUploadId 4 | { 5 | string UploadId { get; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasVersionId.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasVersionId 4 | { 5 | string? VersionId { get; } 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Interfaces/IHasWebsiteRedirect.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | public interface IHasWebsiteRedirect 4 | { 5 | /// 6 | /// f the bucket is configured as a website, redirects requests for this object to another object in the same bucket or to an external URL. Amazon S3 stores the value of this 7 | /// header in the object metadata. 8 | /// 9 | string? WebsiteRedirectLocation { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Multipart/AbortMultipartUploadResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Multipart; 4 | 5 | public class AbortMultipartUploadResponse : BaseResponse, IHasRequestCharged 6 | { 7 | public bool RequestCharged { get; internal set; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/DeleteObjectResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 4 | 5 | public class DeleteObjectResponse : BaseResponse, IHasRequestCharged, IHasVersionId, IHasDeleteMarker 6 | { 7 | public bool IsDeleteMarker { get; internal set; } 8 | public bool RequestCharged { get; internal set; } 9 | public string? VersionId { get; internal set; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/DeleteObjectsResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | using Genbox.SimpleS3.Core.Network.Responses.S3Types; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 5 | 6 | public class DeleteObjectsResponse : BaseResponse, IHasRequestCharged 7 | { 8 | public IList Deleted { get; } = new List(); 9 | public IList Errors { get; } = new List(); 10 | public bool RequestCharged { get; internal set; } 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/GetObjectAclResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | using Genbox.SimpleS3.Core.Network.Responses.S3Types; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 5 | 6 | public class GetObjectAclResponse : BaseResponse, IHasRequestCharged 7 | { 8 | public GetObjectAclResponse() 9 | { 10 | Grants = new List(); 11 | } 12 | 13 | public S3Identity Owner { get; internal set; } 14 | public IList Grants { get; } 15 | public bool RequestCharged { get; internal set; } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/GetObjectLegalHoldResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 4 | 5 | public class GetObjectLegalHoldResponse : BaseResponse, IHasRequestCharged 6 | { 7 | public bool LegalHold { get; internal set; } 8 | public bool RequestCharged { get; internal set; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/GetObjectResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 4 | 5 | public class GetObjectResponse : HeadObjectResponse, IHasContent, IHasRequestCharged 6 | { 7 | public Stream Content { get; internal set; } = Stream.Null; 8 | 9 | public void Dispose() 10 | { 11 | Dispose(true); 12 | GC.SuppressFinalize(this); 13 | } 14 | 15 | public bool RequestCharged { get; internal set; } 16 | 17 | protected virtual void Dispose(bool disposing) 18 | { 19 | if (disposing) 20 | Content.Dispose(); 21 | } 22 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/PutObjectAclResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 4 | 5 | public class PutObjectAclResponse : BaseResponse, IHasRequestCharged 6 | { 7 | public bool RequestCharged { get; internal set; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/PutObjectLegalHoldResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 4 | 5 | public class PutObjectLegalHoldResponse : BaseResponse, IHasRequestCharged 6 | { 7 | public bool RequestCharged { get; internal set; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/Objects/RestoreObjectResponse.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.Objects; 4 | 5 | public class RestoreObjectResponse : BaseResponse, IHasRequestCharged 6 | { 7 | public string? RestoreOutputPath { get; internal set; } 8 | public bool RequestCharged { get; internal set; } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/S3Types/S3Bucket.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Common.Marshal; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.S3Types; 5 | 6 | [PublicAPI] 7 | public class S3Bucket(string bucketName, DateTimeOffset createdOn) : IHasBucketName 8 | { 9 | /// The date the bucket was created 10 | public DateTimeOffset CreatedOn { get; } = createdOn; 11 | 12 | /// Name of the bucket 13 | public string BucketName { get; } = bucketName; 14 | 15 | public override string ToString() => BucketName; 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/S3Types/S3DeleteError.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Common.Marshal; 3 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 4 | 5 | namespace Genbox.SimpleS3.Core.Network.Responses.S3Types; 6 | 7 | public class S3DeleteError(string objectKey, ErrorCode code, string message, string? versionId) : IHasVersionId, IHasObjectKey 8 | { 9 | public ErrorCode Code { get; } = code; 10 | public string Message { get; } = message; 11 | public string ObjectKey { get; } = objectKey; 12 | public string? VersionId { get; } = versionId; 13 | public override string ToString() => $"Error on {ObjectKey}: {Message}"; 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/S3Types/S3DeleteMarker.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Common.Marshal; 2 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Responses.S3Types; 5 | 6 | public class S3DeleteMarker(bool isLatest, string objectKey, DateTimeOffset lastModified, S3Identity owner, string versionId) : IHasObjectKey, IHasVersionId 7 | { 8 | public bool IsLatest { get; } = isLatest; 9 | public DateTimeOffset LastModified { get; } = lastModified; 10 | public S3Identity Owner { get; } = owner; 11 | public string ObjectKey { get; internal set; } = objectKey; 12 | public string VersionId { get; } = versionId; 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/S3Types/S3Grant.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.S3Types; 4 | 5 | public class S3Grant(S3Grantee grantee, S3Permission permission) 6 | { 7 | public S3Grantee Grantee { get; } = grantee; 8 | public S3Permission Permission { get; } = permission; 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/S3Types/S3Grantee.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Enums; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.S3Types; 4 | 5 | public class S3Grantee(GrantType type, string? id, string? displayName, string? uri) 6 | { 7 | public GrantType Type { get; } = type; 8 | public string? Id { get; } = id; 9 | public string? DisplayName { get; } = displayName; 10 | public string? Uri { get; } = uri; 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/S3Types/S3Identity.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.S3Types; 2 | 3 | public class S3Identity(string id, string? name) 4 | { 5 | /// The display name of the identity 6 | public string? Name { get; } = name; 7 | 8 | /// The unique identifier of the identity 9 | public string Id { get; } = id; 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Network/Responses/S3Types/S3Part.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Network.Responses.Interfaces; 2 | 3 | namespace Genbox.SimpleS3.Core.Network.Responses.S3Types; 4 | 5 | public class S3Part(int partNumber, DateTimeOffset lastModified, long size, string? eTag) : IHasETag 6 | { 7 | public int PartNumber { get; } = partNumber; 8 | public DateTimeOffset LastModified { get; } = lastModified; 9 | public long Size { get; } = size; 10 | public string? ETag { get; } = eTag; 11 | 12 | public override string ToString() => $"Part: {PartNumber}"; 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Genbox.ProviderTests")] 4 | [assembly: InternalsVisibleTo("Genbox.SimpleS3.Core.Tests")] 5 | [assembly: InternalsVisibleTo("Genbox.SimpleS3.Core.Benchmarks")] 6 | [assembly: InternalsVisibleTo("Genbox.SimpleS3.Extensions.AmazonS3.Tests")] -------------------------------------------------------------------------------- /Src/SimpleS3.Core/SimpleS3.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Src/SimpleS3.Examples.Advanced/ClientSetup.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.AmazonS3; 2 | using Genbox.SimpleS3.Extensions.AmazonS3; 3 | 4 | namespace Genbox.SimpleS3.Examples.Advanced; 5 | 6 | public static class ClientSetup 7 | { 8 | /// Shows how to use a simple client to work with S3 9 | public static void Example() 10 | { 11 | //Not much to it. Give it credentials, a region and you are ready to use S3. 12 | using AmazonS3Client client = new AmazonS3Client("YourKeyId", "YourAccessKey", AmazonS3Region.EuNorth1); 13 | } 14 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Examples.Advanced/SetupDependencyInjection.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.AmazonS3.Extensions; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Genbox.SimpleS3.Examples.Advanced; 6 | 7 | public static class SetupDependencyInjection 8 | { 9 | /// Shows how to use dependency injection to setup a client to AmazonS3 10 | public static void Example() 11 | { 12 | //Create the dependency injection container 13 | ServiceCollection services = new ServiceCollection(); 14 | 15 | //Add all the AmazonS3 services 16 | services.AddAmazonS3(); 17 | 18 | //Build the service provider 19 | using ServiceProvider serviceProvider = services.BuildServiceProvider(); 20 | 21 | //Now we can get the client. 22 | ISimpleClient client = serviceProvider.GetRequiredService(); 23 | } 24 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Examples.Advanced/SimpleS3.Examples.Advanced.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Library 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Src/SimpleS3.Examples/SimpleS3.Examples.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/README.md: -------------------------------------------------------------------------------- 1 | Files in this directory comes from the official Amazon test suite. I've removed the tests that are incompatible with S3 and some tests that does not make sense from a clients 2 | perspective. -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-casing/get-query-casing.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | param1=value1&PARAM2=VALUE2 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-casing/get-query-casing.req.disabled: -------------------------------------------------------------------------------- 1 | GET /?PARAM2=VALUE2¶m1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-casing/get-query-casing.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 49434b13bbd7105e29de1fa7d46391cdce739cb2533d60c8f25f76819526af4b -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-order/get-query-order.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | Param1=value1&Param2=value2 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-order/get-query-order.req: -------------------------------------------------------------------------------- 1 | GET /?Param2=value2&Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-order/get-query-order.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 816cd5b414d056048ba4f7c5386d6e0533120fb1fcfa93762cf0fc39e2cf19e0 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-reserved/get-query-reserved.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | -._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-reserved/get-query-reserved.req: -------------------------------------------------------------------------------- 1 | GET /?-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-reserved/get-query-reserved.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | c30d4703d9f799439be92736156d47ccfb2d879ddf56f5befa6d1d6aab979177 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-utf8/get-query-utf8.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | %E1%88%B4=bar 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-utf8/get-query-utf8.req: -------------------------------------------------------------------------------- 1 | GET /?ሴ=bar HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query-utf8/get-query-utf8.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | eb30c5bed55734080471a834cc727ae56beb50e5f39d1bff6d0d38cb192a7073 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query/get-query.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | Param1=value1 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query/get-query.req: -------------------------------------------------------------------------------- 1 | GET /?Param1=value1 HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-query/get-query.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 1e24db194ed7d0eec2de28d7369675a243488e08526e8c1c73571282f7c517ab -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-reserved/get-reserved.creq: -------------------------------------------------------------------------------- 1 | GET 2 | /-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-reserved/get-reserved.req: -------------------------------------------------------------------------------- 1 | GET /-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-reserved/get-reserved.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 6a968768eefaa713e2a6b16b589a8ea192661f098f37349f4e2c0082757446f9 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-utf8/get-utf8.creq: -------------------------------------------------------------------------------- 1 | GET 2 | /%E1%88%B4 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-utf8/get-utf8.req: -------------------------------------------------------------------------------- 1 | GET /ሴ HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get-utf8/get-utf8.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | 2a0a97d02205e45ce2e994789806b19270cfbbb0921b278ccf58f5249ac42102 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get/get.creq: -------------------------------------------------------------------------------- 1 | GET 2 | / 3 | 4 | host:example.amazonaws.com 5 | x-amz-date:20150830T123600Z 6 | 7 | host;x-amz-date 8 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get/get.req: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host:example.amazonaws.com 3 | X-Amz-Date:20150830T123600Z -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/Resources/get/get.sts: -------------------------------------------------------------------------------- 1 | AWS4-HMAC-SHA256 2 | 20150830T123600Z 3 | 20150830/us-east-1/service/aws4_request 4 | bb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63 -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3.Tests/SimpleS3.Extensions.AmazonS3.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Genbox.SimpleS3.Extensions.AmazonS3.Tests")] -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.AmazonS3/SimpleS3.Extensions.AmazonS3.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.BackBlazeB2.Tests/SimpleS3.Extensions.BackBlazeB2.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.BackBlazeB2/BackBlazeB2Region.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.BackBlazeB2; 2 | 3 | public enum BackBlazeB2Region 4 | { 5 | Unknown = 0, 6 | UsWest000, 7 | UsWest001, 8 | UsWest002, 9 | EuCentral003, 10 | UsWest004, 11 | UsEast005 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.BackBlazeB2/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Genbox.SimpleS3.Extensions.BackBlazeB2.Tests")] -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.BackBlazeB2/SimpleS3.Extensions.BackBlazeB2.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.GenericS3.Tests/SimpleS3.Extensions.GenericS3.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.GenericS3/GenericS3Config.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.Core.Abstracts.Authentication; 3 | using Genbox.SimpleS3.Core.Common.Authentication; 4 | using JetBrains.Annotations; 5 | 6 | namespace Genbox.SimpleS3.Extensions.GenericS3; 7 | 8 | [PublicAPI] 9 | public class GenericS3Config() : SimpleS3Config("GenericS3", string.Empty) //Needed for config binding 10 | { 11 | public GenericS3Config(string endpoint) : this() 12 | { 13 | Endpoint = endpoint; 14 | } 15 | 16 | public GenericS3Config(IAccessKey? credentials, string endpoint, string regionCode) : this(endpoint) 17 | { 18 | Credentials = credentials; 19 | RegionCode = regionCode; 20 | } 21 | 22 | public GenericS3Config(string keyId, string secretKey, string endpoint, string regionCode) : this(new StringAccessKey(keyId, secretKey), endpoint, regionCode) {} 23 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.GenericS3/GenericS3RegionData.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Region; 2 | 3 | namespace Genbox.SimpleS3.Extensions.GenericS3; 4 | 5 | public class GenericS3RegionData : IRegionData 6 | { 7 | public static GenericS3RegionData Instance { get; } = new GenericS3RegionData(); 8 | 9 | public IEnumerable GetRegions() 10 | { 11 | yield break; 12 | } 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.GenericS3/SimpleS3.Extensions.GenericS3.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.GoogleCloudStorage.Tests/SimpleS3.Extensions.GoogleCloudStorage.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.GoogleCloudStorage/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Genbox.SimpleS3.Extensions.GoogleCloudStorage.Tests")] -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.GoogleCloudStorage/SimpleS3.Extensions.GoogleCloudStorage.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClient/HttpBuilderActions.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.HttpClient; 2 | 3 | public class HttpBuilderActions 4 | { 5 | public IList> HttpClientActions { get; } = new List>(); 6 | public IList> HttpHandlerActions { get; } = new List>(); 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClient/HttpClientConfig.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Common; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Extensions.HttpClient; 5 | 6 | [PublicAPI] 7 | public class HttpClientConfig 8 | { 9 | /// Set to 'true' if you want the proxy that is defined to be used. Otherwise set it to 'false'. Defaults to 'false'. 10 | public bool UseProxy { get; set; } 11 | 12 | /// Use this to set a proxy to which all requests should be sent through. 13 | public string? Proxy { get; set; } 14 | 15 | public HttpVersion HttpVersion { get; set; } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClient/IHttpClientBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Genbox.SimpleS3.Extensions.HttpClient; 4 | 5 | public interface IHttpClientBuilder 6 | { 7 | IServiceCollection Services { get; } 8 | 9 | string Name { get; } 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClient/Internal/CustomHttpClientBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Genbox.SimpleS3.Extensions.HttpClient.Internal; 5 | 6 | internal sealed class CustomHttpClientBuilder(IServiceCollection services, string? name = null) : ServiceBuilderBase(services, name), IHttpClientBuilder; -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClient/README.md: -------------------------------------------------------------------------------- 1 | # SimpleS3.Extensions.HttpClient 2 | 3 | This extension is a network driver that provides basic HTTP communication through the .NET System.Net.Http.HttpClient class. A single HttpClient instance is used for all 4 | connections. It supports web proxies. 5 | 6 | To use it, add a reference to [Genbox.SimpleS3.Core](https://www.nuget.org/packages/Genbox.SimpleS3.Core) 7 | and [Genbox.SimpleS3.Extensions.HttpClient](https://www.nuget.org/packages/Genbox.SimpleS3.Extensions.HttpClient). 8 | 9 | ### Using Microsoft.Extensions.DependencyInjection 10 | 11 | If you are using [Microsoft's dependency injection](https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection/) (recommended), then you simply add the driver like 12 | this: 13 | 14 | ```csharp 15 | ServiceCollection services = new ServiceCollection(); 16 | ICoreBuilder coreBuilder = SimpleS3CoreServices.AddSimpleS3Core(services); 17 | coreBuilder.UseHttpClient(); 18 | ``` -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClient/SimpleS3.Extensions.HttpClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory.Polly/Internal/PollyHttpMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Polly; 2 | 3 | namespace Genbox.SimpleS3.Extensions.HttpClientFactory.Polly.Internal; 4 | 5 | internal sealed class PollyHttpMessageHandler(IAsyncPolicy policy) : DelegatingHandler 6 | { 7 | private readonly Context _context = new Context(); 8 | private readonly IAsyncPolicy _policy = policy ?? throw new ArgumentNullException(nameof(policy)); 9 | 10 | protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 11 | { 12 | return await _policy.ExecuteAsync((_, ct) => SendCoreAsync(request, ct), _context, cancellationToken).ConfigureAwait(false); 13 | } 14 | 15 | private Task SendCoreAsync(HttpRequestMessage request, CancellationToken cancellationToken) => base.SendAsync(request, cancellationToken); 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory.Polly/PollyConfig.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Extensions.HttpClientFactory.Polly; 4 | 5 | [PublicAPI] 6 | public class PollyConfig 7 | { 8 | //Default policy: 9 | //- Retries: 3 10 | //-Timeout: 2^attempt seconds (2, 4, 8 seconds) + 0 to 1000 ms jitter 11 | 12 | public int Retries { get; set; } = 3; 13 | 14 | public RetryMode RetryMode { get; set; } = RetryMode.ExponentialBackoffJitter; 15 | public TimeSpan MaxRandomDelay { get; set; } = TimeSpan.FromMilliseconds(1000); 16 | public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(10); 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory.Polly/Retry/RetryableBufferingStreamWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using Genbox.SimpleS3.Core.Abstracts.Request; 3 | using Genbox.SimpleS3.Core.Abstracts.Wrappers; 4 | 5 | namespace Genbox.SimpleS3.Extensions.HttpClientFactory.Polly.Retry; 6 | 7 | internal sealed class RetryableBufferingStreamWrapper : IRequestStreamWrapper 8 | { 9 | public bool IsSupported(IRequest request) => true; 10 | 11 | [SuppressMessage("IDisposableAnalyzers.Correctness", "IDISP015:Member should not return created and cached instance")] 12 | public Stream Wrap(Stream input, IRequest request) => input.CanSeek ? input : new RetryableBufferingStream(input); 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory.Polly/RetryMode.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.HttpClientFactory.Polly; 2 | 3 | public enum RetryMode 4 | { 5 | NoDelay = 0, 6 | LinearDelay, 7 | LinearDelayJitter, 8 | ExponentialBackoff, 9 | ExponentialBackoffJitter 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory.Polly/SimpleS3.Extensions.HttpClientFactory.Polly.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory/HttpBuilderActions.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.HttpClientFactory; 2 | 3 | public class HttpBuilderActions 4 | { 5 | public IList> HttpClientActions { get; } = new List>(); 6 | public IList> HttpHandlerActions { get; } = new List>(); 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory/HttpClientFactoryConfig.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Common; 2 | using JetBrains.Annotations; 3 | 4 | namespace Genbox.SimpleS3.Extensions.HttpClientFactory; 5 | 6 | [PublicAPI] 7 | public class HttpClientFactoryConfig 8 | { 9 | /// Set to 'true' if you want the proxy that is defined to be used. Otherwise set it to 'false'. Defaults to 'false'. 10 | public bool UseProxy { get; set; } 11 | 12 | /// Use this to set a proxy to which all requests should be sent through. 13 | public string? Proxy { get; set; } 14 | 15 | /// Set the HTTP version that the driver should use. 16 | public HttpVersion HttpVersion { get; set; } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory/Internal/CustomHttpClientFactoryBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Genbox.SimpleS3.Extensions.HttpClientFactory.Internal; 5 | 6 | internal sealed class CustomHttpClientFactoryBuilder(IServiceCollection services, string? name = null) : ServiceBuilderBase(services, name), IHttpClientBuilder; -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.HttpClientFactory/SimpleS3.Extensions.HttpClientFactory.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Abstracts/IProfile.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 4 | 5 | [PublicAPI] 6 | public interface IProfile 7 | { 8 | string Name { get; set; } 9 | string KeyId { get; set; } 10 | byte[] AccessKey { get; set; } 11 | string RegionCode { get; set; } 12 | string Location { get; set; } 13 | DateTimeOffset CreatedOn { get; set; } 14 | IDictionary? Tags { get; set; } 15 | string? GetTag(string key); 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Abstracts/IProfileManager.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 2 | 3 | public interface IProfileManager 4 | { 5 | IProfile? GetProfile(string name); 6 | string SaveProfile(IProfile profile); 7 | IProfile CreateProfile(string name, string keyId, byte[] accessKey, string region, bool persist = true); 8 | IEnumerable List(); 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Abstracts/IProfileManagerBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 4 | 5 | public interface IProfileManagerBuilder 6 | { 7 | IServiceCollection Services { get; } 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Abstracts/IProfileSerializer.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 2 | 3 | public interface IProfileSerializer 4 | { 5 | byte[] Serialize(T profile) where T : IProfile; 6 | T Deserialize(byte[] data) where T : IProfile; 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Abstracts/IProfileSetup.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 2 | 3 | public interface IProfileSetup 4 | { 5 | IProfile SetupProfile(string profileName, bool persist = true); 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Abstracts/IStorage.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 2 | 3 | public interface IStorage 4 | { 5 | byte[]? Get(string name); 6 | string Put(string name, byte[] data); 7 | IEnumerable List(); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/DiskStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Genbox.SimpleS3.Extensions.ProfileManager; 4 | 5 | public class DiskStorageOptions 6 | { 7 | public static string DefaultLocation => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SimpleS3", "Profiles") : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".SimpleS3", "Profiles"); 8 | 9 | public string ProfileLocation { get; set; } = DefaultLocation; 10 | 11 | public bool OverwriteExisting { get; set; } 12 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Extensions/ProfileAccessKey.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | using Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 3 | 4 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Extensions; 5 | 6 | public class ProfileAccessKey(IProfile profile) : IAccessKey 7 | { 8 | public string KeyId { get; } = profile.KeyId; 9 | public byte[] SecretKey { get; } = profile.AccessKey; 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Extensions/ProfileManagerExtensions.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 2 | 3 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Extensions; 4 | 5 | public static class ProfileManagerExtensions 6 | { 7 | public static IProfile? GetDefaultProfile(this IProfileManager profileManager) => profileManager.GetProfile(ProfileManager.DefaultProfile); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Extensions/ProfileSetupExtensions.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 2 | 3 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Extensions; 4 | 5 | public static class ProfileSetupExtensions 6 | { 7 | public static IProfile SetupDefaultProfile(this IProfileSetup setup, bool persist = true) => setup.SetupProfile(ProfileManager.DefaultProfile, persist); 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Internal/DataProtection/DataProtectionKeyProtector.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Authentication; 2 | using Microsoft.AspNetCore.DataProtection; 3 | 4 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Internal.DataProtection; 5 | 6 | internal class DataProtectionKeyProtector(IDataProtectionProvider provider) : IAccessKeyProtector 7 | { 8 | private readonly IDataProtector _protector = provider.CreateProtector(nameof(DataProtectionKeyProtector)); 9 | 10 | public byte[] ProtectKey(byte[] key) => _protector.Protect(key); 11 | 12 | public byte[] UnprotectKey(byte[] key) => _protector.Unprotect(key); 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/Internal/ProfileManagerBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Extensions.ProfileManager.Abstracts; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Genbox.SimpleS3.Extensions.ProfileManager.Internal; 5 | 6 | internal class ProfileManagerBuilder(IServiceCollection services) : IProfileManagerBuilder 7 | { 8 | public IServiceCollection Services { get; } = services; 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/ProfileManagerOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Extensions.ProfileManager; 2 | 3 | public class ProfileManagerOptions 4 | { 5 | /// Controls whether the ProfileManager should clear the input key when creating profiles or not. Defaults to true. 6 | public bool ClearInputKey { get; set; } = true; 7 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.ProfileManager/SimpleS3.Extensions.ProfileManager.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.Wasabi.Tests/SimpleS3.Extensions.Wasabi.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.Wasabi/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Genbox.SimpleS3.Extensions.Wasabi.Tests")] -------------------------------------------------------------------------------- /Src/SimpleS3.Extensions.Wasabi/SimpleS3.Extensions.Wasabi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.GenericS3.Tests/SimpleS3.GenericS3.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/SimpleS3.GenericS3.Tests/StaticCreatorTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Common.Authentication; 2 | using Genbox.SimpleS3.Core.TestBase.Code; 3 | using Genbox.SimpleS3.Extensions.GenericS3; 4 | 5 | namespace Genbox.SimpleS3.GenericS3.Tests; 6 | 7 | public class StaticCreatorTests 8 | { 9 | [Fact] 10 | public async Task StaticClient() 11 | { 12 | NullNetworkDriver driver = new NullNetworkDriver(); 13 | 14 | GenericS3Config config = new GenericS3Config(new StringAccessKey("ExampleKeyId00000000", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"), "https://myendpoint.com", "us-east-1"); 15 | using GenericS3Client client = new GenericS3Client(config, driver); 16 | 17 | await client.GetObjectAsync("testbucket", "GetObjectAsync"); 18 | Assert.Equal("https://myendpoint.com/GetObjectAsync", driver.LastUrl); 19 | } 20 | } -------------------------------------------------------------------------------- /Src/SimpleS3.GenericS3/SimpleS3.GenericS3.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Src/SimpleS3.GoogleCloudStorage.Tests/SimpleS3.GoogleCloudStorage.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/SimpleS3.GoogleCloudStorage.Tests/StaticCreatorTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.TestBase.Code; 2 | using Genbox.SimpleS3.Extensions.GoogleCloudStorage; 3 | 4 | namespace Genbox.SimpleS3.GoogleCloudStorage.Tests; 5 | 6 | public class StaticCreatorTests 7 | { 8 | [Fact] 9 | public async Task StaticClient() 10 | { 11 | NullNetworkDriver driver = new NullNetworkDriver(); 12 | 13 | GoogleCloudStorageConfig config = new GoogleCloudStorageConfig("GOOGTS7C7FUP3AIRVJTE2BCDKINBTES3HC2GY5CBFJDCQ2SYHV6A6XXVTJFSA", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ", GoogleCloudStorageRegion.EuropeWest1); 14 | using GoogleCloudStorageClient client = new GoogleCloudStorageClient(config, driver); 15 | 16 | await client.GetObjectAsync("testbucket", "GetObjectAsync"); 17 | Assert.Equal("https://testbucket.storage.googleapis.com/GetObjectAsync", driver.LastUrl); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.GoogleCloudStorage/SimpleS3.GoogleCloudStorage.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/SimpleS3.ProviderBase/Abstracts/IClientBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Genbox.SimpleS3.ProviderBase.Abstracts; 5 | 6 | public interface IClientBuilder 7 | { 8 | IServiceCollection Services { get; } 9 | 10 | IHttpClientBuilder HttpBuilder { get; } 11 | 12 | ICoreBuilder CoreBuilder { get; } 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.ProviderBase/ClientBuilder.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts; 2 | using Genbox.SimpleS3.ProviderBase.Abstracts; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Genbox.SimpleS3.ProviderBase; 6 | 7 | public class ClientBuilder(IServiceCollection services, IHttpClientBuilder httpBuilder, ICoreBuilder coreBuilder, string? name = null) : ServiceBuilderBase(services, name), IClientBuilder 8 | { 9 | public IHttpClientBuilder HttpBuilder { get; } = httpBuilder; 10 | public ICoreBuilder CoreBuilder { get; } = coreBuilder; 11 | } -------------------------------------------------------------------------------- /Src/SimpleS3.ProviderBase/ErrorMessages.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.ProviderBase; 2 | 3 | public static class ErrorMessages 4 | { 5 | public const string ProviderNotSupported = "The provider does not support this function"; 6 | } -------------------------------------------------------------------------------- /Src/SimpleS3.ProviderBase/NetworkConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Genbox.SimpleS3.Extensions.HttpClientFactory.Polly; 3 | 4 | namespace Genbox.SimpleS3.ProviderBase; 5 | 6 | public class NetworkConfig 7 | { 8 | public IWebProxy? Proxy { get; set; } 9 | public int Retries { get; set; } = 3; 10 | public RetryMode RetryMode { get; set; } = RetryMode.ExponentialBackoffJitter; 11 | public TimeSpan MaxRandomDelay { get; set; } = TimeSpan.FromMilliseconds(1000); 12 | public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(10); 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.ProviderBase/SimpleS3.ProviderBase.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/Api.txt: -------------------------------------------------------------------------------- 1 | GetBucketAccelerateConfiguration,bucket 2 | GetObject,object -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/Enums/ApiType.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Utility.S3Template.Enums; 2 | 3 | internal enum ApiType 4 | { 5 | Unknown = 0, 6 | Bucket, 7 | Object 8 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/Enums/DataType.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Utility.S3Template.Enums; 2 | 3 | internal enum DataType 4 | { 5 | Unknown = 0, 6 | Request, 7 | RequestMarshal, 8 | Response, 9 | ResponseMarshal 10 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/SimpleS3.Utility.S3Template.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | PreserveNewest 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/Templates/RequestMarshalTemplate.txt: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Genbox.SimpleS3.Core.Abstracts; 3 | using Genbox.SimpleS3.Core.Abstracts.Marshallers; 4 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 5 | using JetBrains.Annotations; 6 | 7 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.%ApiType%s 8 | { 9 | internal class %ApiName%RequestMarshal : IRequestMarshal<%ApiName%Request> 10 | { 11 | public Stream MarshalRequest(%ApiName%Request request, IS3Config config) 12 | { 13 | return null; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/Templates/RequestTemplate.txt: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.Abstracts.Enums; 2 | using Genbox.SimpleS3.Core.Network.Requests.Interfaces; 3 | 4 | namespace Genbox.SimpleS3.Core.Network.Requests.%ApiType%s 5 | { 6 | /// 7 | /// %ApiName% 8 | /// 9 | public class %ApiName%Request : BaseRequest, IHas%ApiType%Name 10 | { 11 | public %ApiName%Request(string %ApiTypeLower%Name) : base(HttpMethod.) 12 | { 13 | %ApiType%Name = %ApiTypeLower%Name; 14 | } 15 | 16 | public string %ApiType%Name { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/Templates/ResponseMarshalTemplate.txt: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using Genbox.SimpleS3.Core.Abstracts; 4 | using Genbox.SimpleS3.Core.Abstracts.Marshallers; 5 | using Genbox.SimpleS3.Core.Network.Requests.Buckets; 6 | using Genbox.SimpleS3.Core.Network.Responses.Buckets; 7 | using JetBrains.Annotations; 8 | 9 | namespace Genbox.SimpleS3.Core.Internals.Marshallers.Responses.%ApiType%s 10 | { 11 | internal class %ApiName%ResponseMarshal : IResponseMarshal<%ApiName%Request, %ApiName%Response> 12 | { 13 | public void MarshalResponse(IS3Config config, %ApiName%Request request, %ApiName%Response response, IDictionary headers, Stream responseStream) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.S3Template/Templates/ResponseTemplate.txt: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Core.Network.Responses.%ApiType%s 2 | { 3 | /// 4 | /// %ApiName% 5 | /// 6 | public class %ApiName%Response : BaseResponse 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.Shared/S3Provider.cs: -------------------------------------------------------------------------------- 1 | namespace Genbox.SimpleS3.Utility.Shared; 2 | 3 | [Flags] 4 | public enum S3Provider 5 | { 6 | None = 0, 7 | AmazonS3 = 1, 8 | BackBlazeB2 = 2, 9 | GoogleCloudStorage = 4, 10 | Wasabi = 8, 11 | 12 | All = AmazonS3 | BackBlazeB2 | GoogleCloudStorage | Wasabi 13 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.TestCleanup/SimpleS3.Utility.TestCleanup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | PreserveNewest 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Src/SimpleS3.Utility.TestSetup/SimpleS3.Utility.TestSetup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | PreserveNewest 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Src/SimpleS3.Wasabi.Tests/SimpleS3.Wasabi.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/SimpleS3.Wasabi.Tests/StaticCreatorTests.cs: -------------------------------------------------------------------------------- 1 | using Genbox.SimpleS3.Core.TestBase.Code; 2 | using Genbox.SimpleS3.Extensions.Wasabi; 3 | 4 | namespace Genbox.SimpleS3.Wasabi.Tests; 5 | 6 | public class StaticCreatorTests 7 | { 8 | [Fact] 9 | public async Task StaticClient() 10 | { 11 | NullNetworkDriver driver = new NullNetworkDriver(); 12 | 13 | WasabiConfig config = new WasabiConfig("ExampleKeyId00000000", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", WasabiRegion.EuCentral1); 14 | using WasabiClient client = new WasabiClient(config, driver); 15 | 16 | await client.GetObjectAsync("testbucket", "GetObjectAsync"); 17 | Assert.Equal("https://testbucket.s3.eu-central-1.wasabisys.com/GetObjectAsync", driver.LastUrl); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/SimpleS3.Wasabi/SimpleS3.Wasabi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | --------------------------------------------------------------------------------