Skip to content

Commit 6561bbc

Browse files
Merge pull request #22 from aKzenT/master
Added cancellation of requests using CancellationToken
2 parents d86103a + 8a0a8ae commit 6561bbc

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

CSharpHTTPClient/Client.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Threading.Tasks;
1010
using System.Web.Script.Serialization;
1111
using System.Web;
12+
using System.Threading;
1213

1314
namespace SendGrid.CSharp.HTTP.Client
1415
{
@@ -266,6 +267,7 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, o
266267

267268
if( Enum.IsDefined(typeof(Methods), binder.Name.ToUpper()))
268269
{
270+
CancellationToken cancellationToken = CancellationToken.None;
269271
string queryParams = null;
270272
string requestBody = null;
271273
int i = 0;
@@ -286,9 +288,13 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, o
286288
{
287289
AddRequestHeader((Dictionary<string, string>)obj);
288290
}
291+
else if (name == "cancellationToken")
292+
{
293+
cancellationToken = (CancellationToken)obj;
294+
}
289295
i++;
290296
}
291-
result = RequestAsync(binder.Name.ToUpper(), requestBody: requestBody, queryParams: queryParams).ConfigureAwait(false);
297+
result = RequestAsync(binder.Name.ToUpper(), requestBody: requestBody, queryParams: queryParams, cancellationToken: cancellationToken).ConfigureAwait(false);
292298
return true;
293299
}
294300
else
@@ -304,22 +310,24 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, o
304310
/// </summary>
305311
/// <param name="client">Client object ready for communication with API</param>
306312
/// <param name="request">The parameters for the API call</param>
313+
/// <param name="cancellationToken">A token that allows cancellation of the http request</param>
307314
/// <returns>Response object</returns>
308-
public async virtual Task<Response> MakeRequest(HttpClient client, HttpRequestMessage request)
315+
public async virtual Task<Response> MakeRequest(HttpClient client, HttpRequestMessage request, CancellationToken cancellationToken = default(CancellationToken))
309316
{
310317

311-
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
318+
HttpResponseMessage response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
312319
return new Response(response.StatusCode, response.Content, response.Headers);
313320
}
314321

315322
/// <summary>
316323
/// Prepare for async call to the API server
317324
/// </summary>
318325
/// <param name="method">HTTP verb</param>
326+
/// <param name="cancellationToken">A token that allows cancellation of the http request</param>
319327
/// <param name="requestBody">JSON formatted string</param>
320328
/// <param name="queryParams">JSON formatted queary paramaters</param>
321329
/// <returns>Response object</returns>
322-
private async Task<Response> RequestAsync(string method, String requestBody = null, String queryParams = null)
330+
private async Task<Response> RequestAsync(string method, String requestBody = null, String queryParams = null, CancellationToken cancellationToken = default(CancellationToken))
323331
{
324332
using (var client = new HttpClient())
325333
{
@@ -367,9 +375,13 @@ private async Task<Response> RequestAsync(string method, String requestBody = nu
367375
RequestUri = new Uri(endpoint),
368376
Content = content
369377
};
370-
return await MakeRequest(client, request).ConfigureAwait(false);
378+
return await MakeRequest(client, request, cancellationToken).ConfigureAwait(false);
371379

372380
}
381+
catch(TaskCanceledException)
382+
{
383+
throw;
384+
}
373385
catch (Exception ex)
374386
{
375387
HttpResponseMessage response = new HttpResponseMessage();

UnitTest/UnitTest.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Net.Http;
77
using System.Text;
88
using System.Net;
9+
using System.Threading;
910

1011
namespace UnitTest
1112
{
@@ -17,12 +18,19 @@ public MockClient(string host, Dictionary<string, string> requestHeaders = null,
1718
{
1819
}
1920

20-
public async override Task<Response> MakeRequest(HttpClient client, HttpRequestMessage request)
21+
public override Task<Response> MakeRequest(HttpClient client, HttpRequestMessage request, CancellationToken cancellationToken)
2122
{
22-
HttpResponseMessage response = new HttpResponseMessage();
23-
response.Content = new StringContent("{'test': 'test_content'}", Encoding.UTF8, "application/json");
24-
response.StatusCode = HttpStatusCode.OK;
25-
return new Response(response.StatusCode, response.Content, response.Headers);
23+
return Task.Factory.StartNew(() =>
24+
{
25+
26+
HttpResponseMessage response = new HttpResponseMessage();
27+
response.Content = new StringContent("{'test': 'test_content'}", Encoding.UTF8, "application/json");
28+
response.StatusCode = HttpStatusCode.OK;
29+
30+
cancellationToken.ThrowIfCancellationRequested();
31+
32+
return new Response(response.StatusCode, response.Content, response.Headers);
33+
}, cancellationToken);
2634
}
2735
}
2836

@@ -74,5 +82,17 @@ public async void TestMethodCall()
7482
var content = new StringContent("{'test': 'test_content'}", Encoding.UTF8, "application/json");
7583
Assert.AreEqual(response.Body.ReadAsStringAsync().Result, content.ReadAsStringAsync().Result);
7684
}
85+
86+
[Test]
87+
[ExpectedException(typeof(TaskCanceledException))]
88+
public async void TestMethodCallWithCancellationToken()
89+
{
90+
var cancellationTokenSource = new CancellationTokenSource();
91+
cancellationTokenSource.Cancel();
92+
93+
var host = "http://api.test.com";
94+
dynamic test_client = new MockClient(host: host);
95+
Response response = await test_client.get(cancellationToken: cancellationTokenSource.Token);
96+
}
7797
}
7898
}

0 commit comments

Comments
 (0)