Commit e1543300 authored by Jehonathan Thomas's avatar Jehonathan Thomas Committed by GitHub

Merge pull request #275 from justcoding121/beta

Stable
parents acad670d ac2877be
...@@ -202,4 +202,4 @@ FakesAssemblies/ ...@@ -202,4 +202,4 @@ FakesAssemblies/
*.plg *.plg
# Visual Studio 6 workspace options file # Visual Studio 6 workspace options file
*.opt *.opt
\ No newline at end of file
...@@ -14,10 +14,6 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -14,10 +14,6 @@ namespace Titanium.Web.Proxy.Examples.Basic
//fix console hang due to QuickEdit mode //fix console hang due to QuickEdit mode
ConsoleHelper.DisableQuickEditMode(); ConsoleHelper.DisableQuickEditMode();
//On Console exit make sure we also exit the proxy
NativeMethods.Handler = ConsoleEventCallback;
NativeMethods.SetConsoleCtrlHandler(NativeMethods.Handler, true);
//Start proxy controller //Start proxy controller
controller.StartProxy(); controller.StartProxy();
...@@ -27,34 +23,5 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -27,34 +23,5 @@ namespace Titanium.Web.Proxy.Examples.Basic
controller.Stop(); controller.Stop();
} }
private static bool ConsoleEventCallback(int eventType)
{
if (eventType != 2) return false;
try
{
controller.Stop();
}
catch
{
// ignored
}
return false;
}
}
internal static class NativeMethods
{
// Keeps it from getting garbage collected
internal static ConsoleEventDelegate Handler;
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);
// Pinvoke
internal delegate bool ConsoleEventDelegate(int eventType);
} }
} }
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Security; using System.Net.Security;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Examples.Basic namespace Titanium.Web.Proxy.Examples.Basic
...@@ -15,8 +17,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -15,8 +17,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
//share requestBody outside handlers //share requestBody outside handlers
//Using a dictionary is not a good idea since it can cause memory overflow //Using a dictionary is not a good idea since it can cause memory overflow
//ideally the data should be moved out of memory //ideally the data should be moved out of memory
//private readonly Dictionary<Guid, string> requestBodyHistory //private readonly IDictionary<Guid, string> requestBodyHistory
// = new Dictionary<Guid, string>(); // = new ConcurrentDictionary<Guid, string>();
public ProxyTestController() public ProxyTestController()
{ {
...@@ -29,6 +31,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -29,6 +31,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
proxyServer.ExceptionFunc = exception => Console.WriteLine(exception.Message); proxyServer.ExceptionFunc = exception => Console.WriteLine(exception.Message);
proxyServer.TrustRootCertificate = true; proxyServer.TrustRootCertificate = true;
proxyServer.ForwardToUpstreamGateway = true;
//optionally set the Certificate Engine //optionally set the Certificate Engine
//Under Mono only BouncyCastle will be supported //Under Mono only BouncyCastle will be supported
...@@ -92,8 +95,9 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -92,8 +95,9 @@ namespace Titanium.Web.Proxy.Examples.Basic
endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port); endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
//Only explicit proxies can be set as system proxy! //Only explicit proxies can be set as system proxy!
proxyServer.SetAsSystemHttpProxy(explicitEndPoint); //proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
proxyServer.SetAsSystemHttpsProxy(explicitEndPoint); //proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp);
} }
public void Stop() public void Stop()
......
...@@ -112,7 +112,8 @@ Sample request and response event handlers ...@@ -112,7 +112,8 @@ Sample request and response event handlers
```csharp ```csharp
//To access requestBody from OnResponse handler //To access requestBody from OnResponse handler
private Dictionary<Guid, string> requestBodyHistory = new Dictionary<Guid, string>(); private IDictionary<Guid, string> requestBodyHistory
= new ConcurrentDictionary<Guid, string>();
public async Task OnRequest(object sender, SessionEventArgs e) public async Task OnRequest(object sender, SessionEventArgs e)
{ {
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Helpers.WinHttp;
namespace Titanium.Web.Proxy.UnitTests
{
[TestClass]
public class SystemProxyTest
{
[TestMethod]
public void CompareProxyAdddressReturendByWebProxyAndWinHttpProxyResolver()
{
var proxyManager = new SystemProxyManager();
try
{
CompareUrls();
proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Http);
CompareUrls();
proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Https);
CompareUrls();
proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.AllHttp);
CompareUrls();
// for this test you need to add a proxy.pac file to a local webserver
//function FindProxyForURL(url, host)
//{
// if (shExpMatch(host, "google.com"))
// {
// return "PROXY 127.0.0.1:8888";
// }
// return "DIRECT";
//}
//proxyManager.SetAutoProxyUrl("http://localhost/proxy.pac");
//CompareUrls();
proxyManager.SetProxyOverride("<-loopback>");
CompareUrls();
proxyManager.SetProxyOverride("<local>");
CompareUrls();
proxyManager.SetProxyOverride("yahoo.com");
CompareUrls();
proxyManager.SetProxyOverride("*.local");
CompareUrls();
proxyManager.SetProxyOverride("http://*.local");
CompareUrls();
proxyManager.SetProxyOverride("<-loopback>;*.local");
CompareUrls();
proxyManager.SetProxyOverride("<-loopback>;*.local;<local>");
CompareUrls();
}
finally
{
proxyManager.RestoreOriginalSettings();
}
}
private void CompareUrls()
{
var webProxy = WebRequest.GetSystemWebProxy();
var resolver = new WinHttpWebProxyFinder();
resolver.LoadFromIE();
CompareProxy(webProxy, resolver, "http://127.0.0.1");
CompareProxy(webProxy, resolver, "https://127.0.0.1");
CompareProxy(webProxy, resolver, "http://localhost");
CompareProxy(webProxy, resolver, "https://localhost");
string hostName = null;
try
{
hostName = Dns.GetHostName();
}
catch{}
if (hostName != null)
{
CompareProxy(webProxy, resolver, "http://" + hostName);
CompareProxy(webProxy, resolver, "https://" + hostName);
}
CompareProxy(webProxy, resolver, "http://google.com");
CompareProxy(webProxy, resolver, "https://google.com");
CompareProxy(webProxy, resolver, "http://bing.com");
CompareProxy(webProxy, resolver, "https://bing.com");
CompareProxy(webProxy, resolver, "http://yahoo.com");
CompareProxy(webProxy, resolver, "https://yahoo.com");
CompareProxy(webProxy, resolver, "http://test.local");
CompareProxy(webProxy, resolver, "https://test.local");
}
private void CompareProxy(IWebProxy webProxy, WinHttpWebProxyFinder resolver, string url)
{
var uri = new Uri(url);
var expectedProxyUri = webProxy.GetProxy(uri);
var proxy = resolver.GetProxy(uri);
if (expectedProxyUri == uri)
{
// no proxy
Assert.AreEqual(proxy, null);
return;
}
Assert.AreEqual(expectedProxyUri.ToString(), $"http://{proxy.HostName}:{proxy.Port}/");
}
}
}
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
<Compile Include="CertificateManagerTests.cs" /> <Compile Include="CertificateManagerTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ProxyServerTests.cs" /> <Compile Include="ProxyServerTests.cs" />
<Compile Include="SystemProxyTest.cs" />
<Compile Include="WinAuthTests.cs" /> <Compile Include="WinAuthTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Helpers
{
internal class ProxyInfo
{
public bool? AutoDetect { get; }
public string AutoConfigUrl { get; }
public int? ProxyEnable { get; }
public string ProxyServer { get; }
public string ProxyOverride { get; }
public bool BypassLoopback { get; }
public bool BypassOnLocal { get; }
public Dictionary<ProxyProtocolType, HttpSystemProxyValue> Proxies { get; }
public string[] BypassList { get; }
public ProxyInfo(bool? autoDetect, string autoConfigUrl, int? proxyEnable, string proxyServer, string proxyOverride)
{
AutoDetect = autoDetect;
AutoConfigUrl = autoConfigUrl;
ProxyEnable = proxyEnable;
ProxyServer = proxyServer;
ProxyOverride = proxyOverride;
if (proxyServer != null)
{
Proxies = GetSystemProxyValues(proxyServer).ToDictionary(x=>x.ProtocolType);
}
if (proxyOverride != null)
{
var overrides = proxyOverride.Split(';');
var overrides2 = new List<string>();
foreach (var overrideHost in overrides)
{
if (overrideHost == "<-loopback>")
{
BypassLoopback = true;
}
else if (overrideHost == "<local>")
{
BypassOnLocal = true;
}
else
{
overrides2.Add(BypassStringEscape(overrideHost));
}
}
if (overrides2.Count > 0)
{
BypassList = overrides2.ToArray();
}
Proxies = GetSystemProxyValues(proxyServer).ToDictionary(x => x.ProtocolType);
}
}
private static string BypassStringEscape(string rawString)
{
Match match = new Regex("^(?<scheme>.*://)?(?<host>[^:]*)(?<port>:[0-9]{1,5})?$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant).Match(rawString);
string empty1;
string rawString1;
string empty2;
if (match.Success)
{
empty1 = match.Groups["scheme"].Value;
rawString1 = match.Groups["host"].Value;
empty2 = match.Groups["port"].Value;
}
else
{
empty1 = string.Empty;
rawString1 = rawString;
empty2 = string.Empty;
}
string str1 = ConvertRegexReservedChars(empty1);
string str2 = ConvertRegexReservedChars(rawString1);
string str3 = ConvertRegexReservedChars(empty2);
if (str1 == string.Empty)
str1 = "(?:.*://)?";
if (str3 == string.Empty)
str3 = "(?::[0-9]{1,5})?";
return "^" + str1 + str2 + str3 + "$";
}
private static string ConvertRegexReservedChars(string rawString)
{
if (rawString.Length == 0)
return rawString;
var stringBuilder = new StringBuilder();
foreach (char ch in rawString)
{
if ("#$()+.?[\\^{|".IndexOf(ch) != -1)
stringBuilder.Append('\\');
else if (ch == 42)
stringBuilder.Append('.');
stringBuilder.Append(ch);
}
return stringBuilder.ToString();
}
public static ProxyProtocolType? ParseProtocolType(string protocolTypeStr)
{
if (protocolTypeStr == null)
{
return null;
}
ProxyProtocolType? protocolType = null;
if (protocolTypeStr.Equals("http", StringComparison.InvariantCultureIgnoreCase))
{
protocolType = ProxyProtocolType.Http;
}
else if (protocolTypeStr.Equals("https", StringComparison.InvariantCultureIgnoreCase))
{
protocolType = ProxyProtocolType.Https;
}
return protocolType;
}
/// <summary>
/// Parse the system proxy setting values
/// </summary>
/// <param name="proxyServerValues"></param>
/// <returns></returns>
public static List<HttpSystemProxyValue> GetSystemProxyValues(string proxyServerValues)
{
var result = new List<HttpSystemProxyValue>();
if (string.IsNullOrWhiteSpace(proxyServerValues))
return result;
var proxyValues = proxyServerValues.Split(';');
if (proxyValues.Length > 0)
{
result.AddRange(proxyValues.Select(ParseProxyValue).Where(parsedValue => parsedValue != null));
}
else
{
var parsedValue = ParseProxyValue(proxyServerValues);
if (parsedValue != null)
result.Add(parsedValue);
}
return result;
}
/// <summary>
/// Parses the system proxy setting string
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static HttpSystemProxyValue ParseProxyValue(string value)
{
var tmp = Regex.Replace(value, @"\s+", " ").Trim();
int equalsIndex = tmp.IndexOf("=", StringComparison.InvariantCulture);
if (equalsIndex >= 0)
{
string protocolTypeStr = tmp.Substring(0, equalsIndex);
var protocolType = ParseProtocolType(protocolTypeStr);
if (protocolType.HasValue)
{
var endPointParts = tmp.Substring(equalsIndex + 1).Split(':');
return new HttpSystemProxyValue
{
HostName = endPointParts[0],
Port = int.Parse(endPointParts[1]),
ProtocolType = protocolType.Value,
};
}
}
return null;
}
}
}
This diff is collapsed.
using System;
using System.Runtime.InteropServices;
// Helper classes for setting system proxy settings
namespace Titanium.Web.Proxy.Helpers.WinHttp
{
internal partial class NativeMethods
{
internal static class WinHttp
{
[DllImport("winhttp.dll", SetLastError = true)]
internal static extern bool WinHttpGetIEProxyConfigForCurrentUser(ref WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig);
[DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern WinHttpHandle WinHttpOpen(string userAgent, AccessType accessType, string proxyName, string proxyBypass, int dwFlags);
[DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool WinHttpSetTimeouts(WinHttpHandle session, int resolveTimeout, int connectTimeout, int sendTimeout, int receiveTimeout);
[DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool WinHttpGetProxyForUrl(WinHttpHandle session, string url, [In] ref WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out WINHTTP_PROXY_INFO proxyInfo);
[DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool WinHttpCloseHandle(IntPtr httpSession);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
{
public bool AutoDetect;
public IntPtr AutoConfigUrl;
public IntPtr Proxy;
public IntPtr ProxyBypass;
}
[Flags]
internal enum AutoProxyFlags
{
AutoDetect = 1,
AutoProxyConfigUrl = 2,
RunInProcess = 65536,
RunOutProcessOnly = 131072
}
internal enum AccessType
{
DefaultProxy = 0,
NoProxy = 1,
NamedProxy = 3
}
[Flags]
internal enum AutoDetectType
{
None = 0,
Dhcp = 1,
DnsA = 2
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WINHTTP_AUTOPROXY_OPTIONS
{
public AutoProxyFlags Flags;
public AutoDetectType AutoDetectFlags;
[MarshalAs(UnmanagedType.LPWStr)] public string AutoConfigUrl;
private IntPtr lpvReserved;
private int dwReserved;
public bool AutoLogonIfChallenged;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WINHTTP_PROXY_INFO
{
public AccessType AccessType;
public IntPtr Proxy;
public IntPtr ProxyBypass;
}
internal enum ErrorCodes
{
Success = 0,
OutOfHandles = 12001,
Timeout = 12002,
InternalError = 12004,
InvalidUrl = 12005,
UnrecognizedScheme = 12006,
NameNotResolved = 12007,
InvalidOption = 12009,
OptionNotSettable = 12011,
Shutdown = 12012,
LoginFailure = 12015,
OperationCancelled = 12017,
IncorrectHandleType = 12018,
IncorrectHandleState = 12019,
CannotConnect = 12029,
ConnectionError = 12030,
ResendRequest = 12032,
SecureCertDateInvalid = 12037,
SecureCertCNInvalid = 12038,
AuthCertNeeded = 12044,
SecureInvalidCA = 12045,
SecureCertRevFailed = 12057,
CannotCallBeforeOpen = 12100,
CannotCallBeforeSend = 12101,
CannotCallAfterSend = 12102,
CannotCallAfterOpen = 12103,
HeaderNotFound = 12150,
InvalidServerResponse = 12152,
InvalidHeader = 12153,
InvalidQueryRequest = 12154,
HeaderAlreadyExists = 12155,
RedirectFailed = 12156,
SecureChannelError = 12157,
BadAutoProxyScript = 12166,
UnableToDownloadScript = 12167,
SecureInvalidCert = 12169,
SecureCertRevoked = 12170,
NotInitialized = 12172,
SecureFailure = 12175,
AutoProxyServiceError = 12178,
SecureCertWrongUsage = 12179,
AudodetectionFailed = 12180,
HeaderCountExceeded = 12181,
HeaderSizeOverflow = 12182,
ChunkedEncodingHeaderSizeOverflow = 12183,
ResponseDrainOverflow = 12184,
ClientCertNoPrivateKey = 12185,
ClientCertNoAccessPrivateKey = 12186
}
}
}
}
using System;
using System.Runtime.InteropServices;
namespace Titanium.Web.Proxy.Helpers.WinHttp
{
internal class WinHttpHandle : SafeHandle
{
public WinHttpHandle() : base(IntPtr.Zero, true)
{
}
protected override bool ReleaseHandle()
{
return NativeMethods.WinHttp.WinHttpCloseHandle(handle);
}
public override bool IsInvalid => handle == IntPtr.Zero;
}
}
\ No newline at end of file
This diff is collapsed.
...@@ -80,17 +80,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -80,17 +80,14 @@ namespace Titanium.Web.Proxy.Http
var requestLines = new StringBuilder(); var requestLines = new StringBuilder();
//prepare the request & headers //prepare the request & headers
if (ServerConnection.UpStreamHttpProxy != null && ServerConnection.IsHttps == false || ServerConnection.UpStreamHttpsProxy != null && ServerConnection.IsHttps) requestLines.AppendLine($"{Request.Method} {Request.RequestUri.PathAndQuery} HTTP/{Request.HttpVersion.Major}.{Request.HttpVersion.Minor}");
{
requestLines.AppendLine($"{Request.Method} {Request.RequestUri.AbsoluteUri} HTTP/{Request.HttpVersion.Major}.{Request.HttpVersion.Minor}");
}
else
{
requestLines.AppendLine($"{Request.Method} {Request.RequestUri.PathAndQuery} HTTP/{Request.HttpVersion.Major}.{Request.HttpVersion.Minor}");
}
//Send Authentication to Upstream proxy if needed //Send Authentication to Upstream proxy if needed
if (ServerConnection.UpStreamHttpProxy != null && ServerConnection.IsHttps == false && !string.IsNullOrEmpty(ServerConnection.UpStreamHttpProxy.UserName) && ServerConnection.UpStreamHttpProxy.Password != null) if (ServerConnection.UpStreamHttpProxy != null
&& ServerConnection.IsHttps == false
&& !string.IsNullOrEmpty(ServerConnection.UpStreamHttpProxy.UserName)
&& ServerConnection.UpStreamHttpProxy.Password != null)
{ {
requestLines.AppendLine("Proxy-Connection: keep-alive"); requestLines.AppendLine("Proxy-Connection: keep-alive");
requestLines.AppendLine("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes( requestLines.AppendLine("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(
......
...@@ -33,9 +33,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -33,9 +33,11 @@ namespace Titanium.Web.Proxy.Http
public bool HasBody => Method == "POST" || Method == "PUT" || Method == "PATCH"; public bool HasBody => Method == "POST" || Method == "PUT" || Method == "PATCH";
/// <summary> /// <summary>
/// Request Http hostanem /// Http hostname header value if exists
/// Note: Changing this does NOT change host in RequestUri
/// Users can set new RequestUri separately
/// </summary> /// </summary>
internal string Host public string Host
{ {
get get
{ {
...@@ -57,9 +59,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -57,9 +59,9 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary> /// <summary>
/// Request content encoding /// Content encoding header value
/// </summary> /// </summary>
internal string ContentEncoding public string ContentEncoding
{ {
get get
{ {
...@@ -231,7 +233,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -231,7 +233,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Encoding for this request /// Encoding for this request
/// </summary> /// </summary>
internal Encoding Encoding => this.GetEncoding(); public Encoding Encoding => this.GetEncoding();
/// <summary> /// <summary>
/// Terminates the underlying Tcp Connection to client after current request /// Terminates the underlying Tcp Connection to client after current request
...@@ -261,7 +263,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -261,7 +263,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Does this request has an upgrade to websocket header? /// Does this request has an upgrade to websocket header?
/// </summary> /// </summary>
internal bool UpgradeToWebSocket public bool UpgradeToWebSocket
{ {
get get
{ {
......
...@@ -23,12 +23,15 @@ namespace Titanium.Web.Proxy.Http ...@@ -23,12 +23,15 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public string ResponseStatusDescription { get; set; } public string ResponseStatusDescription { get; set; }
internal Encoding Encoding => this.GetResponseCharacterEncoding(); /// <summary>
/// Encoding used in response
/// </summary>
public Encoding Encoding => this.GetResponseCharacterEncoding();
/// <summary> /// <summary>
/// Content encoding for this response /// Content encoding for this response
/// </summary> /// </summary>
internal string ContentEncoding public string ContentEncoding
{ {
get get
{ {
...@@ -41,12 +44,15 @@ namespace Titanium.Web.Proxy.Http ...@@ -41,12 +44,15 @@ namespace Titanium.Web.Proxy.Http
} }
} }
internal Version HttpVersion { get; set; } /// <summary>
/// Http version
/// </summary>
public Version HttpVersion { get; set; }
/// <summary> /// <summary>
/// Keep the connection alive? /// Keep the connection alive?
/// </summary> /// </summary>
internal bool ResponseKeepAlive public bool ResponseKeepAlive
{ {
get get
{ {
...@@ -89,7 +95,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -89,7 +95,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Length of response body /// Length of response body
/// </summary> /// </summary>
internal long ContentLength public long ContentLength
{ {
get get
{ {
...@@ -142,7 +148,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -142,7 +148,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Response transfer-encoding is chunked? /// Response transfer-encoding is chunked?
/// </summary> /// </summary>
internal bool IsChunked public bool IsChunked
{ {
get get
{ {
...@@ -198,14 +204,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -198,14 +204,8 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public Dictionary<string, List<HttpHeader>> NonUniqueResponseHeaders { get; set; } public Dictionary<string, List<HttpHeader>> NonUniqueResponseHeaders { get; set; }
/// <summary>
/// Response network stream
/// </summary>
public Stream ResponseStream { get; set; }
/// <summary> /// <summary>
/// response body contenst as byte array /// response body content as byte array
/// </summary> /// </summary>
internal byte[] ResponseBody { get; set; } internal byte[] ResponseBody { get; set; }
......
This diff is collapsed.
...@@ -6,6 +6,7 @@ using System.Net; ...@@ -6,6 +6,7 @@ using System.Net;
using System.Net.Security; using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.Authentication; using System.Security.Authentication;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
...@@ -236,12 +237,12 @@ namespace Titanium.Web.Proxy ...@@ -236,12 +237,12 @@ namespace Titanium.Web.Proxy
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param> /// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param> /// <param name="clientStreamWriter"></param>
/// <param name="httpsHostName"></param> /// <param name="httpsConnectHostname"></param>
/// <param name="endPoint"></param> /// <param name="endPoint"></param>
/// <param name="connectHeaders"></param> /// <param name="connectHeaders"></param>
/// <returns></returns> /// <returns></returns>
private async Task<bool> HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, private async Task<bool> HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsHostName, CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsConnectHostname,
ProxyEndPoint endPoint, List<HttpHeader> connectHeaders) ProxyEndPoint endPoint, List<HttpHeader> connectHeaders)
{ {
bool disposed = false; bool disposed = false;
...@@ -299,9 +300,9 @@ namespace Titanium.Web.Proxy ...@@ -299,9 +300,9 @@ namespace Titanium.Web.Proxy
//Read the request headers in to unique and non-unique header collections //Read the request headers in to unique and non-unique header collections
await HeaderParser.ReadHeaders(clientStreamReader, args.WebSession.Request.NonUniqueRequestHeaders, args.WebSession.Request.RequestHeaders); await HeaderParser.ReadHeaders(clientStreamReader, args.WebSession.Request.NonUniqueRequestHeaders, args.WebSession.Request.RequestHeaders);
var httpRemoteUri = new Uri(httpsHostName == null var httpRemoteUri = new Uri(httpsConnectHostname == null
? httpCmdSplit[1] ? httpCmdSplit[1]
: string.Concat("https://", args.WebSession.Request.Host ?? httpsHostName, httpCmdSplit[1])); : string.Concat("https://", args.WebSession.Request.Host ?? httpsConnectHostname, httpCmdSplit[1]));
args.WebSession.Request.RequestUri = httpRemoteUri; args.WebSession.Request.RequestUri = httpRemoteUri;
...@@ -311,7 +312,8 @@ namespace Titanium.Web.Proxy ...@@ -311,7 +312,8 @@ namespace Titanium.Web.Proxy
args.ProxyClient.ClientStreamReader = clientStreamReader; args.ProxyClient.ClientStreamReader = clientStreamReader;
args.ProxyClient.ClientStreamWriter = clientStreamWriter; args.ProxyClient.ClientStreamWriter = clientStreamWriter;
if (httpsHostName == null && //proxy authorization check
if (httpsConnectHostname == null &&
await CheckAuthorization(clientStreamWriter, await CheckAuthorization(clientStreamWriter,
args.WebSession.Request.RequestHeaders.Values) == false) args.WebSession.Request.RequestHeaders.Values) == false)
{ {
...@@ -338,6 +340,12 @@ namespace Titanium.Web.Proxy ...@@ -338,6 +340,12 @@ namespace Titanium.Web.Proxy
await BeforeRequest.InvokeParallelAsync(this, args); await BeforeRequest.InvokeParallelAsync(this, args);
} }
if (args.WebSession.Request.CancelRequest)
{
args.Dispose();
break;
}
//if upgrading to websocket then relay the requet without reading the contents //if upgrading to websocket then relay the requet without reading the contents
if (args.WebSession.Request.UpgradeToWebSocket) if (args.WebSession.Request.UpgradeToWebSocket)
{ {
...@@ -354,6 +362,14 @@ namespace Titanium.Web.Proxy ...@@ -354,6 +362,14 @@ namespace Titanium.Web.Proxy
{ {
connection = await GetServerConnection(args); connection = await GetServerConnection(args);
} }
//create a new connection if hostname changes
else if (!connection.HostName.Equals(args.WebSession.Request.RequestUri.Host,
StringComparison.OrdinalIgnoreCase))
{
connection.Dispose();
Interlocked.Decrement(ref serverConnectionCount);
connection = await GetServerConnection(args);
}
//construct the web request that we are going to issue on behalf of the client. //construct the web request that we are going to issue on behalf of the client.
disposed = await HandleHttpSessionRequestInternal(connection, args, false); disposed = await HandleHttpSessionRequestInternal(connection, args, false);
...@@ -364,13 +380,7 @@ namespace Titanium.Web.Proxy ...@@ -364,13 +380,7 @@ namespace Titanium.Web.Proxy
args.Dispose(); args.Dispose();
break; break;
} }
if (args.WebSession.Request.CancelRequest)
{
args.Dispose();
break;
}
//if connection is closing exit //if connection is closing exit
if (args.WebSession.Response.ResponseKeepAlive == false) if (args.WebSession.Response.ResponseKeepAlive == false)
{ {
...@@ -415,12 +425,6 @@ namespace Titanium.Web.Proxy ...@@ -415,12 +425,6 @@ namespace Titanium.Web.Proxy
{ {
args.WebSession.Request.RequestLocked = true; args.WebSession.Request.RequestLocked = true;
//If request was cancelled by user then dispose the client
if (args.WebSession.Request.CancelRequest)
{
return true;
}
//if expect continue is enabled then send the headers first //if expect continue is enabled then send the headers first
//and see if server would return 100 conitinue //and see if server would return 100 conitinue
if (args.WebSession.Request.ExpectContinue) if (args.WebSession.Request.ExpectContinue)
......
...@@ -31,11 +31,6 @@ namespace Titanium.Web.Proxy ...@@ -31,11 +31,6 @@ namespace Titanium.Web.Proxy
//read response & headers from server //read response & headers from server
await args.WebSession.ReceiveResponse(); await args.WebSession.ReceiveResponse();
if (!args.WebSession.Response.ResponseBodyRead)
{
args.WebSession.Response.ResponseStream = args.WebSession.ServerConnection.Stream;
}
//check for windows authentication //check for windows authentication
if(EnableWinAuth if(EnableWinAuth
&& !RunTime.IsRunningOnMono && !RunTime.IsRunningOnMono
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Net" /> <Reference Include="System.Net" />
<Reference Include="System.configuration" /> <Reference Include="System.Configuration" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
...@@ -79,8 +79,12 @@ ...@@ -79,8 +79,12 @@
<Compile Include="Extensions\StringExtensions.cs" /> <Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Helpers\BufferPool.cs" /> <Compile Include="Helpers\BufferPool.cs" />
<Compile Include="Helpers\CustomBufferedStream.cs" /> <Compile Include="Helpers\CustomBufferedStream.cs" />
<Compile Include="Helpers\ProxyInfo.cs" />
<Compile Include="Helpers\WinHttp\NativeMethods.WinHttp.cs" />
<Compile Include="Helpers\Network.cs" /> <Compile Include="Helpers\Network.cs" />
<Compile Include="Helpers\RunTime.cs" /> <Compile Include="Helpers\RunTime.cs" />
<Compile Include="Helpers\WinHttp\WinHttpHandle.cs" />
<Compile Include="Helpers\WinHttp\WinHttpWebProxyFinder.cs" />
<Compile Include="Http\HeaderParser.cs" /> <Compile Include="Http\HeaderParser.cs" />
<Compile Include="Http\Responses\GenericResponse.cs" /> <Compile Include="Http\Responses\GenericResponse.cs" />
<Compile Include="Network\CachedCertificate.cs" /> <Compile Include="Network\CachedCertificate.cs" />
...@@ -129,7 +133,7 @@ ...@@ -129,7 +133,7 @@
<Compile Include="WinAuthHandler.cs" /> <Compile Include="WinAuthHandler.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<COMReference Include="CERTENROLLLib"> <COMReference Include="CERTENROLLLib" Condition="'$(OS)' != 'Unix'">
<Guid>{728AB348-217D-11DA-B2A4-000E7BBB2B09}</Guid> <Guid>{728AB348-217D-11DA-B2A4-000E7BBB2B09}</Guid>
<VersionMajor>1</VersionMajor> <VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor> <VersionMinor>0</VersionMinor>
...@@ -159,4 +163,4 @@ ...@@ -159,4 +163,4 @@
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>
\ No newline at end of file
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
<title>Titanium web proxy</title> <title>Titanium web proxy</title>
<authors>Titanium</authors> <authors>Titanium</authors>
<owners>Titanium</owners> <owners>Titanium</owners>
<licenseUrl>https://github.com/titanium007/Titanium/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/justcoding121/Titanium-Web-Proxy/blob/develop/LICENSE</licenseUrl>
<projectUrl>https://github.com/titanium007/Titanium/</projectUrl> <projectUrl>https://github.com/justcoding121/Titanium-Web-Proxy</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Titanium is a light weight web proxy.</description> <description>Titanium is a light weight web proxy.</description>
<releaseNotes></releaseNotes> <releaseNotes></releaseNotes>
...@@ -20,4 +20,4 @@ ...@@ -20,4 +20,4 @@
<files> <files>
<file src="bin\$configuration$\Titanium.Web.Proxy.dll" target="lib\net45" /> <file src="bin\$configuration$\Titanium.Web.Proxy.dll" target="lib\net45" />
</files> </files>
</package> </package>
\ No newline at end of file
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