Commit 1cc02359 authored by justcoding121's avatar justcoding121

Sync beta to stable manually

parent 57e07f71
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
......@@ -10,10 +11,14 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
private ProxyServer proxyServer;
//share requestBody outside handlers
private Dictionary<Guid, string> requestBodyHistory;
public ProxyTestController()
{
proxyServer = new ProxyServer();
proxyServer.TrustRootCertificate = true;
requestBodyHistory = new Dictionary<Guid, string>();
}
public void StartProxy()
......@@ -79,7 +84,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
////read request headers
var requestHeaders = e.WebSession.Request.RequestHeaders;
if ((e.WebSession.Request.Method == "POST" || e.WebSession.Request.Method == "PUT"))
var method = e.WebSession.Request.Method.ToUpper();
if ((method == "POST" || method == "PUT" || method == "PATCH"))
{
//Get/Set request body bytes
byte[] bodyBytes = await e.GetRequestBody();
......@@ -89,6 +95,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
string bodyString = await e.GetRequestBodyAsString();
await e.SetRequestBodyString(bodyString);
requestBodyHistory[e.Id] = bodyString;
}
//To cancel a request with a custom HTML content
......@@ -113,6 +120,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{
if(requestBodyHistory.ContainsKey(e.Id))
{
//access request body by looking up the shared dictionary using requestId
var requestBody = requestBodyHistory[e.Id];
}
//read response headers
var responseHeaders = e.WebSession.Response.ResponseHeaders;
......
Doneness:
- [ ] Build is okay - I made sure that this change is building successfully.
- [ ] No Bugs - I made sure that this change is working properly as expected. It does'nt have any bugs that you are aware of.
- [ ] Branching - If this is not a hotfix, I am making this request against release branch (aka beta branch)
- [ ] Branching - If this is not a hotfix, I am making this request against develop branch
......@@ -38,6 +38,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
internal ProxyClient ProxyClient { get; set; }
/// <summary>
/// Returns a unique Id for this request/response session
/// same as RequestId of WebSession
/// </summary>
public Guid Id => WebSession.RequestId;
//Should we send a rerequest
public bool ReRequest
{
......@@ -81,10 +87,11 @@ namespace Titanium.Web.Proxy.EventArguments
private async Task ReadRequestBody()
{
//GET request don't have a request body to read
if ((WebSession.Request.Method.ToUpper() != "POST" && WebSession.Request.Method.ToUpper() != "PUT"))
var method = WebSession.Request.Method.ToUpper();
if ((method != "POST" && method != "PUT" && method != "PATCH"))
{
throw new BodyNotFoundException("Request don't have a body." +
"Please verify that this request is a Http POST/PUT and request " +
throw new BodyNotFoundException("Request don't have a body. " +
"Please verify that this request is a Http POST/PUT/PATCH and request " +
"content length is greater than zero before accessing the body.");
}
......
......@@ -10,11 +10,13 @@ using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Tcp;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Helpers
{
using System.Net;
internal enum IpVersion
{
Ipv4 = 1,
......@@ -143,7 +145,7 @@ namespace Titanium.Web.Proxy.Helpers
string remoteHostName, int remotePort, string httpCmd, Version httpVersion, Dictionary<string, HttpHeader> requestHeaders,
bool isHttps, SslProtocols supportedProtocols,
RemoteCertificateValidationCallback remoteCertificateValidationCallback, LocalCertificateSelectionCallback localCertificateSelectionCallback,
Stream clientStream, TcpConnectionFactory tcpConnectionFactory)
Stream clientStream, TcpConnectionFactory tcpConnectionFactory, IPEndPoint upStreamEndPoint)
{
//prepare the prefix content
StringBuilder sb = null;
......@@ -154,7 +156,7 @@ namespace Titanium.Web.Proxy.Helpers
if (httpCmd != null)
{
sb.Append(httpCmd);
sb.Append(Environment.NewLine);
sb.Append(ProxyConstants.NewLine);
}
if (requestHeaders != null)
......@@ -162,18 +164,18 @@ namespace Titanium.Web.Proxy.Helpers
foreach (var header in requestHeaders.Select(t => t.Value.ToString()))
{
sb.Append(header);
sb.Append(Environment.NewLine);
sb.Append(ProxyConstants.NewLine);
}
}
sb.Append(Environment.NewLine);
sb.Append(ProxyConstants.NewLine);
}
var tcpConnection = await tcpConnectionFactory.CreateClient(bufferSize, connectionTimeOutSeconds,
remoteHostName, remotePort,
httpVersion, isHttps,
supportedProtocols, remoteCertificateValidationCallback, localCertificateSelectionCallback,
null, null, clientStream);
null, null, clientStream, upStreamEndPoint);
try
{
......
......@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Http
......@@ -90,7 +91,7 @@ namespace Titanium.Web.Proxy.Http
var header = headerItem.Value;
if (headerItem.Key != "Proxy-Authorization")
{
requestLines.AppendLine(header.Name + ':' + header.Value);
requestLines.AppendLine(header.Name + ": " + header.Value);
}
}
......@@ -102,7 +103,7 @@ namespace Titanium.Web.Proxy.Http
{
if (headerItem.Key != "Proxy-Authorization")
{
requestLines.AppendLine(header.Name + ':' + header.Value);
requestLines.AppendLine(header.Name + ": " + header.Value);
}
}
}
......
......@@ -4,7 +4,7 @@ using System.Net.Sockets;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Network
namespace Titanium.Web.Proxy.Network.Tcp
{
/// <summary>
/// An object that holds TcpConnection to a particular server & port
......
......@@ -8,9 +8,12 @@ using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
using System.Security.Authentication;
using System.Linq;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Network
namespace Titanium.Web.Proxy.Network.Tcp
{
using System.Net;
/// <summary>
/// A class that manages Tcp Connection to server used by this proxy server
/// </summary>
......@@ -33,13 +36,14 @@ namespace Titanium.Web.Proxy.Network
/// <param name="externalHttpProxy"></param>
/// <param name="externalHttpsProxy"></param>
/// <param name="clientStream"></param>
/// <param name="upStreamEndPoint"></param>
/// <returns></returns>
internal async Task<TcpConnection> CreateClient(int bufferSize, int connectionTimeOutSeconds,
string remoteHostName, int remotePort, Version httpVersion,
bool isHttps, SslProtocols supportedSslProtocols,
RemoteCertificateValidationCallback remoteCertificateValidationCallback, LocalCertificateSelectionCallback localCertificateSelectionCallback,
ExternalProxy externalHttpProxy, ExternalProxy externalHttpsProxy,
Stream clientStream)
Stream clientStream, EndPoint upStreamEndPoint)
{
TcpClient client;
Stream stream;
......@@ -51,10 +55,12 @@ namespace Titanium.Web.Proxy.Network
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections
if (externalHttpsProxy != null && externalHttpsProxy.HostName != remoteHostName)
{
client = new TcpClient(externalHttpsProxy.HostName, externalHttpsProxy.Port);
client = new TcpClient();
client.Client.Bind(upStreamEndPoint);
client.Client.Connect(externalHttpsProxy.HostName, externalHttpsProxy.Port);
stream = client.GetStream();
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize, true))
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize, true) { NewLine = ProxyConstants.NewLine })
{
await writer.WriteLineAsync($"CONNECT {remoteHostName}:{remotePort} HTTP/{httpVersion}");
await writer.WriteLineAsync($"Host: {remoteHostName}:{remotePort}");
......@@ -75,7 +81,7 @@ namespace Titanium.Web.Proxy.Network
var result = await reader.ReadLineAsync();
if (!new string[] { "200 OK", "connection established" }.Any(s=> result.ToLower().Contains(s.ToLower())))
if (!new string[] { "200 OK", "connection established" }.Any(s => result.ToLower().Contains(s.ToLower())))
{
throw new Exception("Upstream proxy failed to create a secure tunnel");
}
......@@ -85,7 +91,9 @@ namespace Titanium.Web.Proxy.Network
}
else
{
client = new TcpClient(remoteHostName, remotePort);
client = new TcpClient();
client.Client.Bind(upStreamEndPoint);
client.Client.Connect(remoteHostName, remotePort);
stream = client.GetStream();
}
......@@ -109,12 +117,16 @@ namespace Titanium.Web.Proxy.Network
{
if (externalHttpProxy != null && externalHttpProxy.HostName != remoteHostName)
{
client = new TcpClient(externalHttpProxy.HostName, externalHttpProxy.Port);
client = new TcpClient();
client.Client.Bind(upStreamEndPoint);
client.Client.Connect(externalHttpProxy.HostName, externalHttpProxy.Port);
stream = client.GetStream();
}
else
{
client = new TcpClient(remoteHostName, remotePort);
client = new TcpClient();
client.Client.Bind(upStreamEndPoint);
client.Client.Connect(remoteHostName, remotePort);
stream = client.GetStream();
}
}
......@@ -125,6 +137,7 @@ namespace Titanium.Web.Proxy.Network
stream.ReadTimeout = connectionTimeOutSeconds * 1000;
stream.WriteTimeout = connectionTimeOutSeconds * 1000;
return new TcpConnection()
{
UpStreamHttpProxy = externalHttpProxy,
......@@ -139,4 +152,4 @@ namespace Titanium.Web.Proxy.Network
};
}
}
}
}
\ No newline at end of file
using System.Net;
using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.Tcp
{
/// <summary>
/// Represents a managed interface of IP Helper API TcpRow struct
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary>
internal class TcpRow
{
/// <summary>
/// Initializes a new instance of the <see cref="TcpRow"/> class.
/// </summary>
/// <param name="tcpRow">TcpRow struct.</param>
public TcpRow(NativeMethods.TcpRow tcpRow)
{
ProcessId = tcpRow.owningPid;
int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
long localAddress = tcpRow.localAddr;
LocalEndPoint = new IPEndPoint(localAddress, localPort);
int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
long remoteAddress = tcpRow.remoteAddr;
RemoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
}
/// <summary>
/// Gets the local end point.
/// </summary>
public IPEndPoint LocalEndPoint { get; private set; }
/// <summary>
/// Gets the remote end point.
/// </summary>
public IPEndPoint RemoteEndPoint { get; private set; }
/// <summary>
/// Gets the process identifier.
/// </summary>
public int ProcessId { get; private set; }
}
using System.Net;
using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.Network.Tcp
{
/// <summary>
/// Represents a managed interface of IP Helper API TcpRow struct
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary>
internal class TcpRow
{
/// <summary>
/// Initializes a new instance of the <see cref="TcpRow"/> class.
/// </summary>
/// <param name="tcpRow">TcpRow struct.</param>
public TcpRow(NativeMethods.TcpRow tcpRow)
{
ProcessId = tcpRow.owningPid;
int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
long localAddress = tcpRow.localAddr;
LocalEndPoint = new IPEndPoint(localAddress, localPort);
int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
long remoteAddress = tcpRow.remoteAddr;
RemoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
}
/// <summary>
/// Gets the local end point.
/// </summary>
public IPEndPoint LocalEndPoint { get; private set; }
/// <summary>
/// Gets the remote end point.
/// </summary>
public IPEndPoint RemoteEndPoint { get; private set; }
/// <summary>
/// Gets the process identifier.
/// </summary>
public int ProcessId { get; private set; }
}
}
\ No newline at end of file
using System.Collections;
using System.Collections.Generic;
namespace Titanium.Web.Proxy.Tcp
namespace Titanium.Web.Proxy.Network.Tcp
{
/// <summary>
/// Represents collection of TcpRows
/// </summary>
/// <seealso cref="System.Collections.Generic.IEnumerable{Titanium.Web.Proxy.Tcp.TcpRow}" />
/// <seealso cref="System.Collections.Generic.IEnumerable{Proxy.Tcp.TcpRow}" />
internal class TcpTable : IEnumerable<TcpRow>
{
private readonly IEnumerable<TcpRow> tcpRows;
......
......@@ -9,6 +9,7 @@ using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using System.Linq;
using System.Security.Authentication;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy
{
......@@ -116,6 +117,12 @@ namespace Titanium.Web.Proxy
/// </summary>
public ExternalProxy UpStreamHttpsProxy { get; set; }
/// <summary>
/// Local adapter/NIC endpoint (where proxy makes request via)
/// default via any IP addresses of this machine
/// </summary>
public IPEndPoint UpStreamEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// </summary>
......
......@@ -10,13 +10,13 @@ using System.Text.RegularExpressions;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Models;
using System.Security.Cryptography.X509Certificates;
using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.Http;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy
{
......@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy
clientStream.WriteTimeout = ConnectionTimeOutSeconds * 1000;
var clientStreamReader = new CustomBinaryReader(clientStream);
var clientStreamWriter = new StreamWriter(clientStream);
var clientStreamWriter = new StreamWriter(clientStream) { NewLine = ProxyConstants.NewLine };
Uri httpRemoteUri;
try
......@@ -121,7 +121,7 @@ namespace Titanium.Web.Proxy
clientStream = sslStream;
clientStreamReader = new CustomBinaryReader(sslStream);
clientStreamWriter = new StreamWriter(sslStream);
clientStreamWriter = new StreamWriter(sslStream) {NewLine = ProxyConstants.NewLine };
}
catch
......@@ -152,7 +152,7 @@ namespace Titanium.Web.Proxy
false, SupportedSslProtocols,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
new LocalCertificateSelectionCallback(SelectClientCertificate),
clientStream, tcpConnectionFactory);
clientStream, tcpConnectionFactory, UpStreamEndPoint);
Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
return;
......@@ -195,7 +195,7 @@ namespace Titanium.Web.Proxy
SslProtocols.Tls, false);
clientStreamReader = new CustomBinaryReader(sslStream);
clientStreamWriter = new StreamWriter(sslStream);
clientStreamWriter = new StreamWriter(sslStream) { NewLine = ProxyConstants.NewLine };
//HTTPS server created - we can now decrypt the client's traffic
}
......@@ -211,7 +211,7 @@ namespace Titanium.Web.Proxy
else
{
clientStreamReader = new CustomBinaryReader(clientStream);
clientStreamWriter = new StreamWriter(clientStream);
clientStreamWriter = new StreamWriter(clientStream) { NewLine = ProxyConstants.NewLine };
}
//now read the request line
......@@ -251,7 +251,7 @@ namespace Titanium.Web.Proxy
args.IsHttps, SupportedSslProtocols,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
new LocalCertificateSelectionCallback(SelectClientCertificate),
customUpStreamHttpProxy ?? UpStreamHttpProxy, customUpStreamHttpsProxy ?? UpStreamHttpsProxy, args.ProxyClient.ClientStream);
customUpStreamHttpProxy ?? UpStreamHttpProxy, customUpStreamHttpsProxy ?? UpStreamHttpsProxy, args.ProxyClient.ClientStream, UpStreamEndPoint);
}
args.WebSession.Request.RequestLocked = true;
......@@ -312,8 +312,9 @@ namespace Titanium.Web.Proxy
{
if (!args.WebSession.Request.ExpectationFailed)
{
//If its a post/put request, then read the client html body and send it to server
if (args.WebSession.Request.Method.ToUpper() == "POST" || args.WebSession.Request.Method.ToUpper() == "PUT")
//If its a post/put/patch request, then read the client html body and send it to server
var method = args.WebSession.Request.Method.ToUpper();
if (method == "POST" || method == "PUT" || method == "PATCH")
{
await SendClientRequestBody(args);
}
......@@ -486,7 +487,7 @@ namespace Titanium.Web.Proxy
httpCmd, httpVersion, args.WebSession.Request.RequestHeaders, args.IsHttps,
SupportedSslProtocols, new RemoteCertificateValidationCallback(ValidateServerCertificate),
new LocalCertificateSelectionCallback(SelectClientCertificate),
clientStream, tcpConnectionFactory);
clientStream, tcpConnectionFactory, UpStreamEndPoint);
Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
break;
......@@ -570,7 +571,7 @@ namespace Titanium.Web.Proxy
}
/// <summary>
/// This is called when the request is PUT/POST to read the body
/// This is called when the request is PUT/POST/PATCH to read the body
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
......
......@@ -8,14 +8,15 @@ namespace Titanium.Web.Proxy.Shared
/// </summary>
internal class ProxyConstants
{
internal static readonly char[] SpaceSplit = { ' ' };
internal static readonly char[] SpaceSplit = { ' ' };
internal static readonly char[] ColonSplit = { ':' };
internal static readonly char[] SemiColonSplit = { ';' };
internal static readonly byte[] NewLineBytes = Encoding.ASCII.GetBytes(Environment.NewLine);
internal static readonly byte[] NewLineBytes = Encoding.ASCII.GetBytes(NewLine);
internal static readonly byte[] ChunkEnd =
Encoding.ASCII.GetBytes(0.ToString("x2") + Environment.NewLine + Environment.NewLine);
Encoding.ASCII.GetBytes(0.ToString("x2") + NewLine + NewLine);
internal const string NewLine = "\r\n";
}
}
......@@ -84,8 +84,8 @@
<Compile Include="Http\Request.cs" />
<Compile Include="Http\Response.cs" />
<Compile Include="Models\ExternalProxy.cs" />
<Compile Include="Network\TcpConnection.cs" />
<Compile Include="Network\TcpConnectionFactory.cs" />
<Compile Include="Network\Tcp\TcpConnection.cs" />
<Compile Include="Network\Tcp\TcpConnectionFactory.cs" />
<Compile Include="Models\HttpHeader.cs" />
<Compile Include="Http\HttpWebClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
......@@ -100,8 +100,8 @@
<Compile Include="Http\Responses\OkResponse.cs" />
<Compile Include="Http\Responses\RedirectResponse.cs" />
<Compile Include="Shared\ProxyConstants.cs" />
<Compile Include="Tcp\TcpRow.cs" />
<Compile Include="Tcp\TcpTable.cs" />
<Compile Include="Network\Tcp\TcpRow.cs" />
<Compile Include="Network\Tcp\TcpTable.cs" />
</ItemGroup>
<ItemGroup>
<COMReference Include="CERTENROLLLib">
......
......@@ -56,9 +56,9 @@ deploy:
auth_token:
secure: ItVm+50ASpDXx1w+FCe2NTpZxqCbjRWfugLjk/bqBIi00DvPnSGOV1rIQ5hnwBW3
on:
branch: /(master|release)/
branch: /(stable|beta)/
- provider: NuGet
api_key:
secure: ZbRmjOcp+TDllRV1wxqLZjdRV7hld388rXlWVJuGGiQleomP9Ku+Nsy3a75E7/9k
on:
branch: /(master|release)/
branch: /(stable|beta)/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment