Skip to content

Commit ed41a79

Browse files
committed
Fixes format exception thrown when user agent header value is incorrect
1 parent dd1dffc commit ed41a79

File tree

3 files changed

+48
-17
lines changed

3 files changed

+48
-17
lines changed

CloudinaryDotNet.Tests/Asset/UrlBuilderTest.cs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,23 +475,43 @@ public void TestExcludeEmptyTransformation()
475475
Assert.AreEqual(TestConstants.DefaultImageUpPath + "c_fill,x_100,y_100/test", uri);
476476
}
477477

478-
[Test]
479-
public void TestAgentPlatformHeaders()
478+
private HttpRequestMessage CreateRequest(string userPlatform)
480479
{
481480
var request = new HttpRequestMessage { RequestUri = new Uri("http://dummy.com") };
482-
m_api.UserPlatform = "Test/1.0";
481+
m_api.UserPlatform = userPlatform;
483482

484483
m_api.PrepareRequestBody(
485484
request,
486485
HttpMethod.GET,
487486
new SortedDictionary<string, object>(),
488487
new FileDescription(""));
488+
return request;
489+
}
490+
491+
[Test]
492+
public void TestAgentPlatformHeaders()
493+
{
494+
var httpRequestMessage = CreateRequest("UserPlatform");
489495

490496
//Can't test the result, so we just verify the UserAgent parameter is sent to the server
491-
StringAssert.AreEqualIgnoringCase($"{m_api.UserPlatform} {ApiShared.USER_AGENT}",
492-
request.Headers.UserAgent.ToString());
493-
StringAssert.IsMatch(@"Test\/1\.0 CloudinaryDotNet\/(\d+)\.(\d+)\.(\d+) \(.*\)",
494-
request.Headers.UserAgent.ToString());
497+
StringAssert.IsMatch(@"CloudinaryDotNet\/(\d+)\.(\d+)\.(\d+) \(" + ApiShared.USER_AGENT.Replace("(", "").Replace(")", "") + @"\) \(UserPlatform\)",
498+
httpRequestMessage.Headers.UserAgent.ToString());
499+
}
500+
501+
[Test]
502+
public void UnityUserAgentShouldNotThrow()
503+
{
504+
var userAgent = "Mono 5.11.0 ((HEAD/768f1b247c6)";
505+
var prevAgent = ApiShared.USER_AGENT;
506+
ApiShared.USER_AGENT = userAgent;
507+
try
508+
{
509+
var httpRequestMessage = CreateRequest("UserPlatform");
510+
}
511+
finally
512+
{
513+
ApiShared.USER_AGENT = prevAgent;
514+
}
495515
}
496516

497517
[Test]

CloudinaryDotNet/ApiShared.Internal.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,21 @@ protected void HandleUnsignedParameters(IDictionary<string, object> parameters)
248248
}
249249
}
250250

251+
private static void AddCommentToUserAgent(
252+
HttpHeaderValueCollection<ProductInfoHeaderValue> userAgentHeader,
253+
string comment)
254+
{
255+
if (string.IsNullOrEmpty(comment))
256+
{
257+
return;
258+
}
259+
260+
var normalizedComment = comment
261+
.Replace(")", string.Empty)
262+
.Replace("(", string.Empty);
263+
userAgentHeader.Add(new ProductInfoHeaderValue($"({normalizedComment})"));
264+
}
265+
251266
private static SortedDictionary<string, object> GetCallParams(HttpMethod method, BaseParams parameters)
252267
{
253268
parameters?.Check();
@@ -455,10 +470,11 @@ private void PrePrepareRequestBody(
455470

456471
// Add platform information to the USER_AGENT header
457472
// This is intended for platform information and not individual applications!
458-
var userPlatform = string.IsNullOrEmpty(UserPlatform)
459-
? USER_AGENT
460-
: string.Format(CultureInfo.InvariantCulture, "{0} {1}", UserPlatform, USER_AGENT);
461-
request.Headers.Add("User-Agent", userPlatform);
473+
var userAgentHeader = request.Headers.UserAgent;
474+
userAgentHeader.Add(new ProductInfoHeaderValue("CloudinaryDotNet", CloudinaryVersion.Full));
475+
476+
AddCommentToUserAgent(userAgentHeader, USER_AGENT);
477+
AddCommentToUserAgent(userAgentHeader, UserPlatform);
462478

463479
byte[] authBytes = Encoding.ASCII.GetBytes(GetApiCredentials());
464480
request.Headers.Add("Authorization", string.Format(CultureInfo.InvariantCulture, "Basic {0}", Convert.ToBase64String(authBytes)));

CloudinaryDotNet/ApiShared.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public partial class ApiShared : ISignProvider
7171
/// <summary>
7272
/// User agent for cloudinary API requests.
7373
/// </summary>
74-
public static string USER_AGENT = BuildUserAgent();
74+
public static string USER_AGENT = RuntimeInformation.FrameworkDescription;
7575

7676
/// <summary>
7777
/// Sends HTTP requests and receives HTTP responses.
@@ -803,10 +803,5 @@ public string BuildUploadFormShared(string field, string resourceType, SortedDic
803803

804804
return builder.ToString();
805805
}
806-
807-
private static string BuildUserAgent()
808-
{
809-
return $"CloudinaryDotNet/{CloudinaryVersion.Full} ({RuntimeInformation.FrameworkDescription})";
810-
}
811806
}
812807
}

0 commit comments

Comments
 (0)