diff --git a/Raygun.Druid4Net.IntegrationTests/App.config b/Raygun.Druid4Net.IntegrationTests/App.config index 7eacbbf..9dc5a3f 100644 --- a/Raygun.Druid4Net.IntegrationTests/App.config +++ b/Raygun.Druid4Net.IntegrationTests/App.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/Raygun.Druid4Net.IntegrationTests/Queries/TestQueryBase.cs b/Raygun.Druid4Net.IntegrationTests/Queries/TestQueryBase.cs index c8f9918..a2e98a6 100644 --- a/Raygun.Druid4Net.IntegrationTests/Queries/TestQueryBase.cs +++ b/Raygun.Druid4Net.IntegrationTests/Queries/TestQueryBase.cs @@ -12,7 +12,12 @@ public abstract class TestQueryBase protected TestQueryBase() { - DruidClient = new DruidClient(new JilSerializer(), ConfigurationManager.AppSettings["druid.broker.host"]); + var options = new ConfigurationOptions() + { + JsonSerializer = new JilSerializer(), + QueryApiBaseAddress = new Uri(ConfigurationManager.AppSettings["druid.broker.host"]) + }; + DruidClient = new DruidClient(options); } } } \ No newline at end of file diff --git a/Raygun.Druid4Net/Configuration/BasicAuthenticationCredentials.cs b/Raygun.Druid4Net/Configuration/BasicAuthenticationCredentials.cs new file mode 100644 index 0000000..889c517 --- /dev/null +++ b/Raygun.Druid4Net/Configuration/BasicAuthenticationCredentials.cs @@ -0,0 +1,11 @@ +namespace Raygun.Druid4Net +{ + public class BasicAuthenticationCredentials + { + public string Password { get; set; } + + public string Username { get; set; } + + public override string ToString() => $"{Username}:{Password}"; + } +} \ No newline at end of file diff --git a/Raygun.Druid4Net/Configuration/ConfigurationOptions.cs b/Raygun.Druid4Net/Configuration/ConfigurationOptions.cs new file mode 100644 index 0000000..cf38700 --- /dev/null +++ b/Raygun.Druid4Net/Configuration/ConfigurationOptions.cs @@ -0,0 +1,23 @@ +using System; + +namespace Raygun.Druid4Net +{ + public class ConfigurationOptions + { + public ConfigurationOptions() + { + QueryApiBaseAddress = new Uri("http://localhost:8082"); + QueryApiEndpoint = "druid/v2"; + } + + public Uri QueryApiBaseAddress { get; set; } + + public string QueryApiEndpoint { get; set; } + + public IJsonSerializer JsonSerializer { get; set; } + + public ProxySettings ProxySettings { get; set; } + + public BasicAuthenticationCredentials BasicAuthenticationCredentials { get; set; } + } +} \ No newline at end of file diff --git a/Raygun.Druid4Net/Configuration/ProxySettings.cs b/Raygun.Druid4Net/Configuration/ProxySettings.cs new file mode 100644 index 0000000..8fc6e25 --- /dev/null +++ b/Raygun.Druid4Net/Configuration/ProxySettings.cs @@ -0,0 +1,15 @@ +using System; + +namespace Raygun.Druid4Net +{ + public class ProxySettings + { + public Uri Address { get; set; } + + public bool BypassOnLocal { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + } +} \ No newline at end of file diff --git a/Raygun.Druid4Net/DruidClient.cs b/Raygun.Druid4Net/DruidClient.cs index 86d88f4..1739b6b 100644 --- a/Raygun.Druid4Net/DruidClient.cs +++ b/Raygun.Druid4Net/DruidClient.cs @@ -5,13 +5,25 @@ namespace Raygun.Druid4Net { public class DruidClient : IDruidClient { - private readonly Requester _requester; - private readonly string _apiEndpoint; + private readonly IRequester _requester; + private readonly ConfigurationOptions _configurationOptions; + [Obsolete("Use the constructor that takes a ConfigurationOptions instance")] public DruidClient(IJsonSerializer jsonSerializer, string hostName, int port = 8082, string apiEndpoint = "druid/v2") { - _requester = new Requester(jsonSerializer, hostName, port); - _apiEndpoint = apiEndpoint; + _configurationOptions = new ConfigurationOptions + { + JsonSerializer = jsonSerializer, + QueryApiBaseAddress = new Uri($"{hostName}:{port}"), + QueryApiEndpoint = apiEndpoint, + }; + _requester = new Requester(_configurationOptions); + } + + public DruidClient(ConfigurationOptions options, IRequester requester = null) + { + _configurationOptions = options; + _requester = requester ?? new Requester(options); } public IQueryResponse> TopN(Func selector) where TResponse : class @@ -23,7 +35,7 @@ public async Task>> TopNAsync(Fu { var request = selector(new TopNQueryDescriptor()).Generate(); - var result = await ExecuteQueryAsync, TopNRequestData>(_apiEndpoint, request); + var result = await ExecuteQueryAsync, TopNRequestData>(_configurationOptions.QueryApiEndpoint, request); return result; } @@ -37,7 +49,7 @@ public async Task>> GroupByAsync, GroupByRequestData>(_apiEndpoint, request); + var result = await ExecuteQueryAsync, GroupByRequestData>(_configurationOptions.QueryApiEndpoint, request); return result; } @@ -51,7 +63,7 @@ public async Task>> TimeseriesAsync, TimeseriesRequestData>(_apiEndpoint, request); + var result = await ExecuteQueryAsync, TimeseriesRequestData>(_configurationOptions.QueryApiEndpoint, request); return result; } @@ -65,7 +77,7 @@ public async Task>> SelectAsync, SelectRequestData>(_apiEndpoint, request); + var result = await ExecuteQueryAsync, SelectRequestData>(_configurationOptions.QueryApiEndpoint, request); return result; } @@ -79,7 +91,7 @@ public async Task> SearchAsync(Func(_apiEndpoint, request); + var result = await ExecuteQueryAsync(_configurationOptions.QueryApiEndpoint, request); return result; } diff --git a/Raygun.Druid4Net/Query/IRequester.cs b/Raygun.Druid4Net/Query/IRequester.cs new file mode 100644 index 0000000..374725e --- /dev/null +++ b/Raygun.Druid4Net/Query/IRequester.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace Raygun.Druid4Net +{ + public interface IRequester + { + Task> PostAsync(string endpoint, IDruidRequest request) + where TResponse : class + where TRequest : QueryRequestData; + } +} \ No newline at end of file diff --git a/Raygun.Druid4Net/Query/Requester.cs b/Raygun.Druid4Net/Query/Requester.cs index d6410b5..2878088 100644 --- a/Raygun.Druid4Net/Query/Requester.cs +++ b/Raygun.Druid4Net/Query/Requester.cs @@ -1,20 +1,69 @@ using System; +using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; namespace Raygun.Druid4Net { - public class Requester + public class Requester : IRequester { private readonly IJsonSerializer _json; private readonly HttpClient _client; - public Requester(IJsonSerializer json, string host, int port) + public Requester(ConfigurationOptions options) { - _json = json; - _client = new HttpClient(); - _client.BaseAddress = new Uri($"{host}:{port}"); + _json = options.JsonSerializer; + _client = CreateClient(options); + + ConfigureClientAuthentication(_client, options); + } + + private void ConfigureClientAuthentication(HttpClient client, ConfigurationOptions options) + { + if (options.BasicAuthenticationCredentials != null && !string.IsNullOrEmpty(options.BasicAuthenticationCredentials.ToString())) + { + var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(options.BasicAuthenticationCredentials.ToString())); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials); + } + } + + private HttpClient CreateClient(ConfigurationOptions options) + { + var client = options.ProxySettings != null ? CreateClientWithProxyServer(options) : new HttpClient(); + client.BaseAddress = options.QueryApiBaseAddress; + return client; + } + + private HttpClient CreateClientWithProxyServer(ConfigurationOptions options) + { +#if (NETSTANDARD1_6) + var httpClientHandler = new HttpClientHandler + { + UseProxy = true + }; +#else + var webProxy = new WebProxy + { + Address = options.ProxySettings.Address, + BypassProxyOnLocal = options.ProxySettings.BypassOnLocal + }; + + if (!string.IsNullOrEmpty(options.ProxySettings.Username) && !string.IsNullOrEmpty(options.ProxySettings.Password)) + { + webProxy.UseDefaultCredentials = false; + webProxy.Credentials = new NetworkCredential(options.ProxySettings.Username, options.ProxySettings.Password); + } + + var httpClientHandler = new HttpClientHandler + { + UseProxy = true, + Proxy = webProxy + }; +#endif + + return new HttpClient(httpClientHandler, true); } public async Task> PostAsync(string endpoint, IDruidRequest request) diff --git a/Raygun.Druid4Net/Raygun.Druid4Net.csproj b/Raygun.Druid4Net/Raygun.Druid4Net.csproj index 5fa9270..672e4ff 100644 --- a/Raygun.Druid4Net/Raygun.Druid4Net.csproj +++ b/Raygun.Druid4Net/Raygun.Druid4Net.csproj @@ -1,6 +1,6 @@  - netstandard1.6;netstandard2.0;net45; + net45;netstandard1.6;netstandard2.0 true @@ -20,22 +20,21 @@ https://app.raygun.com/Content/Images/nuget-icon.png druid;druidio - + NETCORE;NETSTANDARD;NETSTANDARD2_0 - + NETCORE;NETSTANDARD;NETSTANDARD1_6 - + NET45;NETFULL - + - \ No newline at end of file