Commit 734d85df authored by Honfika's avatar Honfika

- Create less TcpRow objects

- Use static Http Verion objects
- Common HTTP header parser (request, response)
- Code duplication removed from ProxyAuthorizationHandler
- Fix? for issue #227
parent a49370d6
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
...@@ -106,14 +107,14 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -106,14 +107,14 @@ namespace Titanium.Web.Proxy.Examples.Basic
//intecept & cancel redirect or update requests //intecept & cancel redirect or update requests
public async Task OnRequest(object sender, SessionEventArgs e) 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); Console.WriteLine(e.WebSession.Request.Url);
//read request headers //read request headers
var requestHeaders = e.WebSession.Request.RequestHeaders; var requestHeaders = e.WebSession.Request.RequestHeaders;
var method = e.WebSession.Request.Method.ToUpper(); 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 //Get/Set request body bytes
byte[] bodyBytes = await e.GetRequestBody(); byte[] bodyBytes = await e.GetRequestBody();
...@@ -168,7 +169,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -168,7 +169,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
if (e.WebSession.Response.ResponseStatusCode == "200") 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(); byte[] bodyBytes = await e.GetResponseBody();
await e.SetResponseBody(bodyBytes); await e.SetResponseBody(bodyBytes);
......
...@@ -93,7 +93,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -93,7 +93,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
//GET request don't have a request body to read //GET request don't have a request body to read
var method = WebSession.Request.Method.ToUpper(); 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. " + throw new BodyNotFoundException("Request don't have a body. " +
"Please verify that this request is a Http POST/PUT/PATCH and request " + "Please verify that this request is a Http POST/PUT/PATCH and request " +
...@@ -411,6 +411,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -411,6 +411,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
response.ResponseHeaders = headers; response.ResponseHeaders = headers;
} }
response.HttpVersion = WebSession.Request.HttpVersion; response.HttpVersion = WebSession.Request.HttpVersion;
response.ResponseBody = result; response.ResponseBody = result;
......
using System.Net.Sockets; using System.Net.Sockets;
using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
...@@ -32,5 +33,25 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -32,5 +33,25 @@ namespace Titanium.Web.Proxy.Extensions
client.Blocking = blockingState; client.Blocking = blockingState;
} }
} }
/// <summary>
/// Gets the local port from a native TCP row object.
/// </summary>
/// <param name="tcpRow">The TCP row.</param>
/// <returns>The local port</returns>
internal static int GetLocalPort(this NativeMethods.TcpRow tcpRow)
{
return (tcpRow.localPort1 << 8) + tcpRow.localPort2 + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
}
/// <summary>
/// Gets the remote port from a native TCP row object.
/// </summary>
/// <param name="tcpRow">The TCP row.</param>
/// <returns>The remote port</returns>
internal static int GetRemotePort(this NativeMethods.TcpRow tcpRow)
{
return (tcpRow.remotePort1 << 8) + tcpRow.remotePort2 + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
}
} }
} }
...@@ -123,9 +123,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -123,9 +123,11 @@ namespace Titanium.Web.Proxy.Helpers
int bytesToRead = bufferSize; int bytesToRead = bufferSize;
if (totalBytesToRead < bufferSize) if (totalBytesToRead < bufferSize)
{
bytesToRead = (int) totalBytesToRead; bytesToRead = (int) totalBytesToRead;
}
var buffer = staticBuffer; var buffer = new byte[bytesToRead];
int bytesRead; int bytesRead;
var totalBytesRead = 0; var totalBytesRead = 0;
......
...@@ -168,6 +168,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -168,6 +168,7 @@ namespace Titanium.Web.Proxy.Helpers
if (bufferLength > 0) if (bufferLength > 0)
{ {
await destination.WriteAsync(streamBuffer, bufferPos, bufferLength, cancellationToken); await destination.WriteAsync(streamBuffer, bufferPos, bufferLength, cancellationToken);
bufferLength = 0;
} }
await baseStream.CopyToAsync(destination, bufferSize, cancellationToken); await baseStream.CopyToAsync(destination, bufferSize, cancellationToken);
...@@ -307,6 +308,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -307,6 +308,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns> /// <returns>
/// A task that represents the asynchronous write operation. /// A task that represents the asynchronous write operation.
/// </returns> /// </returns>
[DebuggerStepThrough]
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
return baseStream.WriteAsync(buffer, offset, count, cancellationToken); return baseStream.WriteAsync(buffer, offset, count, cancellationToken);
......
...@@ -8,8 +8,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -8,8 +8,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
private static int FindProcessIdFromLocalPort(int port, IpVersion ipVersion) private static int FindProcessIdFromLocalPort(int port, IpVersion ipVersion)
{ {
var tcpRow = TcpHelper.GetExtendedTcpTable(ipVersion).FirstOrDefault( var tcpRow = TcpHelper.GetTcpRowByLocalPort(ipVersion, port);
row => row.LocalEndPoint.Port == port);
return tcpRow?.ProcessId ?? 0; return tcpRow?.ProcessId ?? 0;
} }
......
...@@ -123,6 +123,52 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -123,6 +123,52 @@ namespace Titanium.Web.Proxy.Helpers
return new TcpTable(tcpRows); return new TcpTable(tcpRows);
} }
/// <summary>
/// Gets the TCP row by local port number.
/// </summary>
/// <returns><see cref="TcpRow"/>.</returns>
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;
}
/// <summary> /// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers as prefix /// 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 /// Usefull for websocket requests
......
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<string, List<HttpHeader>> nonUniqueResponseHeaders,
Dictionary<string, HttpHeader> 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<HttpHeader> { existing, newHeader };
nonUniqueResponseHeaders.Add(newHeader.Name, nonUniqueHeaders);
headers.Remove(newHeader.Name);
}
//add to unique header collection
else
{
headers.Add(newHeader.Name, newHeader);
}
}
}
}
}
...@@ -170,10 +170,10 @@ namespace Titanium.Web.Proxy.Http ...@@ -170,10 +170,10 @@ namespace Titanium.Web.Proxy.Http
var httpVersion = httpResult[0].Trim().ToLower(); var httpVersion = httpResult[0].Trim().ToLower();
var version = new Version(1, 1); var version = HttpHeader.Version11;
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;
} }
Response.HttpVersion = version; Response.HttpVersion = version;
...@@ -192,7 +192,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -192,7 +192,8 @@ namespace Titanium.Web.Proxy.Http
await ReceiveResponse(); await ReceiveResponse();
return; return;
} }
else if (Response.ResponseStatusCode.Equals("417")
if (Response.ResponseStatusCode.Equals("417")
&& Response.ResponseStatusDescription.Equals("expectation failed", StringComparison.CurrentCultureIgnoreCase)) && Response.ResponseStatusDescription.Equals("expectation failed", StringComparison.CurrentCultureIgnoreCase))
{ {
//read next line after expectation failed response //read next line after expectation failed response
...@@ -204,36 +205,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -204,36 +205,8 @@ namespace Titanium.Web.Proxy.Http
return; return;
} }
//Read the Response headers
//Read the response headers in to unique and non-unique header collections //Read the response headers in to unique and non-unique header collections
string tmpLine; await HeaderParser.ReadHeaders(ServerConnection.StreamReader, Response.NonUniqueResponseHeaders, Response.ResponseHeaders);
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<HttpHeader> {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);
}
}
} }
} }
} }
...@@ -242,8 +242,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -242,8 +242,8 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
internal string RequestBodyString { get; set; } internal string RequestBodyString { get; set; }
internal bool RequestBodyRead { get; set; } internal bool RequestBodyRead { get; set; }
internal bool RequestLocked { get; set; } internal bool RequestLocked { get; set; }
/// <summary> /// <summary>
......
...@@ -9,6 +9,10 @@ namespace Titanium.Web.Proxy.Models ...@@ -9,6 +9,10 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class HttpHeader public class HttpHeader
{ {
internal static Version Version10 = new Version(1, 0);
internal static Version Version11 = new Version(1, 1);
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
......
using System.Net; using System.Net;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
...@@ -17,24 +18,42 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -17,24 +18,42 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
ProcessId = tcpRow.owningPid; ProcessId = tcpRow.owningPid;
int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16); LocalPort = tcpRow.GetLocalPort();
long localAddress = tcpRow.localAddr; LocalAddress = tcpRow.localAddr;
LocalEndPoint = new IPEndPoint(localAddress, localPort);
int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16); RemotePort = tcpRow.GetRemotePort();
long remoteAddress = tcpRow.remoteAddr; RemoteAddress = tcpRow.remoteAddr;
RemoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
} }
/// <summary>
/// Gets the local end point address.
/// </summary>
internal long LocalAddress { get; }
/// <summary>
/// Gets the local end point port.
/// </summary>
internal int LocalPort { get; }
/// <summary> /// <summary>
/// Gets the local end point. /// Gets the local end point.
/// </summary> /// </summary>
internal IPEndPoint LocalEndPoint { get; } internal IPEndPoint LocalEndPoint => new IPEndPoint(LocalAddress, LocalPort);
/// <summary>
/// Gets the remote end point address.
/// </summary>
internal long RemoteAddress { get; }
/// <summary>
/// Gets the remote end point port.
/// </summary>
internal int RemotePort { get; }
/// <summary> /// <summary>
/// Gets the remote end point. /// Gets the remote end point.
/// </summary> /// </summary>
internal IPEndPoint RemoteEndPoint { get; } internal IPEndPoint RemoteEndPoint => new IPEndPoint(RemoteAddress, RemotePort);
/// <summary> /// <summary>
/// Gets the process identifier. /// Gets the process identifier.
......
...@@ -19,78 +19,36 @@ namespace Titanium.Web.Proxy ...@@ -19,78 +19,36 @@ namespace Titanium.Web.Proxy
return true; return true;
} }
var httpHeaders = headers as HttpHeader[] ?? headers.ToArray(); var httpHeaders = headers as ICollection<HttpHeader> ?? headers.ToArray();
try try
{ {
if (httpHeaders.All(t => t.Name != "Proxy-Authorization")) if (httpHeaders.All(t => t.Name != "Proxy-Authorization"))
{ {
await WriteResponseStatus(new Version(1, 1), "407", await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Required");
"Proxy Authentication Required", clientStreamWriter);
var response = new Response
{
ResponseHeaders = new Dictionary<string, HttpHeader>
{
{
"Proxy-Authenticate",
new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync();
return false; return false;
} }
var header = httpHeaders.FirstOrDefault(t => t.Name == "Proxy-Authorization"); 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(); var headerValue = header.Value.Trim();
if (!headerValue.StartsWith("basic", StringComparison.CurrentCultureIgnoreCase)) if (!headerValue.StartsWith("basic", StringComparison.CurrentCultureIgnoreCase))
{ {
//Return not authorized //Return not authorized
await WriteResponseStatus(new Version(1, 1), "407", await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid");
"Proxy Authentication Invalid", clientStreamWriter);
var response = new Response
{
ResponseHeaders = new Dictionary<string, HttpHeader>
{
{
"Proxy-Authenticate",
new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync();
return false; return false;
} }
headerValue = headerValue.Substring(5).Trim(); headerValue = headerValue.Substring(5).Trim();
var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue)); var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue));
if (decoded.Contains(":") == false) if (decoded.Contains(":") == false)
{ {
//Return not authorized //Return not authorized
await WriteResponseStatus(new Version(1, 1), "407", await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid");
"Proxy Authentication Invalid", clientStreamWriter);
var response = new Response
{
ResponseHeaders = new Dictionary<string, HttpHeader>
{
{
"Proxy-Authenticate",
new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync();
return false; return false;
} }
var username = decoded.Substring(0, decoded.IndexOf(':')); var username = decoded.Substring(0, decoded.IndexOf(':'));
var password = decoded.Substring(decoded.IndexOf(':') + 1); var password = decoded.Substring(decoded.IndexOf(':') + 1);
return await AuthenticateUserFunc(username, password); return await AuthenticateUserFunc(username, password);
...@@ -98,9 +56,16 @@ namespace Titanium.Web.Proxy ...@@ -98,9 +56,16 @@ namespace Titanium.Web.Proxy
catch (Exception e) catch (Exception e)
{ {
ExceptionFunc(new ProxyAuthorizationException("Error whilst authorizing request", e, httpHeaders)); ExceptionFunc(new ProxyAuthorizationException("Error whilst authorizing request", e, httpHeaders));
//Return not authorized //Return not authorized
await WriteResponseStatus(new Version(1, 1), "407", await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid");
"Proxy Authentication Invalid", clientStreamWriter); return false;
}
}
private async Task SendAuthentication407Response(StreamWriter clientStreamWriter, string description)
{
await WriteResponseStatus(HttpHeader.Version11, "407", description, clientStreamWriter);
var response = new Response var response = new Response
{ {
ResponseHeaders = new Dictionary<string, HttpHeader> ResponseHeaders = new Dictionary<string, HttpHeader>
...@@ -112,8 +77,6 @@ namespace Titanium.Web.Proxy ...@@ -112,8 +77,6 @@ namespace Titanium.Web.Proxy
await WriteResponseHeaders(clientStreamWriter, response); await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
return false;
}
} }
} }
} }
...@@ -57,14 +57,14 @@ namespace Titanium.Web.Proxy ...@@ -57,14 +57,14 @@ namespace Titanium.Web.Proxy
httpRemoteUri = httpVerb == "CONNECT" ? new Uri("http://" + httpCmdSplit[1]) : new Uri(httpCmdSplit[1]); httpRemoteUri = httpVerb == "CONNECT" ? new Uri("http://" + httpCmdSplit[1]) : new Uri(httpCmdSplit[1]);
//parse the HTTP version //parse the HTTP version
var version = new Version(1, 1); var version = HttpHeader.Version11;
if (httpCmdSplit.Length == 3) if (httpCmdSplit.Length == 3)
{ {
var httpVersion = httpCmdSplit[2].Trim(); 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 @@ namespace Titanium.Web.Proxy ...@@ -87,8 +87,8 @@ namespace Titanium.Web.Proxy
if (httpVerb == "CONNECT" && !excluded && httpRemoteUri.Port != 80) if (httpVerb == "CONNECT" && !excluded && httpRemoteUri.Port != 80)
{ {
httpRemoteUri = new Uri("https://" + httpCmdSplit[1]); httpRemoteUri = new Uri("https://" + httpCmdSplit[1]);
string tmpLine;
connectRequestHeaders = new List<HttpHeader>(); connectRequestHeaders = new List<HttpHeader>();
string tmpLine;
while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync())) while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync()))
{ {
var header = tmpLine.Split(ProxyConstants.ColonSplit, 2); var header = tmpLine.Split(ProxyConstants.ColonSplit, 2);
...@@ -432,50 +432,22 @@ namespace Titanium.Web.Proxy ...@@ -432,50 +432,22 @@ namespace Titanium.Web.Proxy
var httpMethod = httpCmdSplit[0]; var httpMethod = httpCmdSplit[0];
//find the request HTTP version //find the request HTTP version
var httpVersion = new Version(1, 1); var httpVersion = HttpHeader.Version11;
if (httpCmdSplit.Length == 3) 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 //Read the request headers in to unique and non-unique header collections
string tmpLine; await HeaderParser.ReadHeaders(clientStreamReader, args.WebSession.Request.NonUniqueRequestHeaders, args.WebSession.Request.RequestHeaders);
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<HttpHeader> { 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);
}
}
var httpRemoteUri = new Uri(httpsHostName == null ? httpCmdSplit[1] 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; args.WebSession.Request.RequestUri = httpRemoteUri;
...@@ -485,8 +457,7 @@ namespace Titanium.Web.Proxy ...@@ -485,8 +457,7 @@ namespace Titanium.Web.Proxy
args.ProxyClient.ClientStreamReader = clientStreamReader; args.ProxyClient.ClientStreamReader = clientStreamReader;
args.ProxyClient.ClientStreamWriter = clientStreamWriter; args.ProxyClient.ClientStreamWriter = clientStreamWriter;
if (httpsHostName == null && if (httpsHostName == null && await CheckAuthorization(clientStreamWriter, args.WebSession.Request.RequestHeaders.Values) == false)
(await CheckAuthorization(clientStreamWriter, args.WebSession.Request.RequestHeaders.Values) == false))
{ {
Dispose(clientStream, Dispose(clientStream,
clientStreamReader, clientStreamReader,
......
...@@ -9,7 +9,6 @@ using Titanium.Web.Proxy.Exceptions; ...@@ -9,7 +9,6 @@ using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using System.Net.Sockets;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
<Compile Include="Helpers\CustomBufferedStream.cs" /> <Compile Include="Helpers\CustomBufferedStream.cs" />
<Compile Include="Helpers\Network.cs" /> <Compile Include="Helpers\Network.cs" />
<Compile Include="Helpers\RunTime.cs" /> <Compile Include="Helpers\RunTime.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" />
<Compile Include="Network\Certificate\WinCertificateMaker.cs" /> <Compile Include="Network\Certificate\WinCertificateMaker.cs" />
......
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