Skip to content

Commit 3e6b4e5

Browse files
author
Ross Gardner
committed
It appears possible for a PUT request to enter a state where a timeout does not correctly fire. The asyncresult of the request is correctly passed into the SetTimeout method after creation but when it progresses to the response object the SetTimeout is neglected.
This allows for a scenario where a put request can begin and if an error occurs in the response the client can remain unaware as the timeout is not called and therefore the callback never completes. I have seen this behaviour on a mobile device where the connection is dropped during a PUT request that takes a few seconds to return.
1 parent b990048 commit 3e6b4e5

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

RestSharp.IntegrationTests/AsyncTests.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,54 @@ public void Handles_GET_Request_Errors_TaskAsync_With_Response_Type()
168168
}
169169
}
170170

171+
[Fact]
172+
public void Can_Timeout_GET_TaskAsync()
173+
{
174+
const string baseUrl = "http://localhost:8080/";
175+
using (SimpleServer.Create(baseUrl, Handlers.Generic<ResponseHandler>()))
176+
{
177+
var client = new RestClient(baseUrl);
178+
var request = new RestRequest("timeout", Method.GET).AddBody("Body_Content");
179+
180+
//Half the value of ResponseHandler.Timeout
181+
request.Timeout = 500;
182+
183+
System.AggregateException agg = Assert.Throws<System.AggregateException>(
184+
delegate
185+
{
186+
var task = client.ExecuteTaskAsync(request);
187+
task.Wait();
188+
});
189+
190+
Assert.IsType(typeof(WebException), agg.InnerException);
191+
Assert.Equal("The request timed-out.", agg.InnerException.Message);
192+
}
193+
}
194+
195+
[Fact]
196+
public void Can_Timeout_PUT_TaskAsync()
197+
{
198+
const string baseUrl = "http://localhost:8080/";
199+
using (SimpleServer.Create(baseUrl, Handlers.Generic<ResponseHandler>()))
200+
{
201+
var client = new RestClient(baseUrl);
202+
var request = new RestRequest("timeout", Method.PUT).AddBody("Body_Content");
203+
204+
//Half the value of ResponseHandler.Timeout
205+
request.Timeout = 500;
206+
207+
System.AggregateException agg = Assert.Throws<System.AggregateException>(
208+
delegate
209+
{
210+
var task = client.ExecuteTaskAsync(request);
211+
task.Wait();
212+
});
213+
214+
Assert.IsType(typeof(WebException), agg.InnerException);
215+
Assert.Equal("The request timed-out.", agg.InnerException.Message);
216+
}
217+
}
218+
171219
void UrlToStatusCodeHandler(HttpListenerContext obj)
172220
{
173221
obj.Response.StatusCode = int.Parse(obj.Request.Url.Segments.Last());

RestSharp/Http.Async.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ private void RequestStreamCallback(IAsyncResult result, Action<HttpResponse> cal
249249
return;
250250
}
251251

252-
webRequest.BeginGetResponse(r => ResponseCallback(r, callback), webRequest);
252+
IAsyncResult asyncResult = webRequest.BeginGetResponse(r => ResponseCallback(r, callback), webRequest);
253+
SetTimeout(asyncResult, _timeoutState);
253254
}
254255

255256
private void SetTimeout(IAsyncResult asyncResult, TimeOutState timeOutState)

0 commit comments

Comments
 (0)