Skip to content

Commit

Permalink
Merge pull request #12 from MindscapeHQ/requester-options
Browse files Browse the repository at this point in the history
Support for Authentication and Proxy setting in HttpClient

Closes #11
  • Loading branch information
Jeremy Norman authored Mar 29, 2019
2 parents 3c0445e + bb58d7a commit c92f8e8
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Raygun.Druid4Net.IntegrationTests/App.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="druid.broker.host" value="http://localhost"/>
<add key="druid.broker.host" value="http://localhost:8082"/>
</appSettings>
</configuration>
7 changes: 6 additions & 1 deletion Raygun.Druid4Net.IntegrationTests/Queries/TestQueryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
11 changes: 11 additions & 0 deletions Raygun.Druid4Net/Configuration/BasicAuthenticationCredentials.cs
Original file line number Diff line number Diff line change
@@ -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}";
}
}
23 changes: 23 additions & 0 deletions Raygun.Druid4Net/Configuration/ConfigurationOptions.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
15 changes: 15 additions & 0 deletions Raygun.Druid4Net/Configuration/ProxySettings.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
30 changes: 21 additions & 9 deletions Raygun.Druid4Net/DruidClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<TopNResult<TResponse>> TopN<TResponse>(Func<ITopNQueryDescriptor, ITopNQueryDescriptor> selector) where TResponse : class
Expand All @@ -23,7 +35,7 @@ public async Task<IQueryResponse<TopNResult<TResponse>>> TopNAsync<TResponse>(Fu
{
var request = selector(new TopNQueryDescriptor()).Generate();

var result = await ExecuteQueryAsync<TopNResult<TResponse>, TopNRequestData>(_apiEndpoint, request);
var result = await ExecuteQueryAsync<TopNResult<TResponse>, TopNRequestData>(_configurationOptions.QueryApiEndpoint, request);

return result;
}
Expand All @@ -37,7 +49,7 @@ public async Task<IQueryResponse<GroupByResult<TResponse>>> GroupByAsync<TRespon
{
var request = selector(new GroupByQueryDescriptor()).Generate();

var result = await ExecuteQueryAsync<GroupByResult<TResponse>, GroupByRequestData>(_apiEndpoint, request);
var result = await ExecuteQueryAsync<GroupByResult<TResponse>, GroupByRequestData>(_configurationOptions.QueryApiEndpoint, request);

return result;
}
Expand All @@ -51,7 +63,7 @@ public async Task<IQueryResponse<TimeseriesResult<TResponse>>> TimeseriesAsync<T
{
var request = selector(new TimeseriesQueryDescriptor()).Generate();

var result = await ExecuteQueryAsync<TimeseriesResult<TResponse>, TimeseriesRequestData>(_apiEndpoint, request);
var result = await ExecuteQueryAsync<TimeseriesResult<TResponse>, TimeseriesRequestData>(_configurationOptions.QueryApiEndpoint, request);

return result;
}
Expand All @@ -65,7 +77,7 @@ public async Task<IQueryResponse<SelectResult<TResponse>>> SelectAsync<TResponse
{
var request = selector(new SelectQueryDescriptor()).Generate();

var result = await ExecuteQueryAsync<SelectResult<TResponse>, SelectRequestData>(_apiEndpoint, request);
var result = await ExecuteQueryAsync<SelectResult<TResponse>, SelectRequestData>(_configurationOptions.QueryApiEndpoint, request);

return result;
}
Expand All @@ -79,7 +91,7 @@ public async Task<IQueryResponse<SearchResult>> SearchAsync(Func<ISearchQueryDes
{
var request = selector(new SearchQueryDescriptor()).Generate();

var result = await ExecuteQueryAsync<SearchResult, SearchRequestData>(_apiEndpoint, request);
var result = await ExecuteQueryAsync<SearchResult, SearchRequestData>(_configurationOptions.QueryApiEndpoint, request);

return result;
}
Expand Down
11 changes: 11 additions & 0 deletions Raygun.Druid4Net/Query/IRequester.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Threading.Tasks;

namespace Raygun.Druid4Net
{
public interface IRequester
{
Task<IQueryResponse<TResponse>> PostAsync<TResponse, TRequest>(string endpoint, IDruidRequest<TRequest> request)
where TResponse : class
where TRequest : QueryRequestData;
}
}
59 changes: 54 additions & 5 deletions Raygun.Druid4Net/Query/Requester.cs
Original file line number Diff line number Diff line change
@@ -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<IQueryResponse<TResponse>> PostAsync<TResponse, TRequest>(string endpoint, IDruidRequest<TRequest> request)
Expand Down
11 changes: 5 additions & 6 deletions Raygun.Druid4Net/Raygun.Druid4Net.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.6;netstandard2.0;net45;</TargetFrameworks>
<TargetFrameworks>net45;netstandard1.6;netstandard2.0</TargetFrameworks>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>
<!-- NuGet Options -->
Expand All @@ -20,22 +20,21 @@
<PackageIconUrl>https://app.raygun.com/Content/Images/nuget-icon.png</PackageIconUrl>
<PackageTags>druid;druidio</PackageTags>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>NETCORE;NETSTANDARD;NETSTANDARD2_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.6'">
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.6'">
<DefineConstants>NETCORE;NETSTANDARD;NETSTANDARD1_6</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net45'">
<PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
<DefineConstants>NET45;NETFULL</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>

0 comments on commit c92f8e8

Please sign in to comment.