2018-09-21 13:42:52 +01:00
|
|
|
using Newtonsoft.Json;
|
2015-10-16 23:44:35 +01:00
|
|
|
using System;
|
2015-07-07 17:11:11 +01:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Net;
|
2017-05-31 16:25:56 +01:00
|
|
|
using System.Net.Http;
|
|
|
|
using System.Net.Http.Headers;
|
2015-07-07 17:11:11 +01:00
|
|
|
using System.Text;
|
2015-11-05 20:20:22 +00:00
|
|
|
using System.Threading.Tasks;
|
2016-07-07 20:23:36 +01:00
|
|
|
using SpotifyAPI.Web.Models;
|
2015-07-07 17:11:11 +01:00
|
|
|
|
|
|
|
namespace SpotifyAPI.Web
|
|
|
|
{
|
|
|
|
internal class SpotifyWebClient : IClient
|
|
|
|
{
|
|
|
|
public JsonSerializerSettings JsonSettings { get; set; }
|
|
|
|
private readonly Encoding _encoding = Encoding.UTF8;
|
2018-09-17 13:44:22 +01:00
|
|
|
private readonly HttpClient _client;
|
|
|
|
|
2018-12-22 20:40:08 +00:00
|
|
|
private const string UnknownErrorJson = "{\"error\": { \"status\": 0, \"message\": \"SpotifyAPI.Web - Unkown Spotify Error\" }}";
|
|
|
|
|
2018-09-17 13:44:22 +01:00
|
|
|
public SpotifyWebClient(ProxyConfig proxyConfig = null)
|
|
|
|
{
|
|
|
|
HttpClientHandler clientHandler = CreateClientHandler(proxyConfig);
|
|
|
|
_client = new HttpClient(clientHandler);
|
|
|
|
}
|
2015-07-07 17:11:11 +01:00
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public Tuple<ResponseInfo, string> Download(string url, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
Tuple<ResponseInfo, byte[]> raw = DownloadRaw(url, headers);
|
|
|
|
return new Tuple<ResponseInfo, string>(raw.Item1, raw.Item2.Length > 0 ? _encoding.GetString(raw.Item2) : "{}");
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public async Task<Tuple<ResponseInfo, string>> DownloadAsync(string url, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
Tuple<ResponseInfo, byte[]> raw = await DownloadRawAsync(url, headers).ConfigureAwait(false);
|
|
|
|
return new Tuple<ResponseInfo, string>(raw.Item1, raw.Item2.Length > 0 ? _encoding.GetString(raw.Item2) : "{}");
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public Tuple<ResponseInfo, byte[]> DownloadRaw(string url, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
if (headers != null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2018-10-24 22:21:13 +01:00
|
|
|
AddHeaders(headers);
|
2018-09-17 13:44:22 +01:00
|
|
|
}
|
|
|
|
using (HttpResponseMessage response = Task.Run(() => _client.GetAsync(url)).Result)
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, byte[]>(new ResponseInfo
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
StatusCode = response.StatusCode,
|
|
|
|
Headers = ConvertHeaders(response.Headers)
|
|
|
|
}, Task.Run(() => response.Content.ReadAsByteArrayAsync()).Result);
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public async Task<Tuple<ResponseInfo, byte[]>> DownloadRawAsync(string url, Dictionary<string, string> headers = null)
|
2015-11-05 20:20:22 +00:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
if (headers != null)
|
2015-11-05 20:20:22 +00:00
|
|
|
{
|
2018-10-24 22:21:13 +01:00
|
|
|
AddHeaders(headers);
|
2018-09-17 13:44:22 +01:00
|
|
|
}
|
|
|
|
using (HttpResponseMessage response = await _client.GetAsync(url).ConfigureAwait(false))
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, byte[]>(new ResponseInfo
|
2015-11-05 20:20:22 +00:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
StatusCode = response.StatusCode,
|
|
|
|
Headers = ConvertHeaders(response.Headers)
|
|
|
|
}, await response.Content.ReadAsByteArrayAsync());
|
2015-11-05 20:20:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public Tuple<ResponseInfo, T> DownloadJson<T>(string url, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
Tuple<ResponseInfo, string> response = Download(url, headers);
|
2018-12-22 20:40:08 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(response.Item2, JsonSettings));
|
|
|
|
}
|
|
|
|
catch (JsonException)
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(UnknownErrorJson, JsonSettings));
|
|
|
|
}
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public async Task<Tuple<ResponseInfo, T>> DownloadJsonAsync<T>(string url, Dictionary<string, string> headers = null)
|
2015-11-05 20:20:22 +00:00
|
|
|
{
|
2018-12-22 20:40:08 +00:00
|
|
|
Tuple<ResponseInfo, string> response = await DownloadAsync(url, headers).ConfigureAwait(false);try
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(response.Item2, JsonSettings));
|
|
|
|
}
|
|
|
|
catch (JsonException)
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(UnknownErrorJson, JsonSettings));
|
|
|
|
}
|
2015-11-05 20:20:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public Tuple<ResponseInfo, string> Upload(string url, string body, string method, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
Tuple<ResponseInfo, byte[]> data = UploadRaw(url, body, method, headers);
|
|
|
|
return new Tuple<ResponseInfo, string>(data.Item1, data.Item2.Length > 0 ? _encoding.GetString(data.Item2) : "{}");
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public async Task<Tuple<ResponseInfo, string>> UploadAsync(string url, string body, string method, Dictionary<string, string> headers = null)
|
2015-11-05 20:20:22 +00:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
Tuple<ResponseInfo, byte[]> data = await UploadRawAsync(url, body, method, headers).ConfigureAwait(false);
|
|
|
|
return new Tuple<ResponseInfo, string>(data.Item1, data.Item2.Length > 0 ? _encoding.GetString(data.Item2) : "{}");
|
2015-11-05 20:20:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public Tuple<ResponseInfo, byte[]> UploadRaw(string url, string body, string method, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
if (headers != null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2018-10-24 22:21:13 +01:00
|
|
|
AddHeaders(headers);
|
2018-09-17 13:44:22 +01:00
|
|
|
}
|
2015-07-07 17:11:11 +01:00
|
|
|
|
2018-09-17 13:44:22 +01:00
|
|
|
HttpRequestMessage message = new HttpRequestMessage(new HttpMethod(method), url)
|
|
|
|
{
|
|
|
|
Content = new StringContent(body, _encoding)
|
|
|
|
};
|
|
|
|
using (HttpResponseMessage response = Task.Run(() => _client.SendAsync(message)).Result)
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, byte[]>(new ResponseInfo
|
2015-11-05 20:20:22 +00:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
StatusCode = response.StatusCode,
|
|
|
|
Headers = ConvertHeaders(response.Headers)
|
|
|
|
}, Task.Run(() => response.Content.ReadAsByteArrayAsync()).Result);
|
2015-11-05 20:20:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public async Task<Tuple<ResponseInfo, byte[]>> UploadRawAsync(string url, string body, string method, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
if (headers != null)
|
2016-07-07 20:23:36 +01:00
|
|
|
{
|
2018-10-24 22:21:13 +01:00
|
|
|
AddHeaders(headers);
|
2018-09-17 13:44:22 +01:00
|
|
|
}
|
2015-07-07 17:11:11 +01:00
|
|
|
|
2018-09-17 13:44:22 +01:00
|
|
|
HttpRequestMessage message = new HttpRequestMessage(new HttpMethod(method), url)
|
|
|
|
{
|
|
|
|
Content = new StringContent(body, _encoding)
|
|
|
|
};
|
|
|
|
using (HttpResponseMessage response = await _client.SendAsync(message))
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, byte[]>(new ResponseInfo
|
2017-05-31 16:25:56 +01:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
StatusCode = response.StatusCode,
|
|
|
|
Headers = ConvertHeaders(response.Headers)
|
|
|
|
}, await response.Content.ReadAsByteArrayAsync());
|
2015-11-15 19:54:30 +00:00
|
|
|
}
|
2015-11-05 20:20:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public Tuple<ResponseInfo, T> UploadJson<T>(string url, string body, string method, Dictionary<string, string> headers = null)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
Tuple<ResponseInfo, string> response = Upload(url, body, method, headers);
|
2018-12-22 20:40:08 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(response.Item2, JsonSettings));
|
|
|
|
}
|
|
|
|
catch (JsonException)
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(UnknownErrorJson, JsonSettings));
|
|
|
|
}
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public async Task<Tuple<ResponseInfo, T>> UploadJsonAsync<T>(string url, string body, string method, Dictionary<string, string> headers = null)
|
2015-11-05 20:20:22 +00:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
Tuple<ResponseInfo, string> response = await UploadAsync(url, body, method, headers).ConfigureAwait(false);
|
2018-12-22 20:40:08 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(response.Item2, JsonSettings));
|
|
|
|
}
|
|
|
|
catch (JsonException)
|
|
|
|
{
|
|
|
|
return new Tuple<ResponseInfo, T>(response.Item1, JsonConvert.DeserializeObject<T>(UnknownErrorJson, JsonSettings));
|
|
|
|
}
|
2015-11-05 20:20:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
public void Dispose()
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2018-09-17 13:44:22 +01:00
|
|
|
_client.Dispose();
|
2017-05-31 16:25:56 +01:00
|
|
|
GC.SuppressFinalize(this);
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
|
2017-05-31 16:25:56 +01:00
|
|
|
private static WebHeaderCollection ConvertHeaders(HttpResponseHeaders headers)
|
2015-07-07 17:11:11 +01:00
|
|
|
{
|
2017-05-31 16:25:56 +01:00
|
|
|
WebHeaderCollection newHeaders = new WebHeaderCollection();
|
|
|
|
foreach (KeyValuePair<string, IEnumerable<string>> headerPair in headers)
|
|
|
|
{
|
|
|
|
foreach (string headerValue in headerPair.Value)
|
|
|
|
{
|
|
|
|
newHeaders.Add(headerPair.Key, headerValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newHeaders;
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
2018-03-25 18:39:19 +01:00
|
|
|
|
2018-10-24 22:21:13 +01:00
|
|
|
private void AddHeaders(Dictionary<string,string> headers)
|
|
|
|
{
|
2018-10-27 12:56:30 +01:00
|
|
|
_client.DefaultRequestHeaders.Clear();
|
2018-10-24 22:21:13 +01:00
|
|
|
foreach (KeyValuePair<string, string> headerPair in headers)
|
|
|
|
{
|
|
|
|
_client.DefaultRequestHeaders.TryAddWithoutValidation(headerPair.Key, headerPair.Value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-25 18:39:19 +01:00
|
|
|
private static HttpClientHandler CreateClientHandler(ProxyConfig proxyConfig = null)
|
|
|
|
{
|
|
|
|
HttpClientHandler clientHandler = new HttpClientHandler
|
|
|
|
{
|
|
|
|
PreAuthenticate = false,
|
|
|
|
UseDefaultCredentials = true,
|
|
|
|
UseProxy = false
|
|
|
|
};
|
|
|
|
|
2019-03-18 20:24:09 +00:00
|
|
|
if (string.IsNullOrWhiteSpace(proxyConfig?.Host)) return clientHandler;
|
|
|
|
WebProxy proxy = proxyConfig.CreateWebProxy();
|
|
|
|
clientHandler.UseProxy = true;
|
|
|
|
clientHandler.Proxy = proxy;
|
|
|
|
clientHandler.UseDefaultCredentials = proxy.UseDefaultCredentials;
|
|
|
|
clientHandler.PreAuthenticate = proxy.UseDefaultCredentials;
|
2018-03-25 18:39:19 +01:00
|
|
|
|
|
|
|
return clientHandler;
|
|
|
|
}
|
2015-07-07 17:11:11 +01:00
|
|
|
}
|
|
|
|
}
|