| | 1 | | // Copyright (c) Microsoft Corporation. All rights reserved. |
| | 2 | | // Licensed under the MIT License. |
| | 3 | |
|
| | 4 | | using System; |
| | 5 | | using System.Collections.Generic; |
| | 6 | | using System.Net.Http; |
| | 7 | | using Azure.Core; |
| | 8 | | using Azure.Core.Pipeline; |
| | 9 | |
|
| | 10 | | namespace Azure.Storage |
| | 11 | | { |
| | 12 | | /// <summary> |
| | 13 | | /// Defines the client configuration options for connecting to Azure |
| | 14 | | /// Storage. |
| | 15 | | /// </summary> |
| | 16 | | internal static class StorageClientOptions |
| | 17 | | { |
| | 18 | | /// <summary> |
| | 19 | | /// The default scope used for token authentication with Storage. |
| | 20 | | /// </summary> |
| | 21 | | private const string StorageScope = "https://storage.azure.com/.default"; |
| | 22 | |
|
| | 23 | | /// <summary> |
| | 24 | | /// Set common ClientOptions defaults for Azure Storage. |
| | 25 | | /// </summary> |
| | 26 | | /// <param name="options">Storage ClientOptions.</param> |
| | 27 | | public static void Initialize(this ClientOptions options) |
| | 28 | | { |
| | 29 | | // We're going to use the default ResponseClassifier to decide |
| | 30 | | // which errors are retriable, but may extend this in the future. |
| | 31 | |
|
| | 32 | | // We'll use the standard RetryPolicy with a few more retries |
| 336 | 33 | | options.Retry.MaxRetries = Constants.MaxReliabilityRetries; |
| 336 | 34 | | } |
| | 35 | |
|
| | 36 | | /// <summary> |
| | 37 | | /// Get an authentication policy to sign Storage requests. |
| | 38 | | /// </summary> |
| | 39 | | /// <param name="credential">Credential to use.</param> |
| | 40 | | /// <returns>An authentication policy.</returns> |
| | 41 | | public static HttpPipelinePolicy AsPolicy(this StorageSharedKeyCredential credential) => |
| 272 | 42 | | new StorageSharedKeyPipelinePolicy( |
| 272 | 43 | | credential ?? throw Errors.ArgumentNull(nameof(credential))); |
| | 44 | |
|
| | 45 | | /// <summary> |
| | 46 | | /// Get an authentication policy to sign Storage requests. |
| | 47 | | /// </summary> |
| | 48 | | /// <param name="credential">Credential to use.</param> |
| | 49 | | /// <returns>An authentication policy.</returns> |
| | 50 | | public static HttpPipelinePolicy AsPolicy(this TokenCredential credential) => |
| 12 | 51 | | new BearerTokenAuthenticationPolicy( |
| 12 | 52 | | credential ?? throw Errors.ArgumentNull(nameof(credential)), |
| 12 | 53 | | StorageScope); |
| | 54 | |
|
| | 55 | | /// <summary> |
| | 56 | | /// Get an optional authentication policy to sign Storage requests. |
| | 57 | | /// </summary> |
| | 58 | | /// <param name="credentials">Optional credentials to use.</param> |
| | 59 | | /// <returns>An optional authentication policy.</returns> |
| | 60 | | public static HttpPipelinePolicy GetAuthenticationPolicy(object credentials = null) |
| | 61 | | { |
| | 62 | | // Use the credentials to decide on the authentication policy |
| | 63 | | switch (credentials) |
| | 64 | | { |
| | 65 | | case SharedAccessSignatureCredentials _: |
| | 66 | | case null: // Anonymous authentication |
| 8 | 67 | | return null; |
| | 68 | | case StorageSharedKeyCredential sharedKey: |
| 16 | 69 | | return sharedKey.AsPolicy(); |
| | 70 | | case TokenCredential token: |
| 0 | 71 | | return token.AsPolicy(); |
| | 72 | | default: |
| 0 | 73 | | throw Errors.InvalidCredentials(credentials.GetType().FullName); |
| | 74 | | } |
| | 75 | | } |
| | 76 | |
|
| | 77 | | /// <summary> |
| | 78 | | /// Create an HttpPipeline from Storage ClientOptions. |
| | 79 | | /// </summary> |
| | 80 | | /// <param name="options">The Storage ClientOptions.</param> |
| | 81 | | /// <param name="authentication">Optional authentication policy.</param> |
| | 82 | | /// <param name="geoRedundantSecondaryStorageUri">The secondary URI to be used for retries on failed read reques |
| | 83 | | /// <returns>An HttpPipeline to use for Storage requests.</returns> |
| | 84 | | public static HttpPipeline Build(this ClientOptions options, HttpPipelinePolicy authentication = null, Uri geoRe |
| | 85 | | { |
| 336 | 86 | | List<HttpPipelinePolicy> perRetryClientPolicies = new List<HttpPipelinePolicy>(); |
| 336 | 87 | | StorageResponseClassifier classifier = new StorageResponseClassifier(); |
| 336 | 88 | | if (geoRedundantSecondaryStorageUri != null) |
| | 89 | | { |
| 20 | 90 | | perRetryClientPolicies.Add(new GeoRedundantReadPolicy(geoRedundantSecondaryStorageUri)); |
| 20 | 91 | | classifier.SecondaryStorageUri = geoRedundantSecondaryStorageUri; |
| | 92 | | } |
| | 93 | |
|
| 336 | 94 | | perRetryClientPolicies.Add(new StorageRequestValidationPipelinePolicy(options)); |
| 336 | 95 | | perRetryClientPolicies.Add(authentication); // authentication needs to be the last of the perRetry client po |
| | 96 | |
|
| 336 | 97 | | return HttpPipelineBuilder.Build( |
| 336 | 98 | | options, |
| 336 | 99 | | Array.Empty<HttpPipelinePolicy>(), |
| 336 | 100 | | perRetryClientPolicies.ToArray(), |
| 336 | 101 | | classifier); |
| | 102 | | } |
| | 103 | |
|
| | 104 | | /// <summary> |
| | 105 | | /// Create an HttpPipeline from Storage ClientOptions. |
| | 106 | | /// </summary> |
| | 107 | | /// <param name="options">The Storage ClientOptions.</param> |
| | 108 | | /// <param name="credentials">Optional authentication credentials.</param> |
| | 109 | | /// <param name="geoRedundantSecondaryStorageUri">The secondary URI to be used for retries on failed read reques |
| | 110 | | /// <returns>An HttpPipeline to use for Storage requests.</returns> |
| | 111 | | public static HttpPipeline Build(this ClientOptions options, object credentials, Uri geoRedundantSecondaryStorag |
| 24 | 112 | | Build(options, GetAuthenticationPolicy(credentials), geoRedundantSecondaryStorageUri); |
| | 113 | | } |
| | 114 | | } |