diff --git a/Octokit/Http/ApiInfoParser.cs b/Octokit/Http/ApiInfoParser.cs index 94a51c5649..2d7bf20f8f 100644 --- a/Octokit/Http/ApiInfoParser.cs +++ b/Octokit/Http/ApiInfoParser.cs @@ -16,6 +16,11 @@ internal static class ApiInfoParser static readonly Regex _linkRelRegex = new Regex("rel=\"(next|prev|first|last)\"", regexOptions); static readonly Regex _linkUriRegex = new Regex("<(.+)>", regexOptions); + static KeyValuePair LookupHeader(IDictionary headers, string key) + { + return headers.FirstOrDefault(h => string.Equals(h.Key, key, StringComparison.OrdinalIgnoreCase)); + } + public static ApiInfo ParseResponseHeaders(IDictionary responseHeaders) { Ensure.ArgumentNotNull(responseHeaders, nameof(responseHeaders)); @@ -25,28 +30,32 @@ public static ApiInfo ParseResponseHeaders(IDictionary responseH var acceptedOauthScopes = new List(); string etag = null; - if (responseHeaders.ContainsKey("X-Accepted-OAuth-Scopes")) + var acceptedOauthScopesKey = LookupHeader(responseHeaders, "X-Accepted-OAuth-Scopes"); + if (!acceptedOauthScopesKey.Equals(default(KeyValuePair))) { - acceptedOauthScopes.AddRange(responseHeaders["X-Accepted-OAuth-Scopes"] + acceptedOauthScopes.AddRange(acceptedOauthScopesKey.Value .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Trim())); } - if (responseHeaders.ContainsKey("X-OAuth-Scopes")) + var oauthScopesKey = LookupHeader(responseHeaders, "X-OAuth-Scopes"); + if (!oauthScopesKey.Equals(default(KeyValuePair))) { - oauthScopes.AddRange(responseHeaders["X-OAuth-Scopes"] + oauthScopes.AddRange(oauthScopesKey.Value .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Trim())); } - if (responseHeaders.ContainsKey("ETag")) + var etagKey = LookupHeader(responseHeaders, "ETag"); + if (!etagKey.Equals(default(KeyValuePair))) { - etag = responseHeaders["ETag"]; + etag = etagKey.Value; } - if (responseHeaders.ContainsKey("Link")) + var linkKey = LookupHeader(responseHeaders, "Link"); + if (!linkKey.Equals(default(KeyValuePair))) { - var links = responseHeaders["Link"].Split(','); + var links = linkKey.Value.Split(','); foreach (var link in links) { var relMatch = _linkRelRegex.Match(link); diff --git a/Octokit/Http/RateLimit.cs b/Octokit/Http/RateLimit.cs index a5c2f28800..a3d434cf51 100644 --- a/Octokit/Http/RateLimit.cs +++ b/Octokit/Http/RateLimit.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Linq; #if !NO_SERIALIZABLE using System.Runtime.Serialization; #endif @@ -65,11 +66,27 @@ public RateLimit(int limit, int remaining, long resetAsUtcEpochSeconds) [Parameter(Key = "reset")] public long ResetAsUtcEpochSeconds { get; private set; } + static KeyValuePair LookupHeader(IDictionary headers, string key) + { + return headers.FirstOrDefault(h => string.Equals(h.Key, key, StringComparison.OrdinalIgnoreCase)); + } + static long GetHeaderValueAsInt32Safe(IDictionary responseHeaders, string key) { - string value; long result; - return !responseHeaders.TryGetValue(key, out value) || value == null || !long.TryParse(value, out result) + + var foundKey = LookupHeader(responseHeaders, key); + if (foundKey.Equals(default(KeyValuePair))) + { + return 0; + } + + if (string.IsNullOrWhiteSpace(foundKey.Value)) + { + return 0; + } + + return !long.TryParse(foundKey.Value, out result) ? 0 : result; }