diff --git a/generator/.DevConfigs/aabf4e64-a7dd-4ee3-95a7-c8466c22a7e3.json b/generator/.DevConfigs/aabf4e64-a7dd-4ee3-95a7-c8466c22a7e3.json new file mode 100644 index 000000000000..a0f861467e75 --- /dev/null +++ b/generator/.DevConfigs/aabf4e64-a7dd-4ee3-95a7-c8466c22a7e3.json @@ -0,0 +1,9 @@ +{ + "core": { + "changeLogMessages": [ + "Improve user agent string construction in Marshaller.cs" + ], + "type": "patch", + "updateMinimum": true + } +} \ No newline at end of file diff --git a/sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/Marshaller.cs b/sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/Marshaller.cs index 839d09fd4173..3b7fc0315665 100644 --- a/sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/Marshaller.cs +++ b/sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/Marshaller.cs @@ -15,6 +15,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.Text; using Amazon.Runtime.Telemetry; @@ -106,29 +107,28 @@ private static void SetRecursionDetectionHeader(IDictionary head private static void SetUserAgentHeader(IRequestContext requestContext) { - var sb = new StringBuilder(requestContext.ClientConfig.UserAgent); + var sb = new StringBuilder(256); + + sb.Append(InternalSDKUtils.ReplaceInvalidUserAgentCharacters(requestContext.ClientConfig.UserAgent)); var clientAppId = requestContext.ClientConfig.ClientAppId; if (!string.IsNullOrEmpty(clientAppId)) - sb.AppendFormat(" app/{0}", clientAppId); + sb.Append(" app/").Append(InternalSDKUtils.ReplaceInvalidUserAgentCharacters(clientAppId)); - var retryMode = requestContext.ClientConfig.RetryMode.ToString().ToLower(); - sb.AppendFormat(" cfg/retry-mode#{0}", retryMode); + sb.Append(" cfg/retry-mode#}").Append(ToUserAgentHeaderString(requestContext.ClientConfig.RetryMode)); - sb.AppendFormat(" md/{0}", requestContext.IsAsync ? "ClientAsync" : "ClientSync"); + sb.Append(" md/").Append(requestContext.IsAsync ? "ClientAsync" : "ClientSync"); - sb.AppendFormat(" cfg/init-coll#{0}", AWSConfigs.InitializeCollections ? "1" : "0"); + sb.Append(" cfg/init-coll#").Append(AWSConfigs.InitializeCollections ? '1' : '0'); var userAgentAddition = requestContext.OriginalRequest.UserAgentAddition; if (!string.IsNullOrEmpty(userAgentAddition)) { - sb.AppendFormat(" {0}", userAgentAddition); + sb.Append(' ').Append(InternalSDKUtils.ReplaceInvalidUserAgentCharacters(userAgentAddition)); } var userAgent = sb.ToString(); - userAgent = InternalSDKUtils.ReplaceInvalidUserAgentCharacters(userAgent); - if (requestContext.ClientConfig.UseAlternateUserAgentHeader) { requestContext.Request.Headers[HeaderKeys.XAmzUserAgentHeader] = userAgent; @@ -138,5 +138,18 @@ private static void SetUserAgentHeader(IRequestContext requestContext) requestContext.Request.Headers[HeaderKeys.UserAgentHeader] = userAgent; } } + + private static string ToUserAgentHeaderString(RequestRetryMode requestRetryMode) + { + switch (requestRetryMode) + { + case RequestRetryMode.Standard: + return "standard"; + case RequestRetryMode.Adaptive: + return "adaptive"; + default: + return requestRetryMode.ToString().ToLowerInvariant(); + } + } } } diff --git a/sdk/src/Core/GlobalSuppressions.cs b/sdk/src/Core/GlobalSuppressions.cs index 476b7e93d6d5..359bd1bc2926 100644 --- a/sdk/src/Core/GlobalSuppressions.cs +++ b/sdk/src/Core/GlobalSuppressions.cs @@ -191,9 +191,9 @@ [module: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Amazon.Runtime.Internal.Auth.AWS4Signer.#CanonicalizeHeaders(System.Collections.Generic.ICollection`1>)")] [module: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Amazon.Runtime.Internal.Auth.S3Signer.#BuildCanonicalizedHeaders(System.Collections.Generic.IDictionary`2)")] [module: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Amazon.Runtime.Internal.Auth.AWS4Signer.#DetermineSigningRegion(Amazon.Runtime.IClientConfig,System.String,Amazon.RegionEndpoint,Amazon.Runtime.Internal.IRequest)")] - [module: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Amazon.Runtime.Internal.Auth.AWS4Signer.#CanonicalizeHeaders(System.Collections.Generic.IDictionary`2)")] [module: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Amazon.Runtime.Internal.Auth.AWS4Signer.#CanonicalizeHeaderNames(System.Collections.Generic.IDictionary`2)")] +[module: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Amazon.Runtime.Internal.Marshaller.#ToUserAgentHeaderString(Amazon.Runtime.RequestRetryMode)")] // Types names matching namespaces [module: SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces", Scope = "type", Target = "Amazon.Auth.AccessControlPolicy.Policy")] diff --git a/sdk/test/Services/SecurityToken/UnitTests/Custom/StaticCheckTests.cs b/sdk/test/Services/SecurityToken/UnitTests/Custom/StaticCheckTests.cs index 1f516a944cfd..1b576b6ae127 100644 --- a/sdk/test/Services/SecurityToken/UnitTests/Custom/StaticCheckTests.cs +++ b/sdk/test/Services/SecurityToken/UnitTests/Custom/StaticCheckTests.cs @@ -83,5 +83,15 @@ public void EnsureCredentialProfileDetectorSetup() // the properties are used at least once. Assert.IsTrue(profileOptionsProperties.SetEquals(referencedProfileOptionsProperties)); } + + [TestMethod] + public void LookForRequestRetryModeChanges() + { + var expectedHash = "2FC699DB6A4284C5D53F3B7FA4E64165576FD1F6AE458BC737AE503F06DFBE4C"; + AssertExtensions.AssertEnumUnchanged( + typeof(RequestRetryMode), + expectedHash, + "The Amazon.Runtime.Internal.Marshaller.ToUserAgentHeaderString method implementation may need to be updated."); + } } } \ No newline at end of file