Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
DOTNET-202: Initial proxy support (custom and default) and HttpClient…
….CustomRequestModifier
  • Loading branch information
homiedopie committed Sep 13, 2025
commit 993ebfcdf5a7f04a6f96dcc14e4b386a2e68ce51
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,35 @@ StackifyLib.Logger.GlobalEnvironment = "";

By default the library will use the WebRequest.DefaultWebProxy. If you want to set a specific proxy server only for StackifyLib, you can do so in code OR via config.

For proxy using custom credentials:
```xml
<appSettings>
<add key="Stackify.ProxyServer" value="http://test:[email protected]:8888/" />
</appSettings>
```

For proxy using default credentials:
```xml
<appSettings>
<add key="Stackify.ProxyUseDefaultCredentials" value="false" />
</appSettings>
```

For proxy that needs to be tailor fit
```csharp
StackifyLib.Utils.HttpClient.CustomWebProxy = new WebProxy();
```

In case it need some web request intervention, a delegate has been provided to customize the http request
```csharp
StackifyLib.Utils.HttpClient.CustomRequestModifier = (request) =>
{
// Examples:
request.PreAuthenticate = true; // If proxy needs pre-authentication
request.Timeout = 30000;
};
```

If you are having problems you can get logging out of the framework by hooking in to its custom logging.

```csharp
Expand Down
10 changes: 10 additions & 0 deletions Src/StackifyLib/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ public static void LoadSettings()
{
RumKey = rumKey;
}

ProxyServer = Get("Stackify.ProxyServer", string.Empty);
var proxyUseDefaultCredentials = Get("Stackify.ProxyUseDefaultCredentials", string.Empty);
if (string.IsNullOrWhiteSpace(proxyUseDefaultCredentials) == false)
{
ProxyUseDefaultCredentials = proxyUseDefaultCredentials.Equals(bool.TrueString, StringComparison.CurrentCultureIgnoreCase);
}
}
catch (Exception ex)
{
Expand Down Expand Up @@ -217,6 +224,9 @@ public static void LoadSettings()

public static string RumKey { get; set; }

public static string ProxyServer { get; set; }
public static bool? ProxyUseDefaultCredentials { get; set; } = false;


/// <summary>
/// Attempts to fetch a setting value given the key.
Expand Down
11 changes: 5 additions & 6 deletions Src/StackifyLib/StackifyLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<PropertyGroup>
<AssemblyTitle>Stackify API</AssemblyTitle>
<VersionPrefix>2.2.17</VersionPrefix>
<VersionSuffix></VersionSuffix>
<VersionPrefix>2.2.18</VersionPrefix>
<VersionSuffix>beta</VersionSuffix>
<TargetFrameworks>netstandard2.0;net40;net45;net451;net452;net46;net461;net462</TargetFrameworks>
<AssemblyName>StackifyLib</AssemblyName>
<PackageId>StackifyLib</PackageId>
Expand All @@ -14,15 +14,15 @@
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<Version>2.2.17</Version>
<Version>2.2.18-beta</Version>
<Authors>StackifyLib</Authors>
<PackageProjectUrl>https://github.com/stackify/stackify-api-dotnet</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/stackify/stackify-api-dotnet/blob/master/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/stackify/stackify-api-dotnet</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageIconUrl>https://stackify.com/wp-content/uploads/2017/02/stk.png</PackageIconUrl>
<AssemblyVersion>2.2.17.0</AssemblyVersion>
<FileVersion>2.2.17.0</FileVersion>
<AssemblyVersion>2.2.18.0</AssemblyVersion>
<FileVersion>2.2.18.0</FileVersion>
<PackageReleaseNotes>Remove default internal file logger</PackageReleaseNotes>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
Expand Down Expand Up @@ -57,5 +57,4 @@
<PropertyGroup Condition=" '$(TargetFramework)' == 'net40' OR '$(TargetFramework)' == 'net45' OR '$(TargetFramework)' == 'net451' OR '$(TargetFramework)' == 'net452' OR '$(TargetFramework)' == 'net46' ">
<DefineConstants>NETFULL</DefineConstants>
</PropertyGroup>

</Project>
90 changes: 60 additions & 30 deletions Src/StackifyLib/Utils/HttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ public class AppIdentityInfo

public class HttpClient
{
public static IWebProxy CustomWebProxy = null;
public static IWebProxy CustomWebProxy = null;
public static Action<HttpWebRequest> CustomRequestModifier = null;
public static bool IsUnitTest = false;

public string BaseAPIUrl { get; private set; }

Expand Down Expand Up @@ -121,39 +123,31 @@ public HttpClient(string apiKey, string apiUrl)
BaseAPIUrl += "/";
}

#if NETFULL
public static void LoadWebProxyConfig()
{
try
{
string val = Config.Get("Stackify.ProxyServer");

string val = Config.ProxyServer;
if (!string.IsNullOrEmpty(val))
{

StackifyAPILogger.Log("Setting proxy server based on override config", true);

var uri = new Uri(val);

var proxy = new WebProxy(uri, false);
WebProxy proxy = new WebProxy(uri);

if (!string.IsNullOrEmpty(uri.UserInfo) && uri.UserInfo.Contains(":"))
{
string[] pieces = uri.UserInfo.Split(':');

proxy.Credentials = new NetworkCredential(pieces[0], pieces[1]);
proxy = new WebProxy(uri)
{
Credentials = new NetworkCredential(pieces[0], pieces[1])
};
}
else
{

string settingUseDefault = Config.Get("Stackify.ProxyUseDefaultCredentials");

bool useDefault;

if (!string.IsNullOrEmpty(settingUseDefault) && bool.TryParse(settingUseDefault, out useDefault))
bool? settingUseDefault = Config.ProxyUseDefaultCredentials;
if (settingUseDefault.HasValue && settingUseDefault.Value)
{
//will make it use the user of the running windows service
proxy.UseDefaultCredentials = useDefault;
proxy.UseDefaultCredentials = true;
}
}
CustomWebProxy = proxy;
Expand All @@ -164,7 +158,6 @@ public static void LoadWebProxyConfig()
StackifyAPILogger.Log("Error setting default web proxy " + ex.Message, true);
}
}
#endif

/// <summary>
/// This method does some throttling when errors happen to control when it should try again. Error backoff logic
Expand Down Expand Up @@ -614,23 +607,40 @@ private HttpWebRequest BuildJsonRequest(string url, string jsonData, bool compre
request.Headers[HttpRequestHeader.UserAgent] = "StackifyLib-" + _version;
#endif

request.Headers["X-Stackify-Key"] = this.APIKey;
request.Headers.Add("X-Stackify-Key", this.APIKey);
request.ContentType = "application/json";

//if (HttpClient.CustomWebProxy != null)
//{
if (CustomWebProxy != null)
{
request.Proxy = CustomWebProxy;
}

// request.Proxy = HttpClient.CustomWebProxy;
//}
if (CustomRequestModifier != null)
{
try
{
CustomRequestModifier(request);
}
catch (Exception ex)
{
StackifyAPILogger.Log($"Failed to set CustomRequestModifier - Message: {ex.Message}", true);
}
}

if (!string.IsNullOrEmpty(jsonData) && compress)
{
request.Method = "POST";
request.Headers[HttpRequestHeader.ContentEncoding] = "gzip";
request.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip");

if (IsUnitTest)
{
return request;
}

byte[] payload = Encoding.UTF8.GetBytes(jsonData);

#if NETFULL
request.ContentLength = payload.Length;
using (Stream postStream = request.GetRequestStream())
#else
using (Stream postStream = request.GetRequestStreamAsync().GetAwaiter().GetResult())
Expand All @@ -647,8 +657,12 @@ private HttpWebRequest BuildJsonRequest(string url, string jsonData, bool compre
{
request.Method = "POST";

byte[] payload = Encoding.UTF8.GetBytes(jsonData);
if (IsUnitTest)
{
return request;
}

byte[] payload = Encoding.UTF8.GetBytes(jsonData);
#if NETFULL
request.ContentLength= payload.Length;
using (Stream stream = request.GetRequestStream())
Expand Down Expand Up @@ -697,14 +711,30 @@ private HttpWebRequest BuildPOSTRequest(string url, string postdata)
request.Headers[HttpRequestHeader.ContentLength] = "0";
#endif

//if (HttpClient.CustomWebProxy != null)
//{
// request.Proxy = HttpClient.CustomWebProxy;
//}
if (HttpClient.CustomWebProxy != null)
{
request.Proxy = HttpClient.CustomWebProxy;
}

if (CustomRequestModifier != null)
{
try
{
CustomRequestModifier(request);
}
catch (Exception ex)
{
StackifyAPILogger.Log($"Failed to set CustomRequestModifier - Message: {ex.Message}", true);
}
}

request.Method = "POST";

if (IsUnitTest)
{
return request;
}

if (!String.IsNullOrEmpty(postdata))
{
byte[] payload = Encoding.UTF8.GetBytes(postdata);
Expand Down
3 changes: 2 additions & 1 deletion test/StackifyLib.UnitTests/StackifyLib.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
<TargetFrameworks>net6.0;net462</TargetFrameworks>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<IsUnitTestMode>true</IsUnitTestMode>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<DefineConstants>NETCORE</DefineConstants>
</PropertyGroup>
Expand All @@ -13,7 +15,6 @@
<DefineConstants>NETFULL</DefineConstants>
</PropertyGroup>


<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.5.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
Expand Down
Loading
Loading