Commit 9bac69a9 authored by justcoding121's avatar justcoding121

add more comments

parent 4bcd22fc
...@@ -12,10 +12,24 @@ namespace Titanium.Web.Proxy.Http ...@@ -12,10 +12,24 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class Request public class Request
{ {
/// <summary>
/// Request Method
/// </summary>
public string Method { get; set; } public string Method { get; set; }
/// <summary>
/// Request HTTP Uri
/// </summary>
public Uri RequestUri { get; set; } public Uri RequestUri { get; set; }
/// <summary>
/// Request Http Version
/// </summary>
public Version HttpVersion { get; set; } public Version HttpVersion { get; set; }
/// <summary>
/// Request Http hostanem
/// </summary>
internal string Host internal string Host
{ {
get get
...@@ -35,6 +49,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -35,6 +49,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Request content encoding
/// </summary>
internal string ContentEncoding internal string ContentEncoding
{ {
get get
...@@ -50,6 +67,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -50,6 +67,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Request content-length
/// </summary>
public long ContentLength public long ContentLength
{ {
get get
...@@ -68,7 +88,6 @@ namespace Titanium.Web.Proxy.Http ...@@ -68,7 +88,6 @@ namespace Titanium.Web.Proxy.Http
} }
set set
{ {
var header = RequestHeaders.FirstOrDefault(x => x.Name.ToLower() == "content-length"); var header = RequestHeaders.FirstOrDefault(x => x.Name.ToLower() == "content-length");
if (value >= 0) if (value >= 0)
...@@ -88,6 +107,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -88,6 +107,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Request content-type
/// </summary>
public string ContentType public string ContentType
{ {
get get
...@@ -109,6 +131,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -109,6 +131,9 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary>
/// Is request body send as chunked bytes
/// </summary>
public bool IsChunked public bool IsChunked
{ {
get get
...@@ -140,6 +165,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -140,6 +165,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Does this request has a 100-continue header?
/// </summary>
public bool ExpectContinue public bool ExpectContinue
{ {
get get
...@@ -150,19 +178,37 @@ namespace Titanium.Web.Proxy.Http ...@@ -150,19 +178,37 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Request Url
/// </summary>
public string Url { get { return RequestUri.OriginalString; } } public string Url { get { return RequestUri.OriginalString; } }
/// <summary>
/// Encoding for this request
/// </summary>
internal Encoding Encoding { get { return this.GetEncoding(); } } internal Encoding Encoding { get { return this.GetEncoding(); } }
/// <summary> /// <summary>
/// Terminates the underlying Tcp Connection to client after current request /// Terminates the underlying Tcp Connection to client after current request
/// </summary> /// </summary>
internal bool CancelRequest { get; set; } internal bool CancelRequest { get; set; }
/// <summary>
/// Request body as byte array
/// </summary>
internal byte[] RequestBody { get; set; } internal byte[] RequestBody { get; set; }
/// <summary>
/// request body as string
/// </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>
/// Does this request has an upgrade to websocket header?
/// </summary>
internal bool UpgradeToWebSocket internal bool UpgradeToWebSocket
{ {
get get
...@@ -179,8 +225,19 @@ namespace Titanium.Web.Proxy.Http ...@@ -179,8 +225,19 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Request heade collection
/// </summary>
public List<HttpHeader> RequestHeaders { get; set; } public List<HttpHeader> RequestHeaders { get; set; }
/// <summary>
/// Does server responsed positively for 100 continue request
/// </summary>
public bool Is100Continue { get; internal set; } public bool Is100Continue { get; internal set; }
/// <summary>
/// Server responsed negatively for the request for 100 continue
/// </summary>
public bool ExpectationFailed { get; internal set; } public bool ExpectationFailed { get; internal set; }
public Request() public Request()
......
...@@ -18,7 +18,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -18,7 +18,9 @@ namespace Titanium.Web.Proxy.Http
internal Encoding Encoding { get { return this.GetResponseCharacterEncoding(); } } internal Encoding Encoding { get { return this.GetResponseCharacterEncoding(); } }
/// <summary>
/// Content encoding for this response
/// </summary>
internal string ContentEncoding internal string ContentEncoding
{ {
get get
...@@ -35,6 +37,10 @@ namespace Titanium.Web.Proxy.Http ...@@ -35,6 +37,10 @@ namespace Titanium.Web.Proxy.Http
} }
internal Version HttpVersion { get; set; } internal Version HttpVersion { get; set; }
/// <summary>
/// Keep the connection alive?
/// </summary>
internal bool ResponseKeepAlive internal bool ResponseKeepAlive
{ {
get get
...@@ -51,6 +57,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -51,6 +57,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Content type of this response
/// </summary>
public string ContentType public string ContentType
{ {
get get
...@@ -67,6 +76,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -67,6 +76,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Length of response body
/// </summary>
internal long ContentLength internal long ContentLength
{ {
get get
...@@ -105,6 +117,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -105,6 +117,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Response transfer-encoding is chunked?
/// </summary>
internal bool IsChunked internal bool IsChunked
{ {
get get
...@@ -143,14 +158,37 @@ namespace Titanium.Web.Proxy.Http ...@@ -143,14 +158,37 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Collection of all response headers
/// </summary>
public List<HttpHeader> ResponseHeaders { get; set; } public List<HttpHeader> ResponseHeaders { get; set; }
/// <summary>
/// Response network stream
/// </summary>
internal Stream ResponseStream { get; set; } internal Stream ResponseStream { get; set; }
/// <summary>
/// response body contenst as byte array
/// </summary>
internal byte[] ResponseBody { get; set; } internal byte[] ResponseBody { get; set; }
/// <summary>
/// response body as string
/// </summary>
internal string ResponseBodyString { get; set; } internal string ResponseBodyString { get; set; }
internal bool ResponseBodyRead { get; set; } internal bool ResponseBodyRead { get; set; }
internal bool ResponseLocked { get; set; } internal bool ResponseLocked { get; set; }
/// <summary>
/// Is response 100-continue
/// </summary>
public bool Is100Continue { get; internal set; } public bool Is100Continue { get; internal set; }
/// <summary>
/// expectation failed returned by server?
/// </summary>
public bool ExpectationFailed { get; internal set; } public bool ExpectationFailed { get; internal set; }
public Response() public Response()
......
...@@ -44,7 +44,6 @@ namespace Titanium.Web.Proxy.Network ...@@ -44,7 +44,6 @@ namespace Titanium.Web.Proxy.Network
//Get a unique string to identify this connection //Get a unique string to identify this connection
var key = GetConnectionKey(hostname, port, isHttps, version); var key = GetConnectionKey(hostname, port, isHttps, version);
while (true) while (true)
{ {
await connectionAccessLock.WaitAsync(); await connectionAccessLock.WaitAsync();
...@@ -76,6 +75,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -76,6 +75,7 @@ namespace Titanium.Web.Proxy.Network
} }
if (cached == null) if (cached == null)
cached = await CreateClient(hostname, port, isHttps, version); cached = await CreateClient(hostname, port, isHttps, version);
......
...@@ -351,7 +351,7 @@ namespace Titanium.Web.Proxy ...@@ -351,7 +351,7 @@ namespace Titanium.Web.Proxy
} }
catch catch
{ {
//Other errors are discarded to keep the proxy running //Other errors are discarded to keep proxy running
} }
} }
......
...@@ -18,7 +18,9 @@ using System.Threading.Tasks; ...@@ -18,7 +18,9 @@ using System.Threading.Tasks;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
/// <summary>
/// Handle the requesr
/// </summary>
partial class ProxyServer partial class ProxyServer
{ {
//This is called when client is aware of proxy //This is called when client is aware of proxy
...@@ -43,6 +45,7 @@ namespace Titanium.Web.Proxy ...@@ -43,6 +45,7 @@ namespace Titanium.Web.Proxy
//break up the line into three components (method, remote URL & Http Version) //break up the line into three components (method, remote URL & Http Version)
var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3); var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3);
//Find the request Verb
var httpVerb = httpCmdSplit[0]; var httpVerb = httpCmdSplit[0];
if (httpVerb.ToUpper() == "CONNECT") if (httpVerb.ToUpper() == "CONNECT")
...@@ -50,6 +53,7 @@ namespace Titanium.Web.Proxy ...@@ -50,6 +53,7 @@ namespace Titanium.Web.Proxy
else else
httpRemoteUri = new Uri(httpCmdSplit[1]); httpRemoteUri = new Uri(httpCmdSplit[1]);
//parse the HTTP version
Version version = new Version(1, 1); Version version = new Version(1, 1);
if (httpCmdSplit.Length == 3) if (httpCmdSplit.Length == 3)
{ {
...@@ -76,7 +80,8 @@ namespace Titanium.Web.Proxy ...@@ -76,7 +80,8 @@ namespace Titanium.Web.Proxy
try try
{ {
//create the Tcp Connection to server and then release it to connection cache
//Just doing what CONNECT request is asking as to do
var tunnelClient = await TcpConnectionManager.GetClient(httpRemoteUri.Host, httpRemoteUri.Port, true, version); var tunnelClient = await TcpConnectionManager.GetClient(httpRemoteUri.Host, httpRemoteUri.Port, true, version);
await TcpConnectionManager.ReleaseClient(tunnelClient); await TcpConnectionManager.ReleaseClient(tunnelClient);
...@@ -88,7 +93,6 @@ namespace Titanium.Web.Proxy ...@@ -88,7 +93,6 @@ namespace Titanium.Web.Proxy
//HTTPS server created - we can now decrypt the client's traffic //HTTPS server created - we can now decrypt the client's traffic
clientStream = sslStream; clientStream = sslStream;
clientStreamReader = new CustomBinaryReader(sslStream); clientStreamReader = new CustomBinaryReader(sslStream);
clientStreamWriter = new StreamWriter(sslStream); clientStreamWriter = new StreamWriter(sslStream);
...@@ -102,14 +106,19 @@ namespace Titanium.Web.Proxy ...@@ -102,14 +106,19 @@ namespace Titanium.Web.Proxy
return; return;
} }
//Now read the actual HTTPS request line
httpCmd = await clientStreamReader.ReadLineAsync(); httpCmd = await clientStreamReader.ReadLineAsync();
} }
//Sorry cannot do a HTTPS request decrypt to port 80 at this time
else if (httpVerb.ToUpper() == "CONNECT") else if (httpVerb.ToUpper() == "CONNECT")
{ {
//Cyphen out CONNECT request headers
await clientStreamReader.ReadAllLinesAsync(); await clientStreamReader.ReadAllLinesAsync();
//write back successfull CONNECT response
await WriteConnectResponse(clientStreamWriter, version); await WriteConnectResponse(clientStreamWriter, version);
//Just relay the request/response without decrypting it
await TcpHelper.SendRaw(clientStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port, await TcpHelper.SendRaw(clientStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port,
false); false);
...@@ -179,12 +188,23 @@ namespace Titanium.Web.Proxy ...@@ -179,12 +188,23 @@ namespace Titanium.Web.Proxy
await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter, await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
true); true);
} }
/// <summary>
/// This is the core request handler method for a particular connection from client
/// </summary>
/// <param name="client"></param>
/// <param name="httpCmd"></param>
/// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="isHttps"></param>
/// <returns></returns>
private static async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, private static async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, bool isHttps) CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, bool isHttps)
{ {
TcpConnection connection = null; TcpConnection connection = null;
//Loop through each subsequest request on this particular client connection
//(assuming HTTP connection is kept alive by client)
while (true) while (true)
{ {
if (string.IsNullOrEmpty(httpCmd)) if (string.IsNullOrEmpty(httpCmd))
...@@ -203,6 +223,7 @@ namespace Titanium.Web.Proxy ...@@ -203,6 +223,7 @@ namespace Titanium.Web.Proxy
var httpMethod = httpCmdSplit[0]; var httpMethod = httpCmdSplit[0];
//find the request HTTP version
Version version = new Version(1, 1); Version version = new Version(1, 1);
if (httpCmdSplit.Length == 3) if (httpCmdSplit.Length == 3)
{ {
...@@ -216,6 +237,7 @@ namespace Titanium.Web.Proxy ...@@ -216,6 +237,7 @@ namespace Titanium.Web.Proxy
args.WebSession.Request.RequestHeaders = new List<HttpHeader>(); args.WebSession.Request.RequestHeaders = new List<HttpHeader>();
//Read the request headers
string tmpLine; string tmpLine;
while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync())) while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync()))
{ {
...@@ -225,6 +247,8 @@ namespace Titanium.Web.Proxy ...@@ -225,6 +247,8 @@ namespace Titanium.Web.Proxy
var httpRemoteUri = new Uri(!isHttps ? httpCmdSplit[1] : (string.Concat("https://", args.WebSession.Request.Host, httpCmdSplit[1]))); var httpRemoteUri = new Uri(!isHttps ? httpCmdSplit[1] : (string.Concat("https://", args.WebSession.Request.Host, httpCmdSplit[1])));
#if DEBUG #if DEBUG
//Just ignore local requests while Debugging
//Its annoying
if (httpRemoteUri.Host.Contains("localhost")) if (httpRemoteUri.Host.Contains("localhost"))
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
...@@ -242,7 +266,7 @@ namespace Titanium.Web.Proxy ...@@ -242,7 +266,7 @@ namespace Titanium.Web.Proxy
PrepareRequestHeaders(args.WebSession.Request.RequestHeaders, args.WebSession); PrepareRequestHeaders(args.WebSession.Request.RequestHeaders, args.WebSession);
args.WebSession.Request.Host = args.WebSession.Request.RequestUri.Authority; args.WebSession.Request.Host = args.WebSession.Request.RequestUri.Authority;
//If requested interception //If user requested interception do it
if (BeforeRequest != null) if (BeforeRequest != null)
{ {
Delegate[] invocationList = BeforeRequest.GetInvocationList(); Delegate[] invocationList = BeforeRequest.GetInvocationList();
...@@ -256,6 +280,7 @@ namespace Titanium.Web.Proxy ...@@ -256,6 +280,7 @@ namespace Titanium.Web.Proxy
await Task.WhenAll(handlerTasks); await Task.WhenAll(handlerTasks);
} }
//if upgrading to websocket then relay the requet without reading the contents
if (args.WebSession.Request.UpgradeToWebSocket) if (args.WebSession.Request.UpgradeToWebSocket)
{ {
await TcpHelper.SendRaw(clientStream, httpCmd, args.WebSession.Request.RequestHeaders, await TcpHelper.SendRaw(clientStream, httpCmd, args.WebSession.Request.RequestHeaders,
...@@ -267,21 +292,24 @@ namespace Titanium.Web.Proxy ...@@ -267,21 +292,24 @@ namespace Titanium.Web.Proxy
//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.
connection = await TcpConnectionManager.GetClient(args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, args.IsHttps, version); connection = await TcpConnectionManager.GetClient(args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, args.IsHttps, version);
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) if (args.WebSession.Request.CancelRequest)
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
break; break;
} }
//if expect continue is enabled then send the headers first
//and see if server would return 100 conitinue
if (args.WebSession.Request.ExpectContinue) if (args.WebSession.Request.ExpectContinue)
{ {
args.WebSession.SetConnection(connection); args.WebSession.SetConnection(connection);
await args.WebSession.SendRequest(); await args.WebSession.SendRequest();
} }
//If 100 continue was the response inform that to the client
if (Enable100ContinueBehaviour) if (Enable100ContinueBehaviour)
if (args.WebSession.Request.Is100Continue) if (args.WebSession.Request.Is100Continue)
{ {
...@@ -296,6 +324,7 @@ namespace Titanium.Web.Proxy ...@@ -296,6 +324,7 @@ namespace Titanium.Web.Proxy
await args.ProxyClient.ClientStreamWriter.WriteLineAsync(); await args.ProxyClient.ClientStreamWriter.WriteLineAsync();
} }
//If expect continue is not enabled then set the connectio and send request headers
if (!args.WebSession.Request.ExpectContinue) if (!args.WebSession.Request.ExpectContinue)
{ {
args.WebSession.SetConnection(connection); args.WebSession.SetConnection(connection);
...@@ -327,6 +356,7 @@ namespace Titanium.Web.Proxy ...@@ -327,6 +356,7 @@ namespace Titanium.Web.Proxy
} }
} }
//If not expectation failed response was returned by server then parse response
if (!args.WebSession.Request.ExpectationFailed) if (!args.WebSession.Request.ExpectationFailed)
{ {
await HandleHttpSessionResponse(args); await HandleHttpSessionResponse(args);
...@@ -339,6 +369,7 @@ namespace Titanium.Web.Proxy ...@@ -339,6 +369,7 @@ namespace Titanium.Web.Proxy
return; return;
} }
//send the tcp connection to server back to connection cache for reuse
await TcpConnectionManager.ReleaseClient(connection); await TcpConnectionManager.ReleaseClient(connection);
// read the next request // read the next request
...@@ -355,6 +386,12 @@ namespace Titanium.Web.Proxy ...@@ -355,6 +386,12 @@ namespace Titanium.Web.Proxy
} }
/// <summary>
/// Write successfull CONNECT response to client
/// </summary>
/// <param name="clientStreamWriter"></param>
/// <param name="httpVersion"></param>
/// <returns></returns>
private static async Task WriteConnectResponse(StreamWriter clientStreamWriter, Version httpVersion) private static async Task WriteConnectResponse(StreamWriter clientStreamWriter, Version httpVersion)
{ {
await clientStreamWriter.WriteLineAsync(string.Format("HTTP/{0}.{1} {2}", httpVersion.Major, httpVersion.Minor, "200 Connection established")); await clientStreamWriter.WriteLineAsync(string.Format("HTTP/{0}.{1} {2}", httpVersion.Major, httpVersion.Minor, "200 Connection established"));
...@@ -363,6 +400,11 @@ namespace Titanium.Web.Proxy ...@@ -363,6 +400,11 @@ namespace Titanium.Web.Proxy
await clientStreamWriter.FlushAsync(); await clientStreamWriter.FlushAsync();
} }
/// <summary>
/// prepare the request headers so that we can avoid encodings not parsable by this proxy
/// </summary>
/// <param name="requestHeaders"></param>
/// <param name="webRequest"></param>
private static void PrepareRequestHeaders(List<HttpHeader> requestHeaders, HttpWebClient webRequest) private static void PrepareRequestHeaders(List<HttpHeader> requestHeaders, HttpWebClient webRequest)
{ {
for (var i = 0; i < requestHeaders.Count; i++) for (var i = 0; i < requestHeaders.Count; i++)
...@@ -381,6 +423,11 @@ namespace Titanium.Web.Proxy ...@@ -381,6 +423,11 @@ namespace Titanium.Web.Proxy
FixRequestProxyHeaders(requestHeaders); FixRequestProxyHeaders(requestHeaders);
webRequest.Request.RequestHeaders = requestHeaders; webRequest.Request.RequestHeaders = requestHeaders;
} }
/// <summary>
/// Fix proxy specific headers
/// </summary>
/// <param name="headers"></param>
private static void FixRequestProxyHeaders(List<HttpHeader> headers) private static void FixRequestProxyHeaders(List<HttpHeader> headers)
{ {
//If proxy-connection close was returned inform to close the connection //If proxy-connection close was returned inform to close the connection
...@@ -400,7 +447,11 @@ namespace Titanium.Web.Proxy ...@@ -400,7 +447,11 @@ namespace Titanium.Web.Proxy
headers.RemoveAll(x => x.Name.ToLower() == "proxy-connection"); headers.RemoveAll(x => x.Name.ToLower() == "proxy-connection");
} }
//This is called when the request is PUT/POST to read the body /// <summary>
/// This is called when the request is PUT/POST to read the body
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private static async Task SendClientRequestBody(SessionEventArgs args) private static async Task SendClientRequestBody(SessionEventArgs args)
{ {
// End the operation // End the operation
...@@ -445,6 +496,7 @@ namespace Titanium.Web.Proxy ...@@ -445,6 +496,7 @@ namespace Titanium.Web.Proxy
X509Chain chain, X509Chain chain,
SslPolicyErrors sslPolicyErrors) SslPolicyErrors sslPolicyErrors)
{ {
//if user callback is registered then do it
if (ServerCertificateValidationCallback != null) if (ServerCertificateValidationCallback != null)
{ {
var args = new CertificateValidationEventArgs(); var args = new CertificateValidationEventArgs();
...@@ -511,7 +563,7 @@ namespace Titanium.Web.Proxy ...@@ -511,7 +563,7 @@ namespace Titanium.Web.Proxy
localCertificates.Count > 0) localCertificates.Count > 0)
clientCertificate = localCertificates[0]; clientCertificate = localCertificates[0];
//If user call back is registered
if (ClientCertificateSelectionCallback != null) if (ClientCertificateSelectionCallback != null)
{ {
var args = new CertificateSelectionEventArgs(); var args = new CertificateSelectionEventArgs();
......
...@@ -11,11 +11,15 @@ using Titanium.Web.Proxy.Extensions; ...@@ -11,11 +11,15 @@ using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
/// <summary>
/// Handle the response from server
/// </summary>
partial class ProxyServer partial class ProxyServer
{ {
//Called asynchronously when a request was successfully and we received the response //Called asynchronously when a request was successfully and we received the response
public static async Task HandleHttpSessionResponse(SessionEventArgs args) public static async Task HandleHttpSessionResponse(SessionEventArgs args)
{ {
//read response & headers from server
await args.WebSession.ReceiveResponse(); await args.WebSession.ReceiveResponse();
try try
...@@ -23,7 +27,7 @@ namespace Titanium.Web.Proxy ...@@ -23,7 +27,7 @@ namespace Titanium.Web.Proxy
if (!args.WebSession.Response.ResponseBodyRead) if (!args.WebSession.Response.ResponseBodyRead)
args.WebSession.Response.ResponseStream = args.WebSession.ServerConnection.Stream; args.WebSession.Response.ResponseStream = args.WebSession.ServerConnection.Stream;
//If client request call back then do it
if (BeforeResponse != null && !args.WebSession.Response.ResponseLocked) if (BeforeResponse != null && !args.WebSession.Response.ResponseLocked)
{ {
Delegate[] invocationList = BeforeResponse.GetInvocationList(); Delegate[] invocationList = BeforeResponse.GetInvocationList();
...@@ -39,6 +43,7 @@ namespace Titanium.Web.Proxy ...@@ -39,6 +43,7 @@ namespace Titanium.Web.Proxy
args.WebSession.Response.ResponseLocked = true; args.WebSession.Response.ResponseLocked = true;
//Write back to client 100-conitinue response if that's what server returned
if (args.WebSession.Response.Is100Continue) if (args.WebSession.Response.Is100Continue)
{ {
await WriteResponseStatus(args.WebSession.Response.HttpVersion, "100", await WriteResponseStatus(args.WebSession.Response.HttpVersion, "100",
...@@ -52,6 +57,7 @@ namespace Titanium.Web.Proxy ...@@ -52,6 +57,7 @@ namespace Titanium.Web.Proxy
await args.ProxyClient.ClientStreamWriter.WriteLineAsync(); await args.ProxyClient.ClientStreamWriter.WriteLineAsync();
} }
//Write back response status
await WriteResponseStatus(args.WebSession.Response.HttpVersion, args.WebSession.Response.ResponseStatusCode, await WriteResponseStatus(args.WebSession.Response.HttpVersion, args.WebSession.Response.ResponseStatusCode,
args.WebSession.Response.ResponseStatusDescription, args.ProxyClient.ClientStreamWriter); args.WebSession.Response.ResponseStatusDescription, args.ProxyClient.ClientStreamWriter);
...@@ -95,6 +101,12 @@ namespace Titanium.Web.Proxy ...@@ -95,6 +101,12 @@ namespace Titanium.Web.Proxy
} }
} }
/// <summary>
/// get the compressed response body from give response bytes
/// </summary>
/// <param name="encodingType"></param>
/// <param name="responseBodyStream"></param>
/// <returns></returns>
private static async Task<byte[]> GetCompressedResponseBody(string encodingType, byte[] responseBodyStream) private static async Task<byte[]> GetCompressedResponseBody(string encodingType, byte[] responseBodyStream)
{ {
var compressionFactory = new CompressionFactory(); var compressionFactory = new CompressionFactory();
...@@ -102,13 +114,26 @@ namespace Titanium.Web.Proxy ...@@ -102,13 +114,26 @@ namespace Titanium.Web.Proxy
return await compressor.Compress(responseBodyStream); return await compressor.Compress(responseBodyStream);
} }
/// <summary>
/// Write response status
/// </summary>
/// <param name="version"></param>
/// <param name="code"></param>
/// <param name="description"></param>
/// <param name="responseWriter"></param>
/// <returns></returns>
private static async Task WriteResponseStatus(Version version, string code, string description, private static async Task WriteResponseStatus(Version version, string code, string description,
StreamWriter responseWriter) StreamWriter responseWriter)
{ {
await responseWriter.WriteLineAsync(string.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, code, description)); await responseWriter.WriteLineAsync(string.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, code, description));
} }
/// <summary>
/// Write response headers to client
/// </summary>
/// <param name="responseWriter"></param>
/// <param name="headers"></param>
/// <returns></returns>
private static async Task WriteResponseHeaders(StreamWriter responseWriter, List<HttpHeader> headers) private static async Task WriteResponseHeaders(StreamWriter responseWriter, List<HttpHeader> headers)
{ {
if (headers != null) if (headers != null)
...@@ -124,6 +149,11 @@ namespace Titanium.Web.Proxy ...@@ -124,6 +149,11 @@ namespace Titanium.Web.Proxy
await responseWriter.WriteLineAsync(); await responseWriter.WriteLineAsync();
await responseWriter.FlushAsync(); await responseWriter.FlushAsync();
} }
/// <summary>
/// Fix the proxy specific headers before sending response headers to client
/// </summary>
/// <param name="headers"></param>
private static void FixResponseProxyHeaders(List<HttpHeader> headers) private static void FixResponseProxyHeaders(List<HttpHeader> headers)
{ {
//If proxy-connection close was returned inform to close the connection //If proxy-connection close was returned inform to close the connection
...@@ -143,7 +173,14 @@ namespace Titanium.Web.Proxy ...@@ -143,7 +173,14 @@ namespace Titanium.Web.Proxy
headers.RemoveAll(x => x.Name.ToLower() == "proxy-connection"); headers.RemoveAll(x => x.Name.ToLower() == "proxy-connection");
} }
/// <summary>
/// Handle dispose of a client/server session
/// </summary>
/// <param name="client"></param>
/// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="args"></param>
private static void Dispose(TcpClient client, IDisposable clientStream, IDisposable clientStreamReader, private static void Dispose(TcpClient client, IDisposable clientStream, IDisposable clientStreamReader,
IDisposable clientStreamWriter, IDisposable args) IDisposable clientStreamWriter, IDisposable args)
{ {
......
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