Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a991c2b
simplify custom stream
honfika Apr 30, 2018
7baee70
API documentation update by build server
Apr 30, 2018
db2b48a
simplify compressionfactory, usre stream reader interface when only t…
honfika Apr 30, 2018
6731c1e
Merge branch 'master' of https://github.com/justcoding121/Titanium-We…
honfika Apr 30, 2018
927d2b1
TcpClientConnection class
honfika Apr 30, 2018
59e3062
Increase timeout to 60 sec, because long polling usually uses 30 sec …
honfika Apr 30, 2018
bb6be9d
small exception handling improvement
honfika May 1, 2018
9f74731
redundant parameter removed
honfika May 1, 2018
875ba62
space between // and text in comments (except when it is a commented …
honfika May 1, 2018
3bf4649
stylecop fixes
honfika May 1, 2018
b4e71fc
API documentation update by build server
May 1, 2018
9f3e9d9
alpn improvement
honfika May 1, 2018
58afe8a
Merge branch 'master' of https://github.com/justcoding121/Titanium-We…
honfika May 1, 2018
5a7f46c
cleanup comments
justcoding121 May 1, 2018
c2f8625
API documentation update by build server
May 1, 2018
348e14a
race condition fix, #424
honfika May 6, 2018
d148f77
API documentation update by build server
May 6, 2018
9139ab2
Use of Guid as a session identifer #427
honfika May 6, 2018
3299cd6
Merge branch 'master' of https://github.com/justcoding121/Titanium-We…
honfika May 6, 2018
081d1b8
API documentation update by build server
May 6, 2018
ca08a33
update example without RequestId
justcoding121 May 6, 2018
8818a9e
update example
justcoding121 May 6, 2018
b06dd78
Update README.md
justcoding121 May 6, 2018
a013e31
#428 Fix incorrect compression relay
justcoding121 May 6, 2018
76d99c8
spelling
justcoding121 May 6, 2018
ad5a5d3
Update streamextended package
justcoding121 May 7, 2018
d3ad2f8
Merge pull request #429 from justcoding121/master
justcoding121 May 7, 2018
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,4 @@ FakesAssemblies/
*.opt

# Docfx
docs/manifest.json
docs/manifest.json
4 changes: 2 additions & 2 deletions Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ public class Program

public static void Main(string[] args)
{
//fix console hang due to QuickEdit mode
// fix console hang due to QuickEdit mode
ConsoleHelper.DisableQuickEditMode();

//Start proxy controller
// Start proxy controller
controller.StartProxy();

Console.WriteLine("Hit any key to exit..");
Expand Down
138 changes: 71 additions & 67 deletions Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,13 @@ public class ProxyTestController

private readonly ProxyServer proxyServer;

//keep track of request headers
private readonly IDictionary<Guid, HeaderCollection> requestHeaderHistory =
new ConcurrentDictionary<Guid, HeaderCollection>();

//keep track of response headers
private readonly IDictionary<Guid, HeaderCollection> responseHeaderHistory =
new ConcurrentDictionary<Guid, HeaderCollection>();

private ExplicitProxyEndPoint explicitEndPoint;

//share requestBody outside handlers
//Using a dictionary is not a good idea since it can cause memory overflow
//ideally the data should be moved out of memory
//private readonly IDictionary<Guid, string> requestBodyHistory = new ConcurrentDictionary<Guid, string>();

public ProxyTestController()
{
proxyServer = new ProxyServer();

//generate root certificate without storing it in file system
// generate root certificate without storing it in file system
//proxyServer.CertificateManager.CreateRootCertificate(false);

//proxyServer.CertificateManager.TrustRootCertificate();
Expand All @@ -63,11 +50,12 @@ public ProxyTestController()
};
proxyServer.ForwardToUpstreamGateway = true;
proxyServer.CertificateManager.SaveFakeCertificates = true;
//optionally set the Certificate Engine
//Under Mono or Non-Windows runtimes only BouncyCastle will be supported

// optionally set the Certificate Engine
// Under Mono or Non-Windows runtimes only BouncyCastle will be supported
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;

//optionally set the Root Certificate
// optionally set the Root Certificate
//proxyServer.CertificateManager.RootCertificate = new X509Certificate2("myCert.pfx", string.Empty, X509KeyStorageFlags.Exportable);
}

Expand All @@ -83,27 +71,26 @@ public void StartProxy()

explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000);

//Fired when a CONNECT request is received
// Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse += OnBeforeTunnelConnectResponse;

//An explicit endpoint is where the client knows about the existence of a proxy
//So client sends request in a proxy friendly manner
// An explicit endpoint is where the client knows about the existence of a proxy
// So client sends request in a proxy friendly manner
proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.Start();

//Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
//A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS
//to send data to this endPoint
// Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
// A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS
// to send data to this endPoint
//var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 443, true)
//{
// //Generic Certificate hostname to use
// //When SNI is disabled by client
//{
// // Generic Certificate hostname to use
// // When SNI is disabled by client
// GenericCertificateName = "google.com"
//};

//proxyServer.AddEndPoint(transparentEndPoint);

//proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };

Expand All @@ -117,7 +104,7 @@ public void StartProxy()
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
#endif
{
//Only explicit proxies can be set as system proxy!
// Only explicit proxies can be set as system proxy!
//proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
//proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp);
Expand All @@ -135,8 +122,8 @@ public void Stop()
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;

proxyServer.Stop();

//remove the generated certificates
// remove the generated certificates
//proxyServer.CertificateManager.RemoveTrustedRootCertificates();
}

Expand All @@ -147,9 +134,9 @@ private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSess

if (hostname.Contains("dropbox.com"))
{
//Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example dropbox.com
// Exclude Https addresses you don't want to proxy
// Useful for clients that use certificate pinning
// for example dropbox.com
e.DecryptSsl = false;
}
}
Expand All @@ -158,55 +145,48 @@ private async Task OnBeforeTunnelConnectResponse(object sender, TunnelConnectSes
{
}

//intecept & cancel redirect or update requests
// intecept & cancel redirect or update requests
private async Task OnRequest(object sender, SessionEventArgs e)
{
WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
WriteToConsole(e.WebSession.Request.Url);

//read request headers
requestHeaderHistory[e.Id] = e.WebSession.Request.Headers;
// store it in the UserData property
// It can be a simple integer, Guid, or any type
//e.UserData = new CustomUserData()
//{
// RequestHeaders = e.WebSession.Request.Headers,
// RequestBody = e.WebSession.Request.HasBody ? e.WebSession.Request.Body:null,
// RequestBodyString = e.WebSession.Request.HasBody? e.WebSession.Request.BodyString:null
//};

////This sample shows how to get the multipart form data headers
//if (e.WebSession.Request.Host == "mail.yahoo.com" && e.WebSession.Request.IsMultipartFormData)
//{
// e.MultipartRequestPartSent += MultipartRequestPartSent;
//}

//if (e.WebSession.Request.HasBody)
//{
// //Get/Set request body bytes
// var bodyBytes = await e.GetRequestBody();
// await e.SetRequestBody(bodyBytes);

// //Get/Set request body as string
// string bodyString = await e.GetRequestBodyAsString();
// await e.SetRequestBodyString(bodyString);

// //requestBodyHistory[e.Id] = bodyString;
//}

//To cancel a request with a custom HTML content
//Filter URL
// To cancel a request with a custom HTML content
// Filter URL
//if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("yahoo.com"))
//{
//{
// e.Ok("<!DOCTYPE html>" +
// "<html><body><h1>" +
// "Website Blocked" +
// "</h1>" +
// "<p>Blocked by titanium web proxy.</p>" +
// "</body>" +
// "</html>");
//}
//}

////Redirect example
//if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
//{
//{
// e.Redirect("https://www.paypal.com");
//}
//}
}

//Modify response
// Modify response
private void MultipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e)
{
var session = (SessionEventArgs)sender;
Expand All @@ -221,21 +201,34 @@ private async Task OnResponse(object sender, SessionEventArgs e)
{
WriteToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);

//if (requestBodyHistory.ContainsKey(e.Id))
//{
// //access request body by looking up the shared dictionary using requestId
// var requestBody = requestBodyHistory[e.Id];
//}
string ext = System.IO.Path.GetExtension(e.WebSession.Request.RequestUri.AbsolutePath);

////read response headers
//responseHeaderHistory[e.Id] = e.WebSession.Response.Headers;
//access user data set in request to do something with it
//var userData = e.WebSession.UserData as CustomUserData;

//if (ext == ".gif" || ext == ".png" || ext == ".jpg")
//{
// byte[] btBody = Encoding.UTF8.GetBytes("<!DOCTYPE html>" +
// "<html><body><h1>" +
// "Image is blocked" +
// "</h1>" +
// "<p>Blocked by Titanium</p>" +
// "</body>" +
// "</html>");

// var response = new OkResponse(btBody);
// response.HttpVersion = e.WebSession.Request.HttpVersion;

// e.Respond(response);
// e.TerminateServerConnection();
//}

//// print out process id of current session
////WriteToConsole($"PID: {e.WebSession.ProcessId.Value}");

////if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
//if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST")
//{
//{
// if (e.WebSession.Response.StatusCode == (int)HttpStatusCode.OK)
// {
// if (e.WebSession.Response.ContentType != null && e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html"))
Expand All @@ -247,7 +240,7 @@ private async Task OnResponse(object sender, SessionEventArgs e)
// await e.SetResponseBodyString(body);
// }
// }
//}
//}
}

/// <summary>
Expand All @@ -257,7 +250,7 @@ private async Task OnResponse(object sender, SessionEventArgs e)
/// <param name="e"></param>
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
//set IsValid to true/false based on Certificate Errors
// set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == SslPolicyErrors.None)
{
e.IsValid = true;
Expand All @@ -273,7 +266,7 @@ public Task OnCertificateValidation(object sender, CertificateValidationEventArg
/// <param name="e"></param>
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{
//set e.clientCertificate to override
// set e.clientCertificate to override

return Task.FromResult(0);
}
Expand All @@ -285,5 +278,16 @@ private void WriteToConsole(string message)
Console.WriteLine(message);
}
}

///// <summary>
///// User data object as defined by user.
///// User data can be set to each SessionEventArgs.WebSession.UserData property
///// </summary>
//public class CustomUserData
//{
// public HeaderCollection RequestHeaders { get; set; }
// public byte[] RequestBody { get; set; }
// public string RequestBodyString { get; set; }
//}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Windows.Controls;
using System.Windows.Input;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="StreamExtended, Version=1.0.147.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\..\packages\StreamExtended.1.0.147-beta\lib\net45\StreamExtended.dll</HintPath>
<Reference Include="StreamExtended, Version=1.0.164.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\..\packages\StreamExtended.1.0.164\lib\net45\StreamExtended.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
Expand Down
3 changes: 1 addition & 2 deletions Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>

<packages>
<package id="StreamExtended" version="1.0.147-beta" targetFramework="net45" />
<package id="StreamExtended" version="1.0.164" targetFramework="net45" />
</packages>
17 changes: 7 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,6 @@ Sample request and response event handlers

```csharp

//To access requestBody from OnResponse handler
private IDictionary<Guid, string> requestBodyHistory
= new ConcurrentDictionary<Guid, string>();

private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
string hostname = e.WebSession.Request.RequestUri.Host;
Expand Down Expand Up @@ -156,9 +152,9 @@ public async Task OnRequest(object sender, SessionEventArgs e)
string bodyString = await e.GetRequestBodyAsString();
await e.SetRequestBodyString(bodyString);

//store request Body/request headers etc with request Id as key
//so that you can find it from response handler using request Id
requestBodyHistory[e.Id] = bodyString;
//store request
//so that you can find it from response handler
e.UserData = e.WebSession.Request;
}

//To cancel a request with a custom HTML content
Expand Down Expand Up @@ -202,11 +198,12 @@ public async Task OnResponse(object sender, SessionEventArgs e)
}
}

//access request body/request headers etc by looking up using requestId
if(requestBodyHistory.ContainsKey(e.Id))
if(e.UserData!=null)
{
var requestBody = requestBodyHistory[e.Id];
//access request from UserData property where we stored it in RequestHandler
var request = (Request)e.UserData;
}

}

/// Allows overriding default certificate validation logic
Expand Down
Loading