Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

Commit 5e1841f

Browse files
authored
Merge pull request #390 from justcoding121/develop
merge to beta (again)
2 parents b27ba8c + fa0d9f2 commit 5e1841f

33 files changed

+749
-644
lines changed

Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Net.Security;
66
using System.Threading.Tasks;
77
using Titanium.Web.Proxy.EventArguments;
8+
using Titanium.Web.Proxy.Exceptions;
89
using Titanium.Web.Proxy.Helpers;
910
using Titanium.Web.Proxy.Http;
1011
using Titanium.Web.Proxy.Models;
@@ -13,6 +14,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
1314
{
1415
public class ProxyTestController
1516
{
17+
private readonly object lockObj = new object();
18+
1619
private readonly ProxyServer proxyServer;
1720
private ExplicitProxyEndPoint explicitEndPoint;
1821

@@ -33,11 +36,28 @@ public ProxyTestController()
3336

3437
//generate root certificate without storing it in file system
3538
//proxyServer.CertificateManager.CreateRootCertificate(false);
36-
39+
3740
//proxyServer.CertificateManager.TrustRootCertificate();
3841
//proxyServer.CertificateManager.TrustRootCertificateAsAdmin();
3942

40-
proxyServer.ExceptionFunc = exception => Console.WriteLine(exception.Message);
43+
proxyServer.ExceptionFunc = exception =>
44+
{
45+
lock (lockObj)
46+
{
47+
var color = Console.ForegroundColor;
48+
Console.ForegroundColor = ConsoleColor.Red;
49+
if (exception is ProxyHttpException phex)
50+
{
51+
Console.WriteLine(exception.Message + ": " + phex.InnerException?.Message);
52+
}
53+
else
54+
{
55+
Console.WriteLine(exception.Message);
56+
}
57+
58+
Console.ForegroundColor = color;
59+
}
60+
};
4161
proxyServer.ForwardToUpstreamGateway = true;
4262
proxyServer.CertificateManager.SaveFakeCertificates = true;
4363
//optionally set the Certificate Engine
@@ -52,20 +72,20 @@ public void StartProxy()
5272
{
5373
proxyServer.BeforeRequest += OnRequest;
5474
proxyServer.BeforeResponse += OnResponse;
55-
75+
5676
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
5777
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
5878

5979
//proxyServer.EnableWinAuth = true;
6080

6181
explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
6282
{
63-
//You can set only one of the ExcludedHttpsHostNameRegex and IncludedHttpsHostNameRegex properties, otherwise ArgumentException will be thrown
83+
//You can set only one of the ExcludedHttpsHostNameRegex and IncludedHttpsHostNameRegex properties, otherwise ArgumentException will be thrown
6484

65-
//Use self-issued generic certificate on all https requests
66-
//Optimizes performance by not creating a certificate for each https-enabled domain
67-
//Useful when certificate trust is not required by proxy clients
68-
//GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
85+
//Use self-issued generic certificate on all https requests
86+
//Optimizes performance by not creating a certificate for each https-enabled domain
87+
//Useful when certificate trust is not required by proxy clients
88+
//GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
6989
};
7090

7191
//Fired when a CONNECT request is received
@@ -125,7 +145,7 @@ public void Stop()
125145
private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
126146
{
127147
string hostname = e.WebSession.Request.RequestUri.Host;
128-
Console.WriteLine("Tunnel to: " + hostname);
148+
WriteToConsole("Tunnel to: " + hostname);
129149

130150
if (hostname.Contains("dropbox.com"))
131151
{
@@ -143,8 +163,8 @@ private async Task OnBeforeTunnelConnectResponse(object sender, TunnelConnectSes
143163
//intecept & cancel redirect or update requests
144164
private async Task OnRequest(object sender, SessionEventArgs e)
145165
{
146-
Console.WriteLine("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
147-
Console.WriteLine(e.WebSession.Request.Url);
166+
WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
167+
WriteToConsole(e.WebSession.Request.Url);
148168

149169
//read request headers
150170
requestHeaderHistory[e.Id] = e.WebSession.Request.Headers;
@@ -192,16 +212,16 @@ private async Task OnRequest(object sender, SessionEventArgs e)
192212
private void MultipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e)
193213
{
194214
var session = (SessionEventArgs)sender;
195-
Console.WriteLine("Multipart form data headers:");
215+
WriteToConsole("Multipart form data headers:");
196216
foreach (var header in e.Headers)
197217
{
198-
Console.WriteLine(header);
218+
WriteToConsole(header.ToString());
199219
}
200220
}
201221

202222
private async Task OnResponse(object sender, SessionEventArgs e)
203223
{
204-
Console.WriteLine("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);
224+
WriteToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);
205225

206226
//if (requestBodyHistory.ContainsKey(e.Id))
207227
//{
@@ -213,7 +233,7 @@ private async Task OnResponse(object sender, SessionEventArgs e)
213233
//responseHeaderHistory[e.Id] = e.WebSession.Response.Headers;
214234

215235
//// print out process id of current session
216-
////Console.WriteLine($"PID: {e.WebSession.ProcessId.Value}");
236+
////WriteToConsole($"PID: {e.WebSession.ProcessId.Value}");
217237

218238
////if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
219239
//if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST")
@@ -259,5 +279,13 @@ public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs
259279

260280
return Task.FromResult(0);
261281
}
282+
283+
private void WriteToConsole(string message)
284+
{
285+
lock (lockObj)
286+
{
287+
Console.WriteLine(message);
288+
}
289+
}
262290
}
263291
}

Examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.ObjectModel;
44
using System.Linq;
55
using System.Net;
6+
using System.Text;
67
using System.Threading.Tasks;
78
using System.Windows;
89
using System.Windows.Controls;
@@ -102,6 +103,7 @@ public MainWindow()
102103

103104
proxyServer.BeforeRequest += ProxyServer_BeforeRequest;
104105
proxyServer.BeforeResponse += ProxyServer_BeforeResponse;
106+
proxyServer.AfterResponse += ProxyServer_AfterResponse;
105107
explicitEndPoint.BeforeTunnelConnectRequest += ProxyServer_BeforeTunnelConnectRequest;
106108
explicitEndPoint.BeforeTunnelConnectResponse += ProxyServer_BeforeTunnelConnectResponse;
107109
proxyServer.ClientConnectionCountChanged += delegate { Dispatcher.Invoke(() => { ClientConnectionCount = proxyServer.ClientConnectionCount; }); };
@@ -179,6 +181,17 @@ await Dispatcher.InvokeAsync(() =>
179181
}
180182
}
181183

184+
private async Task ProxyServer_AfterResponse(object sender, SessionEventArgs e)
185+
{
186+
await Dispatcher.InvokeAsync(() =>
187+
{
188+
if (sessionDictionary.TryGetValue(e.WebSession, out var item))
189+
{
190+
item.Exception = e.Exception;
191+
}
192+
});
193+
}
194+
182195
private SessionListItem AddSession(SessionEventArgs e)
183196
{
184197
var item = CreateSessionListItem(e);
@@ -255,9 +268,12 @@ private void SelectedSessionChanged()
255268
}
256269

257270
//string hexStr = string.Join(" ", data.Select(x => x.ToString("X2")));
258-
TextBoxRequest.Text = request.HeaderText + request.Encoding.GetString(data) +
259-
(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null) +
260-
(request as ConnectRequest)?.ClientHelloInfo;
271+
var sb = new StringBuilder();
272+
sb.Append(request.HeaderText);
273+
sb.Append(request.Encoding.GetString(data));
274+
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
275+
sb.Append((request as ConnectRequest)?.ClientHelloInfo);
276+
TextBoxRequest.Text = sb.ToString();
261277

262278
var response = session.Response;
263279
data = (response.IsBodyRead ? response.Body : null) ?? new byte[0];
@@ -268,9 +284,18 @@ private void SelectedSessionChanged()
268284
}
269285

270286
//hexStr = string.Join(" ", data.Select(x => x.ToString("X2")));
271-
TextBoxResponse.Text = session.Response.HeaderText + session.Response.Encoding.GetString(data) +
272-
(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null) +
273-
(session.Response as ConnectResponse)?.ServerHelloInfo;
287+
sb = new StringBuilder();
288+
sb.Append(response.HeaderText);
289+
sb.Append(response.Encoding.GetString(data));
290+
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
291+
sb.Append((response as ConnectResponse)?.ServerHelloInfo);
292+
if (SelectedSession.Exception != null)
293+
{
294+
sb.Append(Environment.NewLine);
295+
sb.Append(SelectedSession.Exception);
296+
}
297+
298+
TextBoxResponse.Text = sb.ToString();
274299
}
275300
}
276301
}

Examples/Titanium.Web.Proxy.Examples.Wpf/SessionListItem.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class SessionListItem : INotifyPropertyChanged
1717
private string process;
1818
private long receivedDataCount;
1919
private long sentDataCount;
20+
private Exception exception;
2021

2122
public int Number { get; set; }
2223

@@ -72,6 +73,12 @@ public long SentDataCount
7273
set => SetField(ref sentDataCount, value);
7374
}
7475

76+
public Exception Exception
77+
{
78+
get => exception;
79+
set => SetField(ref exception, value);
80+
}
81+
7582
public event PropertyChangedEventHandler PropertyChanged;
7683

7784
protected void SetField<T>(ref T field, T value,[CallerMemberName] string propertyName = null)

Examples/Titanium.Web.Proxy.Examples.Wpf/Titanium.Web.Proxy.Examples.Wpf.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
<WarningLevel>4</WarningLevel>
5252
</PropertyGroup>
5353
<ItemGroup>
54-
<Reference Include="StreamExtended, Version=1.0.138.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
55-
<HintPath>..\..\packages\StreamExtended.1.0.138-beta\lib\net45\StreamExtended.dll</HintPath>
54+
<Reference Include="StreamExtended, Version=1.0.141.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
55+
<HintPath>..\..\packages\StreamExtended.1.0.141-beta\lib\net45\StreamExtended.dll</HintPath>
5656
</Reference>
5757
<Reference Include="System" />
5858
<Reference Include="System.Data" />
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3-
<package id="StreamExtended" version="1.0.138-beta" targetFramework="net45" />
3+
<package id="StreamExtended" version="1.0.141-beta" targetFramework="net45" />
44
</packages>

Tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
<AppDesignerFolder>Properties</AppDesignerFolder>
99
<RootNamespace>Titanium.Web.Proxy.UnitTests</RootNamespace>
1010
<AssemblyName>Titanium.Web.Proxy.UnitTests</AssemblyName>
11-
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
11+
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
1212
<FileAlignment>512</FileAlignment>
1313
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
1414
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
1515
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
1616
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
1717
<IsCodedUITest>False</IsCodedUITest>
1818
<TestProjectType>UnitTest</TestProjectType>
19+
<TargetFrameworkProfile />
1920
</PropertyGroup>
2021
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
2122
<DebugSymbols>true</DebugSymbols>

Titanium.Web.Proxy/Compression/CompressionFactory.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
using System;
2+
using Titanium.Web.Proxy.Http;
23

34
namespace Titanium.Web.Proxy.Compression
45
{
56
/// <summary>
67
/// A factory to generate the compression methods based on the type of compression
78
/// </summary>
8-
internal class CompressionFactory
9+
internal static class CompressionFactory
910
{
1011
//cache
11-
private static Lazy<ICompression> gzip = new Lazy<ICompression>(() => new GZipCompression());
12-
private static Lazy<ICompression> deflate = new Lazy<ICompression>(() => new DeflateCompression());
12+
private static readonly Lazy<ICompression> gzip = new Lazy<ICompression>(() => new GZipCompression());
13+
private static readonly Lazy<ICompression> deflate = new Lazy<ICompression>(() => new DeflateCompression());
1314

1415
public static ICompression GetCompression(string type)
1516
{
1617
switch (type)
1718
{
18-
case "gzip":
19+
case KnownHeaders.ContentEncodingGzip:
1920
return gzip.Value;
20-
case "deflate":
21+
case KnownHeaders.ContentEncodingDeflate:
2122
return deflate.Value;
2223
default:
23-
return null;
24+
throw new Exception($"Unsupported compression mode: {type}");
2425
}
2526
}
2627
}

Titanium.Web.Proxy/Compression/DeflateCompression.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,9 @@ namespace Titanium.Web.Proxy.Compression
99
/// </summary>
1010
internal class DeflateCompression : ICompression
1111
{
12-
public async Task<byte[]> Compress(byte[] responseBody)
12+
public Stream GetStream(Stream stream)
1313
{
14-
using (var ms = new MemoryStream())
15-
{
16-
using (var zip = new DeflateStream(ms, CompressionMode.Compress, true))
17-
{
18-
await zip.WriteAsync(responseBody, 0, responseBody.Length);
19-
}
20-
21-
return ms.ToArray();
22-
}
14+
return new DeflateStream(stream, CompressionMode.Compress, true);
2315
}
2416
}
2517
}

Titanium.Web.Proxy/Compression/GZipCompression.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,9 @@ namespace Titanium.Web.Proxy.Compression
99
/// </summary>
1010
internal class GZipCompression : ICompression
1111
{
12-
public async Task<byte[]> Compress(byte[] responseBody)
12+
public Stream GetStream(Stream stream)
1313
{
14-
using (var ms = new MemoryStream())
15-
{
16-
using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
17-
{
18-
await zip.WriteAsync(responseBody, 0, responseBody.Length);
19-
}
20-
21-
return ms.ToArray();
22-
}
14+
return new GZipStream(stream, CompressionMode.Compress, true);
2315
}
2416
}
2517
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Threading.Tasks;
1+
using System.IO;
2+
using System.Threading.Tasks;
23

34
namespace Titanium.Web.Proxy.Compression
45
{
@@ -7,6 +8,6 @@ namespace Titanium.Web.Proxy.Compression
78
/// </summary>
89
interface ICompression
910
{
10-
Task<byte[]> Compress(byte[] responseBody);
11+
Stream GetStream(Stream stream);
1112
}
1213
}

0 commit comments

Comments
 (0)