Commit f11b6b60 authored by Honfika's avatar Honfika

Connection Reset #375 fix, disposing the connections/readers/writers in the...

Connection Reset #375 fix, disposing the connections/readers/writers in the same method where they are created
parent 7c45f3a2
...@@ -170,18 +170,18 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -170,18 +170,18 @@ namespace Titanium.Web.Proxy.Examples.Basic
//requestBodyHistory[e.Id] = bodyString; //requestBodyHistory[e.Id] = bodyString;
} }
////To cancel a request with a custom HTML content //To cancel a request with a custom HTML content
////Filter URL //Filter URL
//if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com")) if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
//{ {
// await e.Ok("<!DOCTYPE html>" + await e.Ok("<!DOCTYPE html>" +
// "<html><body><h1>" + "<html><body><h1>" +
// "Website Blocked" + "Website Blocked" +
// "</h1>" + "</h1>" +
// "<p>Blocked by titanium web proxy.</p>" + "<p>Blocked by titanium web proxy.</p>" +
// "</body>" + "</body>" +
// "</html>"); "</html>");
//} }
////Redirect example ////Redirect example
//if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org")) //if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
......
...@@ -29,11 +29,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -29,11 +29,6 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
private readonly int bufferSize; private readonly int bufferSize;
/// <summary>
/// Holds a reference to proxy response handler method
/// </summary>
private Func<SessionEventArgs, Task> httpResponseHandler;
private readonly Action<Exception> exceptionFunc; private readonly Action<Exception> exceptionFunc;
/// <summary> /// <summary>
...@@ -108,11 +103,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -108,11 +103,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
internal SessionEventArgs(int bufferSize, internal SessionEventArgs(int bufferSize,
ProxyEndPoint endPoint, ProxyEndPoint endPoint,
Func<SessionEventArgs, Task> httpResponseHandler,
Action<Exception> exceptionFunc) Action<Exception> exceptionFunc)
{ {
this.bufferSize = bufferSize; this.bufferSize = bufferSize;
this.httpResponseHandler = httpResponseHandler;
this.exceptionFunc = exceptionFunc; this.exceptionFunc = exceptionFunc;
ProxyClient = new ProxyClient(); ProxyClient = new ProxyClient();
...@@ -637,8 +630,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -637,8 +630,6 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.Response = response; WebSession.Response = response;
await httpResponseHandler(this);
WebSession.Request.CancelRequest = true; WebSession.Request.CancelRequest = true;
} }
...@@ -647,7 +638,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -647,7 +638,6 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
httpResponseHandler = null;
CustomUpStreamProxyUsed = null; CustomUpStreamProxyUsed = null;
DataSent = null; DataSent = null;
......
...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.EventArguments
public bool IsHttpsConnect { get; set; } public bool IsHttpsConnect { get; set; }
internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, Action<Exception> exceptionFunc) internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, Action<Exception> exceptionFunc)
: base(bufferSize, endPoint, null, exceptionFunc) : base(bufferSize, endPoint, exceptionFunc)
{ {
WebSession.Request = connectRequest; WebSession.Request = connectRequest;
} }
......
...@@ -88,10 +88,10 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -88,10 +88,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
string httpStatus = await reader.ReadLineAsync(); string httpStatus = await reader.ReadLineAsync();
Response.ParseResponseLine(httpStatus, out var version, out int statusCode, out string statusDescription); Response.ParseResponseLine(httpStatus, out _, out int statusCode, out string statusDescription);
if (!statusDescription.EqualsIgnoreCase("200 OK") if (statusCode != 200 && !statusDescription.EqualsIgnoreCase("OK")
&& !statusDescription.EqualsIgnoreCase("connection established")) && !statusDescription.EqualsIgnoreCase("Connection Established"))
{ {
throw new Exception("Upstream proxy failed to create a secure tunnel"); throw new Exception("Upstream proxy failed to create a secure tunnel");
} }
......
...@@ -654,26 +654,6 @@ namespace Titanium.Web.Proxy ...@@ -654,26 +654,6 @@ namespace Titanium.Web.Proxy
ProxyRunning = false; ProxyRunning = false;
} }
/// <summary>
/// Handle dispose of a client/server session
/// </summary>
/// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="serverConnection"></param>
private void Dispose(CustomBufferedStream clientStream, CustomBinaryReader clientStreamReader, HttpResponseWriter clientStreamWriter, TcpConnection serverConnection)
{
clientStreamReader?.Dispose();
clientStream?.Dispose();
if (serverConnection != null)
{
serverConnection.Dispose();
serverConnection = null;
}
}
/// <summary> /// <summary>
/// Dispose Proxy. /// Dispose Proxy.
/// </summary> /// </summary>
......
...@@ -38,8 +38,6 @@ namespace Titanium.Web.Proxy ...@@ -38,8 +38,6 @@ namespace Titanium.Web.Proxy
/// <returns></returns> /// <returns></returns>
private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient) private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient)
{ {
bool disposed = false;
var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize);
var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
...@@ -47,22 +45,22 @@ namespace Titanium.Web.Proxy ...@@ -47,22 +45,22 @@ namespace Titanium.Web.Proxy
try try
{ {
//read the first line HTTP command
string httpCmd = await clientStreamReader.ReadLineAsync();
if (string.IsNullOrEmpty(httpCmd))
{
return;
}
Request.ParseRequestLine(httpCmd, out string httpMethod, out string httpUrl, out var version);
string connectHostname = null; string connectHostname = null;
ConnectRequest connectRequest = null; ConnectRequest connectRequest = null;
//Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request) //Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
if (httpMethod == "CONNECT") if (await IsConnectMethod(clientStream) == 1)
{ {
//read the first line HTTP command
string httpCmd = await clientStreamReader.ReadLineAsync();
if (string.IsNullOrEmpty(httpCmd))
{
return;
}
Request.ParseRequestLine(httpCmd, out string _, out string httpUrl, out var version);
var httpRemoteUri = new Uri("http://" + httpUrl); var httpRemoteUri = new Uri("http://" + httpUrl);
connectHostname = httpRemoteUri.Host; connectHostname = httpRemoteUri.Host;
...@@ -154,12 +152,7 @@ namespace Titanium.Web.Proxy ...@@ -154,12 +152,7 @@ namespace Titanium.Web.Proxy
return; return;
} }
if (await CanBeHttpMethod(clientStream)) if (await IsConnectMethod(clientStream) == -1)
{
//Now read the actual HTTPS request line
httpCmd = await clientStreamReader.ReadLineAsync();
}
else
{ {
// It can be for example some Google (Cloude Messaging for Chrome) magic // It can be for example some Google (Cloude Messaging for Chrome) magic
excluded = true; excluded = true;
...@@ -207,8 +200,11 @@ namespace Titanium.Web.Proxy ...@@ -207,8 +200,11 @@ namespace Titanium.Web.Proxy
} }
//Now create the request //Now create the request
disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter, await HandleHttpSessionRequest(tcpClient, clientStream, clientStreamReader, clientStreamWriter, connectHostname, endPoint, connectRequest);
connectHostname, endPoint, connectRequest); }
catch (ProxyHttpException e)
{
ExceptionFunc(e);
} }
catch (IOException e) catch (IOException e)
{ {
...@@ -220,44 +216,53 @@ namespace Titanium.Web.Proxy ...@@ -220,44 +216,53 @@ namespace Titanium.Web.Proxy
} }
catch (Exception e) catch (Exception e)
{ {
// is this the correct error message? ExceptionFunc(new Exception("Error occured in whilst handling the client", e));
ExceptionFunc(new Exception("Error whilst authorizing request", e));
} }
finally finally
{ {
if (!disposed) clientStreamReader.Dispose();
{ clientStream.Dispose();
Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
}
} }
} }
private async Task<bool> CanBeHttpMethod(CustomBufferedStream clientStream) /// <summary>
/// Determines whether is connect method.
/// </summary>
/// <param name="clientStream">The client stream.</param>
/// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
private async Task<int> IsConnectMethod(CustomBufferedStream clientStream)
{ {
bool isConnect = true;
int legthToCheck = 10; int legthToCheck = 10;
for (int i = 0; i < legthToCheck; i++) for (int i = 0; i < legthToCheck; i++)
{ {
int b = await clientStream.PeekByteAsync(i); int b = await clientStream.PeekByteAsync(i);
if (b == -1) if (b == -1)
{ {
return false; return -1;
} }
if (b == ' ' && i > 2) if (b == ' ' && i > 2)
{ {
// at least 3 letters and a space // at least 3 letters and a space
return true; return isConnect ? 1 : 0;
} }
if (!char.IsLetter((char)b)) char ch = (char)b;
if (!char.IsLetter(ch))
{ {
// non letter or too short // non letter or too short
return false; return -1;
}
if (i > 6 || ch != "CONNECT"[i])
{
isConnect = false;
} }
} }
// only letters // only letters
return true; return isConnect ? 1 : 0;
} }
/// <summary> /// <summary>
...@@ -269,11 +274,10 @@ namespace Titanium.Web.Proxy ...@@ -269,11 +274,10 @@ namespace Titanium.Web.Proxy
/// <returns></returns> /// <returns></returns>
private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient) private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient)
{ {
bool disposed = false;
var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize);
CustomBinaryReader clientStreamReader = null; var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
HttpResponseWriter clientStreamWriter = null; var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
try try
{ {
...@@ -298,22 +302,14 @@ namespace Titanium.Web.Proxy ...@@ -298,22 +302,14 @@ 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
} }
clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
//now read the request line
string httpCmd = await clientStreamReader.ReadLineAsync();
//Now create the request //Now create the request
disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter, await HandleHttpSessionRequest(tcpClient, clientStream, clientStreamReader, clientStreamWriter,
endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null, true); endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null, true);
} }
finally finally
{ {
if (!disposed) clientStreamReader.Dispose();
{ clientStream.Dispose();
Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
}
} }
} }
...@@ -323,7 +319,6 @@ namespace Titanium.Web.Proxy ...@@ -323,7 +319,6 @@ namespace Titanium.Web.Proxy
/// client/server abruptly terminates connection or by normal HTTP termination /// client/server abruptly terminates connection or by normal HTTP termination
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="httpCmd"></param>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param> /// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param> /// <param name="clientStreamWriter"></param>
...@@ -332,193 +327,181 @@ namespace Titanium.Web.Proxy ...@@ -332,193 +327,181 @@ namespace Titanium.Web.Proxy
/// <param name="connectRequest"></param> /// <param name="connectRequest"></param>
/// <param name="isTransparentEndPoint"></param> /// <param name="isTransparentEndPoint"></param>
/// <returns></returns> /// <returns></returns>
private async Task<bool> HandleHttpSessionRequest(TcpClient client, string httpCmd, CustomBufferedStream clientStream, private async Task HandleHttpSessionRequest(TcpClient client, CustomBufferedStream clientStream,
CustomBinaryReader clientStreamReader, HttpResponseWriter clientStreamWriter, string httpsConnectHostname, CustomBinaryReader clientStreamReader, HttpResponseWriter clientStreamWriter, string httpsConnectHostname,
ProxyEndPoint endPoint, ConnectRequest connectRequest, bool isTransparentEndPoint = false) ProxyEndPoint endPoint, ConnectRequest connectRequest, bool isTransparentEndPoint = false)
{ {
bool disposed = false;
TcpConnection connection = null; TcpConnection connection = null;
//Loop through each subsequest request on this particular client connection try
//(assuming HTTP connection is kept alive by client)
while (true)
{ {
if (string.IsNullOrEmpty(httpCmd)) //Loop through each subsequest request on this particular client connection
//(assuming HTTP connection is kept alive by client)
while (true)
{ {
break; // read the request line
} string httpCmd = await clientStreamReader.ReadLineAsync();
if (string.IsNullOrEmpty(httpCmd))
{
break;
}
var args = new SessionEventArgs(BufferSize, endPoint, HandleHttpSessionResponse, ExceptionFunc) var args = new SessionEventArgs(BufferSize, endPoint, ExceptionFunc)
{ {
ProxyClient = { TcpClient = client }, ProxyClient = { TcpClient = client },
WebSession = { ConnectRequest = connectRequest } WebSession = { ConnectRequest = connectRequest }
}; };
try try
{ {
Request.ParseRequestLine(httpCmd, out string httpMethod, out string httpUrl, out var version); Request.ParseRequestLine(httpCmd, out string httpMethod, out string httpUrl, out var version);
//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.Headers); await HeaderParser.ReadHeaders(clientStreamReader, args.WebSession.Request.Headers);
Uri httpRemoteUri; Uri httpRemoteUri;
if (uriSchemeRegex.IsMatch(httpUrl)) if (uriSchemeRegex.IsMatch(httpUrl))
{
try
{ {
httpRemoteUri = new Uri(httpUrl); try
{
httpRemoteUri = new Uri(httpUrl);
}
catch (Exception ex)
{
throw new Exception($"Invalid URI: '{httpUrl}'", ex);
}
} }
catch (Exception ex) else
{ {
throw new Exception($"Invalid URI: '{httpUrl}'", ex); string host = args.WebSession.Request.Host ?? httpsConnectHostname;
string hostAndPath = host;
if (httpUrl.StartsWith("/"))
{
hostAndPath += httpUrl;
}
string url = string.Concat(httpsConnectHostname == null ? "http://" : "https://", hostAndPath);
try
{
httpRemoteUri = new Uri(url);
}
catch (Exception ex)
{
throw new Exception($"Invalid URI: '{url}'", ex);
}
} }
}
else args.WebSession.Request.RequestUri = httpRemoteUri;
{ args.WebSession.Request.OriginalUrl = httpUrl;
string host = args.WebSession.Request.Host ?? httpsConnectHostname;
string hostAndPath = host; args.WebSession.Request.Method = httpMethod;
if (httpUrl.StartsWith("/")) args.WebSession.Request.HttpVersion = version;
args.ProxyClient.ClientStream = clientStream;
args.ProxyClient.ClientStreamReader = clientStreamReader;
args.ProxyClient.ClientStreamWriter = clientStreamWriter;
//proxy authorization check
if (httpsConnectHostname == null && await CheckAuthorization(clientStreamWriter, args) == false)
{ {
hostAndPath += httpUrl; break;
} }
string url = string.Concat(httpsConnectHostname == null ? "http://" : "https://", hostAndPath); PrepareRequestHeaders(args.WebSession.Request.Headers);
try if (!isTransparentEndPoint)
{ {
httpRemoteUri = new Uri(url); args.WebSession.Request.Host = args.WebSession.Request.RequestUri.Authority;
} }
catch (Exception ex)
//if win auth is enabled
//we need a cache of request body
//so that we can send it after authentication in WinAuthHandler.cs
if (isWindowsAuthenticationEnabledAndSupported && args.WebSession.Request.HasBody)
{ {
throw new Exception($"Invalid URI: '{url}'", ex); await args.GetRequestBody();
} }
}
args.WebSession.Request.RequestUri = httpRemoteUri; //If user requested interception do it
args.WebSession.Request.OriginalUrl = httpUrl; if (BeforeRequest != null)
{
args.WebSession.Request.Method = httpMethod; await BeforeRequest.InvokeAsync(this, args, ExceptionFunc);
args.WebSession.Request.HttpVersion = version; }
args.ProxyClient.ClientStream = clientStream;
args.ProxyClient.ClientStreamReader = clientStreamReader;
args.ProxyClient.ClientStreamWriter = clientStreamWriter;
//proxy authorization check if (args.WebSession.Request.CancelRequest)
if (httpsConnectHostname == null && await CheckAuthorization(clientStreamWriter, args) == false) {
{ await HandleHttpSessionResponse(args);
args.Dispose(); break;
break; }
}
PrepareRequestHeaders(args.WebSession.Request.Headers); //create a new connection if hostname/upstream end point changes
if (!isTransparentEndPoint) if (connection != null
{ && (!connection.HostName.Equals(args.WebSession.Request.RequestUri.Host, StringComparison.OrdinalIgnoreCase)
args.WebSession.Request.Host = args.WebSession.Request.RequestUri.Authority; || (args.WebSession.UpStreamEndPoint != null
} && !args.WebSession.UpStreamEndPoint.Equals(connection.UpStreamEndPoint))))
{
connection.Dispose();
connection = null;
}
//if win auth is enabled if (connection == null)
//we need a cache of request body {
//so that we can send it after authentication in WinAuthHandler.cs connection = await GetServerConnection(args, false);
if (isWindowsAuthenticationEnabledAndSupported && args.WebSession.Request.HasBody) }
{
await args.GetRequestBody();
}
//If user requested interception do it //if upgrading to websocket then relay the requet without reading the contents
if (BeforeRequest != null) if (args.WebSession.Request.UpgradeToWebSocket)
{ {
await BeforeRequest.InvokeAsync(this, args, ExceptionFunc); //prepare the prefix content
} var requestHeaders = args.WebSession.Request.Headers;
await connection.StreamWriter.WriteLineAsync(httpCmd);
await connection.StreamWriter.WriteHeadersAsync(requestHeaders);
string httpStatus = await connection.StreamReader.ReadLineAsync();
if (args.WebSession.Request.CancelRequest) Response.ParseResponseLine(httpStatus, out var responseVersion, out int responseStatusCode, out string responseStatusDescription);
{ args.WebSession.Response.HttpVersion = responseVersion;
args.Dispose(); args.WebSession.Response.StatusCode = responseStatusCode;
break; args.WebSession.Response.StatusDescription = responseStatusDescription;
}
//create a new connection if hostname/upstream end point changes await HeaderParser.ReadHeaders(connection.StreamReader, args.WebSession.Response.Headers);
if (connection != null
&& (!connection.HostName.Equals(args.WebSession.Request.RequestUri.Host, StringComparison.OrdinalIgnoreCase)
|| (args.WebSession.UpStreamEndPoint != null
&& !args.WebSession.UpStreamEndPoint.Equals(connection.UpStreamEndPoint))))
{
connection.Dispose();
connection = null;
}
if (connection == null) await clientStreamWriter.WriteResponseAsync(args.WebSession.Response);
{
connection = await GetServerConnection(args, false);
}
//if upgrading to websocket then relay the requet without reading the contents //If user requested call back then do it
if (args.WebSession.Request.UpgradeToWebSocket) if (BeforeResponse != null && !args.WebSession.Response.ResponseLocked)
{ {
//prepare the prefix content await BeforeResponse.InvokeAsync(this, args, ExceptionFunc);
var requestHeaders = args.WebSession.Request.Headers; }
await connection.StreamWriter.WriteLineAsync(httpCmd);
await connection.StreamWriter.WriteHeadersAsync(requestHeaders);
string httpStatus = await connection.StreamReader.ReadLineAsync();
Response.ParseResponseLine(httpStatus, out var responseVersion, out int responseStatusCode, out string responseStatusDescription); await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
args.WebSession.Response.HttpVersion = responseVersion; (buffer, offset, count) => { args.OnDataSent(buffer, offset, count); },
args.WebSession.Response.StatusCode = responseStatusCode; (buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); },
args.WebSession.Response.StatusDescription = responseStatusDescription; ExceptionFunc);
await HeaderParser.ReadHeaders(connection.StreamReader, args.WebSession.Response.Headers); break;
}
await clientStreamWriter.WriteResponseAsync(args.WebSession.Response); //construct the web request that we are going to issue on behalf of the client.
await HandleHttpSessionRequestInternal(connection, args);
//If user requested call back then do it //if connection is closing exit
if (BeforeResponse != null && !args.WebSession.Response.ResponseLocked) if (args.WebSession.Response.KeepAlive == false)
{ {
await BeforeResponse.InvokeAsync(this, args, ExceptionFunc); break;
} }
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { args.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); },
ExceptionFunc);
args.Dispose();
break;
} }
catch (Exception e) when (!(e is ProxyHttpException))
//construct the web request that we are going to issue on behalf of the client.
disposed = await HandleHttpSessionRequestInternal(connection, args, false);
if (disposed)
{ {
//already disposed inside above method throw new ProxyHttpException("Error occured whilst handling session request", e, args);
args.Dispose();
break;
} }
finally
//if connection is closing exit
if (args.WebSession.Response.KeepAlive == false)
{ {
args.Dispose(); args.Dispose();
break;
} }
args.Dispose();
// read the next request
httpCmd = await clientStreamReader.ReadLineAsync();
}
catch (Exception e)
{
ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request", e, args));
break;
} }
} }
finally
if (!disposed)
{ {
Dispose(clientStream, clientStreamReader, clientStreamWriter, connection); connection?.Dispose();
} }
return true;
} }
/// <summary> /// <summary>
...@@ -526,13 +509,9 @@ namespace Titanium.Web.Proxy ...@@ -526,13 +509,9 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="connection"></param> /// <param name="connection"></param>
/// <param name="args"></param> /// <param name="args"></param>
/// <param name="closeConnection"></param> /// <returns>True if close the connection</returns>
/// <returns></returns> private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args)
private async Task<bool> HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args, bool closeConnection)
{ {
bool disposed = false;
bool keepAlive = false;
try try
{ {
var request = args.WebSession.Request; var request = args.WebSession.Request;
...@@ -605,43 +584,13 @@ namespace Titanium.Web.Proxy ...@@ -605,43 +584,13 @@ namespace Titanium.Web.Proxy
//If not expectation failed response was returned by server then parse response //If not expectation failed response was returned by server then parse response
if (!request.ExpectationFailed) if (!request.ExpectationFailed)
{ {
disposed = await HandleHttpSessionResponse(args); await HandleHttpSessionResponse(args);
//already disposed inside above method
if (disposed)
{
return true;
}
}
//if connection is closing exit
if (args.WebSession.Response.KeepAlive == false)
{
return true;
}
if (!closeConnection)
{
keepAlive = true;
return false;
} }
} }
catch (Exception e) catch (Exception e) when (!(e is ProxyHttpException))
{
ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request (internal)", e, args));
return true;
}
finally
{ {
if (!disposed && !keepAlive) throw new ProxyHttpException("Error occured whilst handling session request (internal)", e, args);
{
//dispose
Dispose(args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader, args.ProxyClient.ClientStreamWriter,
args.WebSession.ServerConnection);
}
} }
return true;
} }
/// <summary> /// <summary>
......
...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy ...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns>true if client/server connection was terminated (and disposed) </returns> /// <returns>true if client/server connection was terminated (and disposed) </returns>
private async Task<bool> HandleHttpSessionResponse(SessionEventArgs args) private async Task HandleHttpSessionResponse(SessionEventArgs args)
{ {
try try
{ {
...@@ -30,12 +30,7 @@ namespace Titanium.Web.Proxy ...@@ -30,12 +30,7 @@ namespace Titanium.Web.Proxy
//check for windows authentication //check for windows authentication
if (isWindowsAuthenticationEnabledAndSupported && response.StatusCode == (int)HttpStatusCode.Unauthorized) if (isWindowsAuthenticationEnabledAndSupported && response.StatusCode == (int)HttpStatusCode.Unauthorized)
{ {
bool disposed = await Handle401UnAuthorized(args); await Handle401UnAuthorized(args);
if (disposed)
{
return true;
}
} }
args.ReRequest = false; args.ReRequest = false;
...@@ -52,8 +47,8 @@ namespace Titanium.Web.Proxy ...@@ -52,8 +47,8 @@ namespace Titanium.Web.Proxy
{ {
//clear current response //clear current response
await args.ClearResponse(); await args.ClearResponse();
bool disposed = await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args, false); await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args);
return disposed; return;
} }
response.ResponseLocked = true; response.ResponseLocked = true;
...@@ -109,16 +104,10 @@ namespace Titanium.Web.Proxy ...@@ -109,16 +104,10 @@ namespace Titanium.Web.Proxy
} }
} }
} }
catch (Exception e) catch (Exception e) when (!(e is ProxyHttpException))
{ {
ExceptionFunc(new ProxyHttpException("Error occured whilst handling session response", e, args)); throw new ProxyHttpException("Error occured whilst handling session response", e, args);
Dispose(args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader, args.ProxyClient.ClientStreamWriter,
args.WebSession.ServerConnection);
return true;
} }
return false;
} }
/// <summary> /// <summary>
......
...@@ -135,8 +135,7 @@ namespace Titanium.Web.Proxy ...@@ -135,8 +135,7 @@ namespace Titanium.Web.Proxy
//request again with updated authorization header //request again with updated authorization header
//and server cookies //and server cookies
bool disposed = await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args, false); await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args);
return disposed;
} }
return false; return false;
......
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