diff --git a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs index b2d821def..0daadd298 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs +++ b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Net; using System.Threading.Tasks; using Titanium.Web.Proxy.EventArguments; @@ -106,14 +107,14 @@ public void Stop() //intecept & cancel redirect or update requests public async Task OnRequest(object sender, SessionEventArgs e) { - Console.WriteLine("Active Client Connections:" + (sender as ProxyServer).ClientConnectionCount); + Console.WriteLine("Active Client Connections:" + ((ProxyServer) sender).ClientConnectionCount); Console.WriteLine(e.WebSession.Request.Url); //read request headers var requestHeaders = e.WebSession.Request.RequestHeaders; var method = e.WebSession.Request.Method.ToUpper(); - if ((method == "POST" || method == "PUT" || method == "PATCH")) + if (method == "POST" || method == "PUT" || method == "PATCH") { //Get/Set request body bytes byte[] bodyBytes = await e.GetRequestBody(); @@ -168,7 +169,7 @@ public async Task OnResponse(object sender, SessionEventArgs e) { if (e.WebSession.Response.ResponseStatusCode == "200") { - if (e.WebSession.Response.ContentType!=null && e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html")) + if (e.WebSession.Response.ContentType != null && e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html")) { byte[] bodyBytes = await e.GetResponseBody(); await e.SetResponseBody(bodyBytes); diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs index fda283883..f70bf8550 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs @@ -93,7 +93,7 @@ private async Task ReadRequestBody() { //GET request don't have a request body to read var method = WebSession.Request.Method.ToUpper(); - if ((method != "POST" && method != "PUT" && method != "PATCH")) + 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/PATCH and request " + @@ -411,6 +411,7 @@ public async Task Ok(byte[] result, Dictionary headers) { response.ResponseHeaders = headers; } + response.HttpVersion = WebSession.Request.HttpVersion; response.ResponseBody = result; diff --git a/Titanium.Web.Proxy/Extensions/TcpExtensions.cs b/Titanium.Web.Proxy/Extensions/TcpExtensions.cs index 7657aadea..8dc4d5a64 100644 --- a/Titanium.Web.Proxy/Extensions/TcpExtensions.cs +++ b/Titanium.Web.Proxy/Extensions/TcpExtensions.cs @@ -1,4 +1,5 @@ using System.Net.Sockets; +using Titanium.Web.Proxy.Helpers; namespace Titanium.Web.Proxy.Extensions { @@ -32,5 +33,25 @@ internal static bool IsConnected(this Socket client) client.Blocking = blockingState; } } + + /// + /// Gets the local port from a native TCP row object. + /// + /// The TCP row. + /// The local port + internal static int GetLocalPort(this NativeMethods.TcpRow tcpRow) + { + return (tcpRow.localPort1 << 8) + tcpRow.localPort2 + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16); + } + + /// + /// Gets the remote port from a native TCP row object. + /// + /// The TCP row. + /// The remote port + internal static int GetRemotePort(this NativeMethods.TcpRow tcpRow) + { + return (tcpRow.remotePort1 << 8) + tcpRow.remotePort2 + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16); + } } } diff --git a/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs b/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs index 77028ec46..6d10c3d91 100644 --- a/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs +++ b/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs @@ -15,27 +15,14 @@ internal class CustomBinaryReader : IDisposable { private readonly CustomBufferedStream stream; private readonly int bufferSize; + private readonly byte[] staticBuffer; private readonly Encoding encoding; - [ThreadStatic] - private static byte[] staticBufferField; - - private byte[] staticBuffer - { - get - { - if (staticBufferField == null || staticBufferField.Length != bufferSize) - { - staticBufferField = new byte[bufferSize]; - } - - return staticBufferField; - } - } - internal CustomBinaryReader(CustomBufferedStream stream, int bufferSize) { this.stream = stream; + staticBuffer = new byte[bufferSize]; + this.bufferSize = bufferSize; //default to UTF-8 @@ -122,10 +109,13 @@ internal async Task ReadBytesAsync(long totalBytesToRead) { int bytesToRead = bufferSize; + var buffer = staticBuffer; if (totalBytesToRead < bufferSize) + { bytesToRead = (int) totalBytesToRead; + buffer = new byte[bytesToRead]; + } - var buffer = staticBuffer; int bytesRead; var totalBytesRead = 0; diff --git a/Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs b/Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs index 825faa5eb..78fa6db21 100644 --- a/Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs +++ b/Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs @@ -168,6 +168,7 @@ public override async Task CopyToAsync(Stream destination, int bufferSize, Cance if (bufferLength > 0) { await destination.WriteAsync(streamBuffer, bufferPos, bufferLength, cancellationToken); + bufferLength = 0; } await baseStream.CopyToAsync(destination, bufferSize, cancellationToken); @@ -307,6 +308,7 @@ public byte ReadByteFromBuffer() /// /// A task that represents the asynchronous write operation. /// + [DebuggerStepThrough] public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { return baseStream.WriteAsync(buffer, offset, count, cancellationToken); diff --git a/Titanium.Web.Proxy/Helpers/Network.cs b/Titanium.Web.Proxy/Helpers/Network.cs index 121926813..7ee2d9a55 100644 --- a/Titanium.Web.Proxy/Helpers/Network.cs +++ b/Titanium.Web.Proxy/Helpers/Network.cs @@ -8,8 +8,7 @@ internal class NetworkHelper { private static int FindProcessIdFromLocalPort(int port, IpVersion ipVersion) { - var tcpRow = TcpHelper.GetExtendedTcpTable(ipVersion).FirstOrDefault( - row => row.LocalEndPoint.Port == port); + var tcpRow = TcpHelper.GetTcpRowByLocalPort(ipVersion, port); return tcpRow?.ProcessId ?? 0; } diff --git a/Titanium.Web.Proxy/Helpers/Tcp.cs b/Titanium.Web.Proxy/Helpers/Tcp.cs index 2147e7290..5261ec338 100644 --- a/Titanium.Web.Proxy/Helpers/Tcp.cs +++ b/Titanium.Web.Proxy/Helpers/Tcp.cs @@ -123,6 +123,52 @@ internal static TcpTable GetExtendedTcpTable(IpVersion ipVersion) return new TcpTable(tcpRows); } + /// + /// Gets the TCP row by local port number. + /// + /// . + internal static TcpRow GetTcpRowByLocalPort(IpVersion ipVersion, int localPort) + { + IntPtr tcpTable = IntPtr.Zero; + int tcpTableLength = 0; + + var ipVersionValue = ipVersion == IpVersion.Ipv4 ? NativeMethods.AfInet : NativeMethods.AfInet6; + + if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) != 0) + { + try + { + tcpTable = Marshal.AllocHGlobal(tcpTableLength); + if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) == 0) + { + NativeMethods.TcpTable table = (NativeMethods.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(NativeMethods.TcpTable)); + + IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length)); + + for (int i = 0; i < table.length; ++i) + { + var tcpRow = (NativeMethods.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(NativeMethods.TcpRow)); + if (tcpRow.GetLocalPort() == localPort) + { + return new TcpRow(tcpRow); + } + + rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(NativeMethods.TcpRow))); + } + } + } + finally + { + if (tcpTable != IntPtr.Zero) + { + Marshal.FreeHGlobal(tcpTable); + } + } + } + + return null; + } + /// /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers as prefix /// Usefull for websocket requests diff --git a/Titanium.Web.Proxy/Http/HeaderParser.cs b/Titanium.Web.Proxy/Http/HeaderParser.cs new file mode 100644 index 000000000..27d8e051a --- /dev/null +++ b/Titanium.Web.Proxy/Http/HeaderParser.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Titanium.Web.Proxy.Helpers; +using Titanium.Web.Proxy.Models; +using Titanium.Web.Proxy.Shared; + +namespace Titanium.Web.Proxy.Http +{ + internal static class HeaderParser + { + internal static async Task ReadHeaders(CustomBinaryReader reader, + Dictionary> nonUniqueResponseHeaders, + Dictionary headers) + { + string tmpLine; + while (!string.IsNullOrEmpty(tmpLine = await reader.ReadLineAsync())) + { + var header = tmpLine.Split(ProxyConstants.ColonSplit, 2); + + var newHeader = new HttpHeader(header[0], header[1]); + + //if header exist in non-unique header collection add it there + if (nonUniqueResponseHeaders.ContainsKey(newHeader.Name)) + { + nonUniqueResponseHeaders[newHeader.Name].Add(newHeader); + } + //if header is alread in unique header collection then move both to non-unique collection + else if (headers.ContainsKey(newHeader.Name)) + { + var existing = headers[newHeader.Name]; + + var nonUniqueHeaders = new List { existing, newHeader }; + + nonUniqueResponseHeaders.Add(newHeader.Name, nonUniqueHeaders); + headers.Remove(newHeader.Name); + } + //add to unique header collection + else + { + headers.Add(newHeader.Name, newHeader); + } + } + } + } +} diff --git a/Titanium.Web.Proxy/Http/HttpWebClient.cs b/Titanium.Web.Proxy/Http/HttpWebClient.cs index b91618223..46aa379c7 100644 --- a/Titanium.Web.Proxy/Http/HttpWebClient.cs +++ b/Titanium.Web.Proxy/Http/HttpWebClient.cs @@ -170,10 +170,10 @@ internal async Task ReceiveResponse() var httpVersion = httpResult[0].Trim().ToLower(); - var version = new Version(1, 1); - if (0 == string.CompareOrdinal(httpVersion, "http/1.0")) + var version = HttpHeader.Version11; + if (string.Equals(httpVersion, "HTTP/1.0", StringComparison.OrdinalIgnoreCase)) { - version = new Version(1, 0); + version = HttpHeader.Version10; } Response.HttpVersion = version; @@ -192,8 +192,9 @@ internal async Task ReceiveResponse() await ReceiveResponse(); return; } - else if (Response.ResponseStatusCode.Equals("417") - && Response.ResponseStatusDescription.Equals("expectation failed", StringComparison.CurrentCultureIgnoreCase)) + + if (Response.ResponseStatusCode.Equals("417") + && Response.ResponseStatusDescription.Equals("expectation failed", StringComparison.CurrentCultureIgnoreCase)) { //read next line after expectation failed response Response.ExpectationFailed = true; @@ -204,36 +205,8 @@ internal async Task ReceiveResponse() return; } - //Read the Response headers //Read the response headers in to unique and non-unique header collections - string tmpLine; - while (!string.IsNullOrEmpty(tmpLine = await ServerConnection.StreamReader.ReadLineAsync())) - { - var header = tmpLine.Split(ProxyConstants.ColonSplit, 2); - - var newHeader = new HttpHeader(header[0], header[1]); - - //if header exist in non-unique header collection add it there - if (Response.NonUniqueResponseHeaders.ContainsKey(newHeader.Name)) - { - Response.NonUniqueResponseHeaders[newHeader.Name].Add(newHeader); - } - //if header is alread in unique header collection then move both to non-unique collection - else if (Response.ResponseHeaders.ContainsKey(newHeader.Name)) - { - var existing = Response.ResponseHeaders[newHeader.Name]; - - var nonUniqueHeaders = new List {existing, newHeader}; - - Response.NonUniqueResponseHeaders.Add(newHeader.Name, nonUniqueHeaders); - Response.ResponseHeaders.Remove(newHeader.Name); - } - //add to unique header collection - else - { - Response.ResponseHeaders.Add(newHeader.Name, newHeader); - } - } + await HeaderParser.ReadHeaders(ServerConnection.StreamReader, Response.NonUniqueResponseHeaders, Response.ResponseHeaders); } } } diff --git a/Titanium.Web.Proxy/Http/Request.cs b/Titanium.Web.Proxy/Http/Request.cs index 8adf03842..949cd5570 100644 --- a/Titanium.Web.Proxy/Http/Request.cs +++ b/Titanium.Web.Proxy/Http/Request.cs @@ -241,9 +241,9 @@ public bool ExpectContinue /// request body as string /// internal string RequestBodyString { get; set; } - - + internal bool RequestBodyRead { get; set; } + internal bool RequestLocked { get; set; } /// diff --git a/Titanium.Web.Proxy/Models/HttpHeader.cs b/Titanium.Web.Proxy/Models/HttpHeader.cs index 6f884e720..c5a678e69 100644 --- a/Titanium.Web.Proxy/Models/HttpHeader.cs +++ b/Titanium.Web.Proxy/Models/HttpHeader.cs @@ -9,6 +9,10 @@ namespace Titanium.Web.Proxy.Models /// public class HttpHeader { + internal static Version Version10 = new Version(1, 0); + + internal static Version Version11 = new Version(1, 1); + /// /// Constructor. /// diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpRow.cs b/Titanium.Web.Proxy/Network/Tcp/TcpRow.cs index 9a8a5f6c3..5bc306c05 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpRow.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpRow.cs @@ -1,4 +1,5 @@ using System.Net; +using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Helpers; namespace Titanium.Web.Proxy.Network.Tcp @@ -17,24 +18,42 @@ internal 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); + LocalPort = tcpRow.GetLocalPort(); + LocalAddress = tcpRow.localAddr; - int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16); - long remoteAddress = tcpRow.remoteAddr; - RemoteEndPoint = new IPEndPoint(remoteAddress, remotePort); + RemotePort = tcpRow.GetRemotePort(); + RemoteAddress = tcpRow.remoteAddr; } + /// + /// Gets the local end point address. + /// + internal long LocalAddress { get; } + + /// + /// Gets the local end point port. + /// + internal int LocalPort { get; } + /// /// Gets the local end point. /// - internal IPEndPoint LocalEndPoint { get; } + internal IPEndPoint LocalEndPoint => new IPEndPoint(LocalAddress, LocalPort); + + /// + /// Gets the remote end point address. + /// + internal long RemoteAddress { get; } + + /// + /// Gets the remote end point port. + /// + internal int RemotePort { get; } /// /// Gets the remote end point. /// - internal IPEndPoint RemoteEndPoint { get; } + internal IPEndPoint RemoteEndPoint => new IPEndPoint(RemoteAddress, RemotePort); /// /// Gets the process identifier. diff --git a/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs b/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs index 9c9a78e4e..c8279925c 100644 --- a/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs +++ b/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs @@ -19,78 +19,36 @@ private async Task CheckAuthorization(StreamWriter clientStreamWriter, IEn return true; } - var httpHeaders = headers as HttpHeader[] ?? headers.ToArray(); + var httpHeaders = headers as ICollection ?? headers.ToArray(); try { if (httpHeaders.All(t => t.Name != "Proxy-Authorization")) { - await WriteResponseStatus(new Version(1, 1), "407", - "Proxy Authentication Required", clientStreamWriter); - var response = new Response - { - ResponseHeaders = new Dictionary - { - { - "Proxy-Authenticate", - new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"") - }, - {"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")} - } - }; - await WriteResponseHeaders(clientStreamWriter, response); - - await clientStreamWriter.WriteLineAsync(); + await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Required"); return false; } + var header = httpHeaders.FirstOrDefault(t => t.Name == "Proxy-Authorization"); - if (null == header) throw new NullReferenceException(); + if (header == null) throw new NullReferenceException(); var headerValue = header.Value.Trim(); if (!headerValue.StartsWith("basic", StringComparison.CurrentCultureIgnoreCase)) { //Return not authorized - await WriteResponseStatus(new Version(1, 1), "407", - "Proxy Authentication Invalid", clientStreamWriter); - var response = new Response - { - ResponseHeaders = new Dictionary - { - { - "Proxy-Authenticate", - new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"") - }, - {"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")} - } - }; - await WriteResponseHeaders(clientStreamWriter, response); - - await clientStreamWriter.WriteLineAsync(); + await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid"); return false; } + headerValue = headerValue.Substring(5).Trim(); var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue)); if (decoded.Contains(":") == false) { //Return not authorized - await WriteResponseStatus(new Version(1, 1), "407", - "Proxy Authentication Invalid", clientStreamWriter); - var response = new Response - { - ResponseHeaders = new Dictionary - { - { - "Proxy-Authenticate", - new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"") - }, - {"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")} - } - }; - await WriteResponseHeaders(clientStreamWriter, response); - - await clientStreamWriter.WriteLineAsync(); + await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid"); return false; } + var username = decoded.Substring(0, decoded.IndexOf(':')); var password = decoded.Substring(decoded.IndexOf(':') + 1); return await AuthenticateUserFunc(username, password); @@ -98,22 +56,27 @@ await WriteResponseStatus(new Version(1, 1), "407", catch (Exception e) { ExceptionFunc(new ProxyAuthorizationException("Error whilst authorizing request", e, httpHeaders)); - //Return not authorized - await WriteResponseStatus(new Version(1, 1), "407", - "Proxy Authentication Invalid", clientStreamWriter); - var response = new Response - { - ResponseHeaders = new Dictionary - { - {"Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")}, - {"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")} - } - }; - await WriteResponseHeaders(clientStreamWriter, response); - await clientStreamWriter.WriteLineAsync(); + //Return not authorized + await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid"); return false; } } + + private async Task SendAuthentication407Response(StreamWriter clientStreamWriter, string description) + { + await WriteResponseStatus(HttpHeader.Version11, "407", description, clientStreamWriter); + var response = new Response + { + ResponseHeaders = new Dictionary + { + {"Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")}, + {"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")} + } + }; + await WriteResponseHeaders(clientStreamWriter, response); + + await clientStreamWriter.WriteLineAsync(); + } } } diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index 846c38b53..624c71546 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -57,14 +57,14 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli httpRemoteUri = httpVerb == "CONNECT" ? new Uri("http://" + httpCmdSplit[1]) : new Uri(httpCmdSplit[1]); //parse the HTTP version - var version = new Version(1, 1); + var version = HttpHeader.Version11; if (httpCmdSplit.Length == 3) { var httpVersion = httpCmdSplit[2].Trim(); - if (0 == string.CompareOrdinal(httpVersion, "http/1.0")) + if (string.Equals(httpVersion, "HTTP/1.0", StringComparison.OrdinalIgnoreCase)) { - version = new Version(1, 0); + version = HttpHeader.Version10; } } @@ -87,8 +87,8 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli if (httpVerb == "CONNECT" && !excluded && httpRemoteUri.Port != 80) { httpRemoteUri = new Uri("https://" + httpCmdSplit[1]); - string tmpLine; connectRequestHeaders = new List(); + string tmpLine; while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync())) { var header = tmpLine.Split(ProxyConstants.ColonSplit, 2); @@ -432,50 +432,22 @@ private async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, St var httpMethod = httpCmdSplit[0]; //find the request HTTP version - var httpVersion = new Version(1, 1); + var httpVersion = HttpHeader.Version11; if (httpCmdSplit.Length == 3) { - var httpVersionString = httpCmdSplit[2].ToLower().Trim(); + var httpVersionString = httpCmdSplit[2].Trim(); - if (0 == string.CompareOrdinal(httpVersionString, "http/1.0")) + if (string.Equals(httpVersionString, "HTTP/1.0", StringComparison.OrdinalIgnoreCase)) { - httpVersion = new Version(1, 0); + httpVersion = HttpHeader.Version10; } } - //Read the request headers in to unique and non-unique header collections - string tmpLine; - while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync())) - { - var header = tmpLine.Split(ProxyConstants.ColonSplit, 2); - - var newHeader = new HttpHeader(header[0], header[1]); - - //if header exist in non-unique header collection add it there - if (args.WebSession.Request.NonUniqueRequestHeaders.ContainsKey(newHeader.Name)) - { - args.WebSession.Request.NonUniqueRequestHeaders[newHeader.Name].Add(newHeader); - } - //if header is alread in unique header collection then move both to non-unique collection - else if (args.WebSession.Request.RequestHeaders.ContainsKey(newHeader.Name)) - { - var existing = args.WebSession.Request.RequestHeaders[newHeader.Name]; - - var nonUniqueHeaders = new List { existing, newHeader }; - - args.WebSession.Request.NonUniqueRequestHeaders.Add(newHeader.Name, nonUniqueHeaders); - args.WebSession.Request.RequestHeaders.Remove(newHeader.Name); - } - //add to unique header collection - else - { - args.WebSession.Request.RequestHeaders.Add(newHeader.Name, newHeader); - } - } + await HeaderParser.ReadHeaders(clientStreamReader, args.WebSession.Request.NonUniqueRequestHeaders, args.WebSession.Request.RequestHeaders); var httpRemoteUri = new Uri(httpsHostName == null ? httpCmdSplit[1] - : (string.Concat("https://", args.WebSession.Request.Host ?? httpsHostName, httpCmdSplit[1]))); + : string.Concat("https://", args.WebSession.Request.Host ?? httpsHostName, httpCmdSplit[1])); args.WebSession.Request.RequestUri = httpRemoteUri; @@ -483,10 +455,9 @@ private async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, St args.WebSession.Request.HttpVersion = httpVersion; args.ProxyClient.ClientStream = clientStream; args.ProxyClient.ClientStreamReader = clientStreamReader; - args.ProxyClient.ClientStreamWriter = clientStreamWriter; + args.ProxyClient.ClientStreamWriter = clientStreamWriter; - if (httpsHostName == null && - (await CheckAuthorization(clientStreamWriter, args.WebSession.Request.RequestHeaders.Values) == false)) + if (httpsHostName == null && await CheckAuthorization(clientStreamWriter, args.WebSession.Request.RequestHeaders.Values) == false) { Dispose(clientStream, clientStreamReader, diff --git a/Titanium.Web.Proxy/ResponseHandler.cs b/Titanium.Web.Proxy/ResponseHandler.cs index 70b22ef28..3a8ac88a8 100644 --- a/Titanium.Web.Proxy/ResponseHandler.cs +++ b/Titanium.Web.Proxy/ResponseHandler.cs @@ -9,7 +9,6 @@ using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Helpers; -using System.Net.Sockets; using Titanium.Web.Proxy.Network.Tcp; namespace Titanium.Web.Proxy diff --git a/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj b/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj index c3eb67485..6b186297c 100644 --- a/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj +++ b/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj @@ -77,6 +77,7 @@ +