using System.Net.Http; using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Net; namespace SpotifyAPI.Web.Http { public class APIConnector : IAPIConnector { private readonly Uri _baseAddress; private readonly IAuthenticator _authenticator; private readonly IJSONSerializer _jsonSerializer; private readonly IHTTPClient _httpClient; public APIConnector(Uri baseAddress, IAuthenticator authenticator) : this(baseAddress, authenticator, new NewtonsoftJSONSerializer(), new NetHttpClient()) { } public APIConnector(Uri baseAddress, IAuthenticator authenticator, IJSONSerializer jsonSerializer, IHTTPClient httpClient) { _baseAddress = baseAddress; _authenticator = authenticator; _jsonSerializer = jsonSerializer; _httpClient = httpClient; } public Task Delete(Uri uri) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Delete); } public Task Delete(Uri uri, IDictionary parameters) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Delete, parameters); } public Task Delete(Uri uri, IDictionary parameters, object body) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Delete, parameters, body); } public Task Get(Uri uri) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Get); } public Task Get(Uri uri, IDictionary parameters) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Get, parameters); } public Task Post(Uri uri) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Post); } public Task Post(Uri uri, IDictionary parameters) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Post, parameters); } public Task Post(Uri uri, IDictionary parameters, object body) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Get, parameters, body); } public Task Put(Uri uri) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Put); } public Task Put(Uri uri, IDictionary parameters) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Put, parameters); } public Task Put(Uri uri, IDictionary parameters, object body) { Ensure.ArgumentNotNull(uri, nameof(uri)); return SendAPIRequest(uri, HttpMethod.Put, parameters, body); } public void SetRequestTimeout(TimeSpan timeout) { _httpClient.SetRequestTimeout(timeout); } private async Task SendAPIRequest( Uri uri, HttpMethod method, IDictionary parameters = null, object body = null ) { Ensure.ArgumentNotNull(uri, nameof(uri)); Ensure.ArgumentNotNull(method, nameof(method)); var request = new Request { BaseAddress = _baseAddress, Parameters = parameters, Endpoint = uri, Method = method, Body = body }; _jsonSerializer.SerializeRequest(request); await _authenticator.Apply(request).ConfigureAwait(false); IResponse response = await _httpClient.DoRequest(request).ConfigureAwait(false); ProcessErrors(response); IAPIResponse apiResponse = _jsonSerializer.DeserializeResponse(response); return apiResponse.Body; } private void ProcessErrors(IResponse response) { Ensure.ArgumentNotNull(response, nameof(response)); if ((int)response.StatusCode >= 200 && (int)response.StatusCode < 400) { return; } throw response.StatusCode switch { HttpStatusCode.Unauthorized => new APIUnauthorizedException(response), _ => new APIException(response), }; } } }