Skip to content

Commit

Permalink
* Added new overload for ExecuteAsync to support Cancellation Tokens
Browse files Browse the repository at this point in the history
* Added more comments in the code and on the methods
* Updated readme file
  • Loading branch information
Zuntara committed Jul 18, 2017
1 parent e9b7589 commit 9e95545
Show file tree
Hide file tree
Showing 17 changed files with 335 additions and 143 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ Define optional error, timeout and success handling

Execute the call

.ExecuteAsync([timoutInMs])
.ExecuteAsync([timoutInMs]) // timeout default = 5000 ms
.ExecuteAsync(CancellationTokenSource)

Returns an object of **RestApiCallResult**
This object contains the Speed and status of the call
Expand Down
13 changes: 12 additions & 1 deletion RestApiBuilder.Core/Behaviors/BaseBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,26 @@

namespace RestApiClientBuilder.Core.Behaviors
{
/// <summary>
/// Base class for behaviors
/// </summary>
public abstract class BaseBehavior : IRestBehavior
{
/// <summary>
/// Called when a request is created.
/// </summary>
/// <param name="request">Request that's created</param>
public virtual void OnRequestCreated(ConnectionRequest request)
{
}

/// <summary>
/// Called when a client is being created, typical place to add a handler to the provider for <see cref="IRestConnectionProvider.OnCreateClient"/>
/// </summary>
/// <param name="provider">Provider used to create requests and clients</param>
/// <param name="baseAddress">Base Uri for the requests</param>
public virtual void OnClientCreation(IRestConnectionProvider provider, Uri baseAddress)
{

}
}
}
9 changes: 9 additions & 0 deletions RestApiBuilder.Core/Interfaces/IRestApiExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace RestApiClientBuilder.Core.Interfaces
Expand All @@ -14,6 +15,14 @@ public interface IRestApiExecutor
/// <exception cref="ArgumentMissingException">Throwed when an API argument in the uri is missing.</exception>
Task<RestApiCallResult> ExecuteAsync(int timeoutMs = 5000);

/// <summary>
/// Execute the REST call and return the result of the call in a wrapped object.
/// </summary>
/// <param name="cts">Cancellation token source (with optional timeout included)</param>
/// <returns>Result of the call with error-info included</returns>
/// <exception cref="ArgumentMissingException">Throwed when an API argument in the uri is missing.</exception>
Task<RestApiCallResult> ExecuteAsync(CancellationTokenSource cts);

/// <summary>
/// Gets triggered when the statuscode of the call is different then 200
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions RestApiBuilder.Core/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.1.0")]
[assembly: AssemblyFileVersion("2.1.0")]
[assembly: AssemblyVersion("2.1.1")]
[assembly: AssemblyFileVersion("2.1.1")]
[assembly: InternalsVisibleTo("RestApiClientBuilder.Core.Tests")]
[assembly: InternalsVisibleTo("RestApiClientBuilder.Owin.OAuth2")]
154 changes: 25 additions & 129 deletions RestApiBuilder.Core/Providers/BaseConnectionProvider.cs
Original file line number Diff line number Diff line change
@@ -1,145 +1,41 @@
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;

namespace RestApiClientBuilder.Core.Providers
{
public class ConnectionRequest
{
public string Content { get; set; }
public Uri RelativeUri { get; set; }
public HttpMethod Method { get; set; }
public Uri BaseAddress { get; set; }
}

public class ConnectionRequestResponse
{
public string ResponseString { get; set; }
public int StatusCode { get; set; }
public bool IsSuccess { get; set; }
public string ErrorReason { get; set; }
}

/// <summary>
/// Base class for a connection provider
/// </summary>
public abstract class BaseConnectionProvider : IRestConnectionProvider
{
/// <summary>
/// True when a custom interception handler is added to the client
/// </summary>
public bool HasHandlers { get; set; }

/// <summary>
/// Called when the client needs to be created
/// </summary>
public Func<bool, object> OnCreateClient { get; set; }

public abstract ConnectionRequest CreateRequest(HttpMethod post, Uri baseAddress, Uri endpointRelativeUri, string content);
/// <summary>
/// Called when a request is created
/// </summary>
/// <param name="method">HTTP method to invoke</param>
/// <param name="baseAddress">Base Uri to invoke to</param>
/// <param name="endpointRelativeUri">Relative uri for the endpoint</param>
/// <param name="content">Optional content for body of PUT and POST requests</param>
/// <returns>Connection request summary data</returns>
public abstract ConnectionRequest CreateRequest(HttpMethod method, Uri baseAddress, Uri endpointRelativeUri, string content);

/// <summary>
/// Executes a request in an async manner.
/// </summary>
/// <param name="connectionRequest">Request definition to execute</param>
/// <param name="token">Cancellation token to use when executing</param>
/// <returns>Response object of the request</returns>
public abstract Task<ConnectionRequestResponse> ProcessRequestAsync(ConnectionRequest connectionRequest, CancellationToken token);
}

public interface IRestConnectionProvider
{
bool HasHandlers { get; set; }

Func<bool, object> OnCreateClient { get; set; }

ConnectionRequest CreateRequest(HttpMethod post, Uri baseAddress, Uri endpointRelativeUri, string content);

Task<ConnectionRequestResponse> ProcessRequestAsync(ConnectionRequest connectionRequest, CancellationToken token);
}

public class HttpClientConnectionProvider : BaseConnectionProvider
{
private static HttpClient _httpClient;

public HttpClientConnectionProvider()
{
OnCreateClient = (hasHandlers) =>
{
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HasHandlers = false;
return client;
};
}

public override ConnectionRequest CreateRequest(HttpMethod method, Uri baseAddress, Uri endpointRelativeUri, string content)
{
return new ConnectionRequest
{
Method = method,
BaseAddress = baseAddress,
RelativeUri = endpointRelativeUri,
Content = content
};
}

public override async Task<ConnectionRequestResponse> ProcessRequestAsync(ConnectionRequest connectionRequest, CancellationToken token)
{
_httpClient = (HttpClient)OnCreateClient(HasHandlers);

_httpClient.BaseAddress = connectionRequest.BaseAddress;

if (connectionRequest.Method == HttpMethod.Post)
{
HttpContent content = new StringContent(connectionRequest.Content);

HttpRequestMessage request = new HttpRequestMessage(System.Net.Http.HttpMethod.Post, connectionRequest.RelativeUri);
request.Content = content;

HttpResponseMessage response = await _httpClient.SendAsync(request, token);

return new ConnectionRequestResponse
{
IsSuccess = response.IsSuccessStatusCode,
ResponseString = response.IsSuccessStatusCode ? await response.Content.ReadAsStringAsync() : null,
StatusCode = (int) response.StatusCode,
ErrorReason = !response.IsSuccessStatusCode ? response.ReasonPhrase : null
};
}
if (connectionRequest.Method == HttpMethod.Put)
{
HttpContent content = new StringContent(connectionRequest.Content);

HttpRequestMessage request = new HttpRequestMessage(System.Net.Http.HttpMethod.Put, connectionRequest.RelativeUri);
request.Content = content;

HttpResponseMessage response = await _httpClient.SendAsync(request, token);

return new ConnectionRequestResponse
{
IsSuccess = response.IsSuccessStatusCode,
ResponseString = response.IsSuccessStatusCode ? await response.Content.ReadAsStringAsync() : null,
StatusCode = (int)response.StatusCode,
ErrorReason = !response.IsSuccessStatusCode ? response.ReasonPhrase : null
};
}
if (connectionRequest.Method == HttpMethod.Get)
{
HttpRequestMessage request = new HttpRequestMessage(System.Net.Http.HttpMethod.Get, connectionRequest.RelativeUri);

HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, token);

return new ConnectionRequestResponse
{
IsSuccess = response.IsSuccessStatusCode,
ResponseString = response.IsSuccessStatusCode ? await response.Content.ReadAsStringAsync() : null,
StatusCode = (int)response.StatusCode,
ErrorReason = !response.IsSuccessStatusCode ? response.ReasonPhrase : null
};
}
if (connectionRequest.Method == HttpMethod.Delete)
{
HttpRequestMessage request = new HttpRequestMessage(System.Net.Http.HttpMethod.Delete, connectionRequest.RelativeUri);

HttpResponseMessage response = await _httpClient.SendAsync(request, token);

return new ConnectionRequestResponse
{
IsSuccess = response.IsSuccessStatusCode,
ResponseString = response.IsSuccessStatusCode ? await response.Content.ReadAsStringAsync() : null,
StatusCode = (int)response.StatusCode,
ErrorReason = !response.IsSuccessStatusCode ? response.ReasonPhrase : null
};
}
return null;
}
}
}
30 changes: 30 additions & 0 deletions RestApiBuilder.Core/Providers/ConnectionRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;

namespace RestApiClientBuilder.Core.Providers
{
/// <summary>
/// Connection request wrapper
/// </summary>
public class ConnectionRequest
{
/// <summary>
/// Optional content for PUT or POST requests
/// </summary>
public string Content { get; set; }

/// <summary>
/// Relative Uri for the request
/// </summary>
public Uri RelativeUri { get; set; }

/// <summary>
/// Method of the request
/// </summary>
public HttpMethod Method { get; set; }

/// <summary>
/// Base Uri for the request
/// </summary>
public Uri BaseAddress { get; set; }
}
}
28 changes: 28 additions & 0 deletions RestApiBuilder.Core/Providers/ConnectionRequestResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace RestApiClientBuilder.Core.Providers
{
/// <summary>
/// Response of request wrapper
/// </summary>
public class ConnectionRequestResponse
{
/// <summary>
/// Response in string format (raw)
/// </summary>
public string ResponseString { get; set; }

/// <summary>
/// Statuscode of the response
/// </summary>
public int StatusCode { get; set; }

/// <summary>
/// True when the call is a success
/// </summary>
public bool IsSuccess { get; set; }

/// <summary>
/// Filled when an error occured.
/// </summary>
public string ErrorReason { get; set; }
}
}
Loading

0 comments on commit 9e95545

Please sign in to comment.