diff --git a/src/abstractions/MultipartBody.cs b/src/abstractions/MultipartBody.cs index c785cccb..c689085c 100644 --- a/src/abstractions/MultipartBody.cs +++ b/src/abstractions/MultipartBody.cs @@ -91,6 +91,7 @@ public bool RemovePart(string partName) private readonly Dictionary _parts = new Dictionary(StringComparer.OrdinalIgnoreCase); /// public IDictionary> GetFieldDeserializers() => throw new NotImplementedException(); + private const char DoubleQuote = '"'; /// public void Serialize(ISerializationWriter writer) { @@ -123,13 +124,13 @@ public void Serialize(ISerializationWriter writer) contentDispositionBuilder.Clear(); contentDispositionBuilder.Append("form-data; name=\""); contentDispositionBuilder.Append(part.Name); - contentDispositionBuilder.Append("\""); + contentDispositionBuilder.Append(DoubleQuote); if(part.FileName != null) { contentDispositionBuilder.Append("; filename=\""); contentDispositionBuilder.Append(part.FileName); - contentDispositionBuilder.Append("\""); + contentDispositionBuilder.Append(DoubleQuote); } writer.WriteStringValue("Content-Disposition", contentDispositionBuilder.ToString()); @@ -176,12 +177,9 @@ public void Serialize(ISerializationWriter writer) AddNewLine(writer); writer.WriteStringValue(string.Empty, $"--{Boundary}--"); } - private void AddNewLine(ISerializationWriter writer) - { - writer.WriteStringValue(string.Empty, string.Empty); - } + private static void AddNewLine(ISerializationWriter writer) => writer.WriteStringValue(string.Empty, string.Empty); - private void WriteSerializedContent(ISerializationWriter writer, ISerializationWriter partWriter) + private static void WriteSerializedContent(ISerializationWriter writer, ISerializationWriter partWriter) { using var partContent = partWriter.GetSerializedContent(); if(partContent.CanSeek) @@ -191,19 +189,11 @@ private void WriteSerializedContent(ISerializationWriter writer, ISerializationW writer.WriteByteArrayValue(string.Empty, ms.ToArray()); } - private class Part + private sealed class Part(string name, object content, string contentType, string? fileName) { - public Part(string name, object content, string contentType, string? fileName) - { - this.Name = name; - this.Content = content; - this.ContentType = contentType; - this.FileName = fileName; - } - - public string Name { get; } - public object Content { get; } - public string ContentType { get; } - public string? FileName { get; } + public string Name { get; } = name; + public object Content { get; } = content; + public string ContentType { get; } = contentType; + public string? FileName { get; } = fileName; } } diff --git a/src/http/httpClient/HttpClientRequestAdapter.cs b/src/http/httpClient/HttpClientRequestAdapter.cs index a178fc75..af2c2ac1 100644 --- a/src/http/httpClient/HttpClientRequestAdapter.cs +++ b/src/http/httpClient/HttpClientRequestAdapter.cs @@ -508,6 +508,7 @@ private async Task GetHttpResponseMessage(RequestInformatio /// The key for the event raised by tracing when an authentication challenge is received /// public const string AuthenticateChallengedEventKey = "com.microsoft.kiota.authenticate_challenge_received"; + private static readonly char[] ComaSplitSeparator = [',']; private async Task RetryCAEResponseIfRequired(HttpResponseMessage response, RequestInformation requestInfo, CancellationToken cancellationToken, string? claims, Activity? activityForAttributes) { @@ -528,7 +529,7 @@ private async Task RetryCAEResponseIfRequired(HttpResponseM if(authHeader is not null) { - var authHeaderParameters = authHeader.Parameter?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var authHeaderParameters = authHeader.Parameter?.Split(ComaSplitSeparator, StringSplitOptions.RemoveEmptyEntries); string? rawResponseClaims = null; if(authHeaderParameters != null) diff --git a/src/http/httpClient/Middleware/ParametersNameDecodingHandler.cs b/src/http/httpClient/Middleware/ParametersNameDecodingHandler.cs index 61c3f69a..edff7395 100644 --- a/src/http/httpClient/Middleware/ParametersNameDecodingHandler.cs +++ b/src/http/httpClient/Middleware/ParametersNameDecodingHandler.cs @@ -70,28 +70,30 @@ protected override Task SendAsync(HttpRequestMessage reques activity?.Dispose(); } } + private static readonly char[] EntriesSeparator = ['&']; + private static readonly char[] ParameterSeparator = ['=']; internal static string? DecodeUriEncodedString(string? original, char[] charactersToDecode) { - if(string.IsNullOrEmpty(original) || charactersToDecode == null || charactersToDecode.Length == 0) + // for some reason static analysis is not picking up the fact that string.IsNullOrEmpty is already checking for null + if(original is null || original.Length == 0 || charactersToDecode == null || charactersToDecode.Length == 0) return original; var symbolsToReplace = new List<(string, string)>(); foreach(var character in charactersToDecode) { var symbol = ($"%{Convert.ToInt32(character):X}", character.ToString()); - if(original?.Contains(symbol.Item1) ?? false) + if(original.Contains(symbol.Item1)) { symbolsToReplace.Add(symbol); } } var encodedParameterValues = new List(); - var parts = original?.TrimStart('?').Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries); - if(parts is null) return original; + var parts = original.TrimStart('?').Split(EntriesSeparator, StringSplitOptions.RemoveEmptyEntries); foreach(var part in parts) { - var parameter = part.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[0]; + var parameter = part.Split(ParameterSeparator, StringSplitOptions.RemoveEmptyEntries)[0]; if(parameter.Contains("%")) // only pull out params with `%` (encoded) { encodedParameterValues.Add(parameter); @@ -108,7 +110,7 @@ protected override Task SendAsync(HttpRequestMessage reques updatedParameterName = updatedParameterName.Replace(symbolToReplace.Item1, symbolToReplace.Item2); } } - original = original?.Replace(parameter, updatedParameterName); + original = original.Replace(parameter, updatedParameterName); } return original; diff --git a/src/serialization/form/FormParseNode.cs b/src/serialization/form/FormParseNode.cs index 8cb0eb67..8101a7c7 100644 --- a/src/serialization/form/FormParseNode.cs +++ b/src/serialization/form/FormParseNode.cs @@ -17,6 +17,8 @@ public class FormParseNode : IParseNode private readonly string RawValue; private string DecodedValue => Uri.UnescapeDataString(RawValue); private readonly Dictionary Fields; + private static readonly char[] pairDelimiter = ['=']; + private static readonly char[] entriesDelimiter = ['&']; /// Initializes a new instance of the class. /// The raw value to parse. /// Thrown when the is null. @@ -24,8 +26,7 @@ public FormParseNode(string rawValue) { RawValue = rawValue ?? throw new ArgumentNullException(nameof(rawValue)); Fields = new Dictionary(StringComparer.OrdinalIgnoreCase); - char[] pairDelimiter = new char[] { '=' }; - string[] pairs = rawValue.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries); + string[] pairs = rawValue.Split(entriesDelimiter, StringSplitOptions.RemoveEmptyEntries); foreach(string pair in pairs) { string[] keyValue = pair.Split(pairDelimiter, StringSplitOptions.RemoveEmptyEntries); @@ -89,6 +90,7 @@ private static string SanitizeKey(string key) private static readonly Type timeSpanType = typeof(TimeSpan?); private static readonly Type dateType = typeof(Date?); private static readonly Type timeType = typeof(Time?); + private static readonly char[] ComaSeparator = [',']; /// /// Get the collection of primitives of type from the form node @@ -97,7 +99,7 @@ private static string SanitizeKey(string key) public IEnumerable GetCollectionOfPrimitiveValues() { var genericType = typeof(T); - var primitiveValueCollection = DecodedValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var primitiveValueCollection = DecodedValue.Split(ComaSeparator, StringSplitOptions.RemoveEmptyEntries); foreach(var collectionValue in primitiveValueCollection) { var currentParseNode = new FormParseNode(collectionValue) @@ -223,7 +225,7 @@ private void AssignFieldValues(T item) where T : IParsable IEnumerable IParseNode.GetCollectionOfEnumValues() #endif { - foreach(var v in DecodedValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + foreach(var v in DecodedValue.Split(ComaSeparator, StringSplitOptions.RemoveEmptyEntries)) yield return GetEnumValueInternal(v); }