forked from mercadolibre/net-sdk
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Using HttpClient instead of RestSharp.
- Use of .NET 4's HttpClient instead of RestSharp - Removed depdendency to RestSharp - No longer compiling project as net-sdk.dll but as MercadoLibreSdk.dll (this will help to publish the SDK to nuget) - New mercado libre site enum so that the SDK can be used against a given mercardo libre country/site - API end points no longer static - Credentials are in their own class - Ability to listen to changes to the application access tokens - No longer relying on node JS to unit test the HTTP requests (using mock HTTP library instead) - MeliApiService implements IMeliApiService to make it easy to moq the service - Using the moq library to mock calls to interface in unit test - Added rules to .gitignore file
- Loading branch information
Showing
233 changed files
with
63,334 additions
and
47,773 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,9 @@ TestResult.xml | |
net-sdk.userprefs | ||
.DS_Store | ||
SDK/.DS_Store | ||
*.obj | ||
*.exe | ||
*.pdb | ||
*.user | ||
[Bb]in | ||
[Dd]ebug*/ |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
using System; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Http.Headers; | ||
using System.Threading.Tasks; | ||
|
||
namespace MercadoLibre.SDK.Http | ||
{ | ||
/// <summary> | ||
/// Helper class to easily get new instances of a <see cref="HttpClient"/> with default behaviour and a retry mechanism. | ||
/// </summary> | ||
/// <remarks> | ||
/// Most of the time only one instance of <see cref="HttpClient"/> should be used per request: | ||
/// If you hang on to one instance of HTTP client and change its Timeout setting after a fist request was issued an exception will be thrown. | ||
/// </remarks> | ||
public class HttpClientProvider : IHttpClientProvider | ||
{ | ||
/// <summary> | ||
/// Hook to intercept HTTP responses and react to them (e.g. automatically authenticate upon 401 Unauthorized responses). | ||
/// </summary> | ||
/// <value> | ||
/// The custom send asynchronous. | ||
/// </value> | ||
/// <returns>True when the original request should be retried.</returns> | ||
public Func<HttpResponseMessage, Task<bool>> RetryIntercept { get; set; } | ||
|
||
/// <summary> | ||
/// Hook to set default settings on the HTTP client that <see cref="Create(System.Net.Http.HttpMessageHandler, bool)"/> returns. | ||
/// </summary> | ||
/// <value> | ||
/// The initialise with. | ||
/// </value> | ||
public Action<HttpClient> InitialiseWith { get; set; } | ||
|
||
/// <summary> | ||
/// Gets a new instance of <see cref="HttpClient" />. | ||
/// </summary> | ||
/// <param name="configureRetryIntercept">if set to <c>true</c> [configure the retry intercept].</param> | ||
/// <returns></returns> | ||
public HttpClient Create(bool configureRetryIntercept = true) | ||
{ | ||
return Create(null, configureRetryIntercept); | ||
} | ||
|
||
/// <summary> | ||
/// Gets a new instance of <see cref="HttpClient" />. | ||
/// </summary> | ||
/// <param name="innerMessageHandler">The inner message handler.</param> | ||
/// <param name="configureRetryIntercept">if set to <c>true</c> [configure the retry intercept].</param> | ||
/// <returns></returns> | ||
public HttpClient Create(HttpMessageHandler innerMessageHandler, bool configureRetryIntercept = true) | ||
{ | ||
HttpClient client; | ||
|
||
if (innerMessageHandler == null) | ||
{ | ||
var innerClientHandler = new HttpClientHandler | ||
{ | ||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | ||
}; | ||
|
||
client = RetryIntercept == null || configureRetryIntercept == false | ||
? new HttpClient(innerClientHandler) | ||
: new HttpClient(new RetryDelegatingHandler | ||
{ | ||
InnerHandler = innerClientHandler, | ||
RetryIntercept = RetryIntercept | ||
}); | ||
} | ||
else | ||
{ | ||
client = RetryIntercept == null || configureRetryIntercept == false | ||
? new HttpClient(innerMessageHandler) | ||
: new HttpClient(new RetryDelegatingHandler | ||
{ | ||
RetryIntercept = RetryIntercept, | ||
InnerHandler = innerMessageHandler | ||
}); | ||
} | ||
|
||
if (InitialiseWith != null) | ||
{ | ||
InitialiseWith(client); | ||
} | ||
|
||
return client; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System.Net.Http; | ||
|
||
namespace MercadoLibre.SDK.Http | ||
{ | ||
/// <summary> | ||
/// Interface to provide a HTTP client | ||
/// </summary> | ||
public interface IHttpClientProvider | ||
{ | ||
/// <summary> | ||
/// Gets a new instance of <see cref="HttpClient" />. | ||
/// </summary> | ||
/// <param name="configureRetryIntercept">if set to <c>true</c> [configure the retry intercept].</param> | ||
/// <returns></returns> | ||
HttpClient Create(bool configureRetryIntercept = true); | ||
|
||
/// <summary> | ||
/// Gets a new instance of <see cref="HttpClient" />. | ||
/// </summary> | ||
/// <param name="innerMessageHandler">The inner message handler (optional).</param> | ||
/// <param name="configureRetryIntercept">if set to <c>true</c> [configure the retry intercept].</param> | ||
/// <returns></returns> | ||
HttpClient Create(HttpMessageHandler innerMessageHandler, bool configureRetryIntercept = true); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using System; | ||
using System.Net.Http; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace MercadoLibre.SDK.Http | ||
{ | ||
/// <summary> | ||
/// HTTP Message handler that inspect status code in responses and automatically tries to refresh the token if a refresh token is set. | ||
/// </summary> | ||
public class RetryDelegatingHandler : DelegatingHandler | ||
{ | ||
/// <summary> | ||
/// Gets or sets a hook to determinue (and optionaly take action (e.g. authenticate)) wether the request should be retried or not. | ||
/// </summary> | ||
/// <value> | ||
/// The retry intercept. | ||
/// </value> | ||
/// <returns>True when the original request should be retried.</returns> | ||
public Func<HttpResponseMessage, Task<bool>> RetryIntercept { get; set; } | ||
|
||
/// <summary> | ||
/// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation. | ||
/// </summary> | ||
/// <param name="request">The HTTP request message to send to the server.</param> | ||
/// <param name="cancellationToken">A cancellation token to cancel operation.</param> | ||
/// <returns> | ||
/// Returns <see cref="T:System.Threading.Tasks.Task`1" />. The task object representing the asynchronous operation. | ||
/// </returns> | ||
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
var response = await base.SendAsync(request, cancellationToken); | ||
|
||
if (RetryIntercept != null) | ||
{ | ||
// Hook to determine wether the request should be retried or not | ||
if (await RetryIntercept(response)) | ||
{ | ||
// Retry | ||
response = await base.SendAsync(request, cancellationToken); | ||
} | ||
} | ||
|
||
return response; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using HttpParamsUtility; | ||
using MercadoLibre.SDK.Meta; | ||
|
||
namespace MercadoLibre.SDK | ||
{ | ||
/// <summary> | ||
/// Interface for the service wrapping access to the Mercado Libre REST API. | ||
/// </summary> | ||
public interface IMeliApiService | ||
{ | ||
/// <summary> | ||
/// Gets or sets the crendentials. | ||
/// </summary> | ||
/// <value> | ||
/// The crendentials. | ||
/// </value> | ||
/// <remarks> | ||
/// - Don't forget to set this before calling methods that require an API token. | ||
/// - You can subscribe to events on <see cref="MeliCredentials"/> to track when the tokens are refreshed. | ||
/// </remarks> | ||
MeliCredentials Credentials { get; set; } | ||
|
||
/// <summary> | ||
/// Generate an URL to get an access token for other users. | ||
/// </summary> | ||
/// <param name="clientId">The client identifier (meli app ID).</param> | ||
/// <param name="site">The site.</param> | ||
/// <param name="redirectUri">The call back URI redirect URL to (Mercado Libre with append ?code=YOUR_SECRET_CODE to this URL).</param> | ||
/// <returns>The authentication URL to redirect your user to.</returns> | ||
string GetAuthUrl(long clientId, MeliSite site, string redirectUri); | ||
|
||
/// <summary> | ||
/// Requests an access and refresh token from the code provided by the mercado libre callback. | ||
/// </summary> | ||
/// <param name="code">The code.</param> | ||
/// <param name="redirectUri">The redirect URI.</param> | ||
/// <returns>Return True when the operation is successful.</returns> | ||
Task<bool> AuthorizeAsync(string code, string redirectUri); | ||
|
||
/// <summary> | ||
/// Sends a GET request. | ||
/// </summary> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <returns></returns> | ||
Task<HttpResponseMessage> GetAsync(string resource, HttpParams parameters = null); | ||
|
||
/// <summary> | ||
/// Sends a GET request and deserialises the JSON response. | ||
/// </summary> | ||
/// <typeparam name="T">The class to use to deserialise the JSON response.</typeparam> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <returns></returns> | ||
Task<T> GetAsync<T>(string resource, HttpParams parameters = null); | ||
|
||
/// <summary> | ||
/// Sends a POST request. | ||
/// </summary> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <param name="content">The payload for the content of the HTTP request.</param> | ||
/// <returns></returns> | ||
Task<HttpResponseMessage> PostAsync(string resource, HttpParams parameters = null, object content = null); | ||
|
||
/// <summary> | ||
/// Sends a POST request and deserialises the JSON response. | ||
/// </summary> | ||
/// <typeparam name="T">The class to use to deserialise the JSON response.</typeparam> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <param name="content">The payload for the content of the HTTP request.</param> | ||
/// <returns></returns> | ||
Task<T> PostAsync<T>(string resource, HttpParams parameters = null, object content = null); | ||
|
||
/// <summary> | ||
/// Sends a PUT request. | ||
/// </summary> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <param name="content">The content.</param> | ||
/// <returns></returns> | ||
Task<HttpResponseMessage> PutAsync(string resource, HttpParams parameters = null, object content = null); | ||
|
||
/// <summary> | ||
/// Sends a PUT request and deserialises the JSON response. | ||
/// </summary> | ||
/// <typeparam name="T">The class to use to deserialise the JSON response.</typeparam> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <param name="content">The content.</param> | ||
/// <returns></returns> | ||
Task<T> PutAsync<T>(string resource, HttpParams parameters = null, object content = null); | ||
|
||
/// <summary> | ||
/// Sends a DELETE request. | ||
/// </summary> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <returns></returns> | ||
Task<HttpResponseMessage> DeleteAsync(string resource, HttpParams parameters = null); | ||
|
||
/// <summary> | ||
/// Sends a DELETE request and deserialises the JSON response. | ||
/// </summary> | ||
/// <typeparam name="T">The class to use to deserialise the JSON response.</typeparam> | ||
/// <param name="resource">The resource.</param> | ||
/// <param name="parameters">The parameters.</param> | ||
/// <returns></returns> | ||
Task<T> DeleteAsync<T>(string resource, HttpParams parameters = null); | ||
} | ||
} |
Oops, something went wrong.