Commit a7cab15f authored by justcoding121's avatar justcoding121

#519 handle change in hostname on ReRequest

parent 8311e6b5
......@@ -118,7 +118,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
string hostname = e.WebSession.Request.RequestUri.Host;
string hostname = e.HttpClient.Request.RequestUri.Host;
await WriteToConsole("Tunnel to: " + hostname);
if (hostname.Contains("dropbox.com"))
......@@ -139,7 +139,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
private async Task OnRequest(object sender, SessionEventArgs e)
{
await WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
await WriteToConsole(e.WebSession.Request.Url);
await WriteToConsole(e.HttpClient.Request.Url);
// store it in the UserData property
// It can be a simple integer, Guid, or any type
......@@ -191,7 +191,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
await WriteToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);
string ext = System.IO.Path.GetExtension(e.WebSession.Request.RequestUri.AbsolutePath);
string ext = System.IO.Path.GetExtension(e.HttpClient.Request.RequestUri.AbsolutePath);
//access user data set in request to do something with it
//var userData = e.WebSession.UserData as CustomUserData;
......
......@@ -122,7 +122,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private async Task ProxyServer_BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
string hostname = e.WebSession.Request.RequestUri.Host;
string hostname = e.HttpClient.Request.RequestUri.Host;
if (hostname.EndsWith("webex.com"))
{
e.DecryptSsl = false;
......@@ -135,7 +135,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
await Dispatcher.InvokeAsync(() =>
{
if (sessionDictionary.TryGetValue(e.WebSession, out var item))
if (sessionDictionary.TryGetValue(e.HttpClient, out var item))
{
item.Update();
}
......@@ -147,9 +147,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
SessionListItem item = null;
await Dispatcher.InvokeAsync(() => { item = AddSession(e); });
if (e.WebSession.Request.HasBody)
if (e.HttpClient.Request.HasBody)
{
e.WebSession.Request.KeepBody = true;
e.HttpClient.Request.KeepBody = true;
await e.GetRequestBody();
}
}
......@@ -159,7 +159,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
SessionListItem item = null;
await Dispatcher.InvokeAsync(() =>
{
if (sessionDictionary.TryGetValue(e.WebSession, out item))
if (sessionDictionary.TryGetValue(e.HttpClient, out item))
{
item.Update();
}
......@@ -167,9 +167,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
if (item != null)
{
if (e.WebSession.Response.HasBody)
if (e.HttpClient.Response.HasBody)
{
e.WebSession.Response.KeepBody = true;
e.HttpClient.Response.KeepBody = true;
await e.GetResponseBody();
await Dispatcher.InvokeAsync(() => { item.Update(); });
......@@ -181,7 +181,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
await Dispatcher.InvokeAsync(() =>
{
if (sessionDictionary.TryGetValue(e.WebSession, out var item))
if (sessionDictionary.TryGetValue(e.HttpClient, out var item))
{
item.Exception = e.Exception;
}
......@@ -192,7 +192,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
var item = CreateSessionListItem(e);
Sessions.Add(item);
sessionDictionary.Add(e.WebSession, item);
sessionDictionary.Add(e.HttpClient, item);
return item;
}
......@@ -203,16 +203,16 @@ namespace Titanium.Web.Proxy.Examples.Wpf
var item = new SessionListItem
{
Number = lastSessionNumber,
WebSession = e.WebSession,
WebSession = e.HttpClient,
IsTunnelConnect = isTunnelConnect
};
if (isTunnelConnect || e.WebSession.Request.UpgradeToWebSocket)
if (isTunnelConnect || e.HttpClient.Request.UpgradeToWebSocket)
{
e.DataReceived += (sender, args) =>
{
var session = (SessionEventArgs)sender;
if (sessionDictionary.TryGetValue(session.WebSession, out var li))
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
li.ReceivedDataCount += args.Count;
}
......@@ -221,7 +221,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
e.DataSent += (sender, args) =>
{
var session = (SessionEventArgs)sender;
if (sessionDictionary.TryGetValue(session.WebSession, out var li))
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
li.SentDataCount += args.Count;
}
......
......@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy.EventArguments
get => reRequest;
set
{
if (WebSession.Response.StatusCode == 0)
if (HttpClient.Response.StatusCode == 0)
{
throw new Exception("Response status code is empty. Cannot request again a request " + "which was never send to server.");
}
......@@ -69,12 +69,12 @@ namespace Titanium.Web.Proxy.EventArguments
private ICustomStreamReader getStreamReader(bool isRequest)
{
return isRequest ? ProxyClient.ClientStream : WebSession.ServerConnection.Stream;
return isRequest ? ProxyClient.ClientStream : HttpClient.Connection.Stream;
}
private HttpWriter getStreamWriter(bool isRequest)
{
return isRequest ? (HttpWriter)ProxyClient.ClientStreamWriter : WebSession.ServerConnection.StreamWriter;
return isRequest ? (HttpWriter)ProxyClient.ClientStreamWriter : HttpClient.Connection.StreamWriter;
}
/// <summary>
......@@ -82,9 +82,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
private async Task readRequestBodyAsync(CancellationToken cancellationToken)
{
WebSession.Request.EnsureBodyAvailable(false);
HttpClient.Request.EnsureBodyAvailable(false);
var request = WebSession.Request;
var request = HttpClient.Request;
// If not already read (not cached yet)
if (!request.IsBodyRead)
......@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
// syphon out the response body from server
await SyphonOutBodyAsync(false, cancellationToken);
WebSession.Response = new Response();
HttpClient.Response = new Response();
}
internal void OnMultipartRequestPartSent(string boundary, HeaderCollection headers)
......@@ -126,12 +126,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
private async Task readResponseBodyAsync(CancellationToken cancellationToken)
{
if (!WebSession.Request.Locked)
if (!HttpClient.Request.Locked)
{
throw new Exception("You cannot read the response body before request is made to server.");
}
var response = WebSession.Response;
var response = HttpClient.Response;
if (!response.HasBody)
{
return;
......@@ -178,7 +178,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns></returns>
internal async Task SyphonOutBodyAsync(bool isRequest, CancellationToken cancellationToken)
{
var requestResponse = isRequest ? (RequestResponseBase)WebSession.Request : WebSession.Response;
var requestResponse = isRequest ? (RequestResponseBase)HttpClient.Request : HttpClient.Response;
if (requestResponse.IsBodyRead || !requestResponse.OriginalHasBody)
{
return;
......@@ -197,7 +197,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns></returns>
internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode transformation, CancellationToken cancellationToken)
{
var request = WebSession.Request;
var request = HttpClient.Request;
long contentLength = request.ContentLength;
......@@ -243,7 +243,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
var stream = getStreamReader(isRequest);
var requestResponse = isRequest ? (RequestResponseBase)WebSession.Request : WebSession.Response;
var requestResponse = isRequest ? (RequestResponseBase)HttpClient.Request : HttpClient.Response;
bool isChunked = useOriginalHeaderValues? requestResponse.OriginalIsChunked : requestResponse.IsChunked;
long contentLength = useOriginalHeaderValues ? requestResponse.OriginalContentLength : requestResponse.ContentLength;
......@@ -351,12 +351,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The body as bytes.</returns>
public async Task<byte[]> GetRequestBody(CancellationToken cancellationToken = default)
{
if (!WebSession.Request.IsBodyRead)
if (!HttpClient.Request.IsBodyRead)
{
await readRequestBodyAsync(cancellationToken);
}
return WebSession.Request.Body;
return HttpClient.Request.Body;
}
/// <summary>
......@@ -366,12 +366,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The body as string.</returns>
public async Task<string> GetRequestBodyAsString(CancellationToken cancellationToken = default)
{
if (!WebSession.Request.IsBodyRead)
if (!HttpClient.Request.IsBodyRead)
{
await readRequestBodyAsync(cancellationToken);
}
return WebSession.Request.BodyString;
return HttpClient.Request.BodyString;
}
/// <summary>
......@@ -380,7 +380,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The request body bytes.</param>
public void SetRequestBody(byte[] body)
{
var request = WebSession.Request;
var request = HttpClient.Request;
if (request.Locked)
{
throw new Exception("You cannot call this function after request is made to server.");
......@@ -395,12 +395,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The request body string to set.</param>
public void SetRequestBodyString(string body)
{
if (WebSession.Request.Locked)
if (HttpClient.Request.Locked)
{
throw new Exception("You cannot call this function after request is made to server.");
}
SetRequestBody(WebSession.Request.Encoding.GetBytes(body));
SetRequestBody(HttpClient.Request.Encoding.GetBytes(body));
}
......@@ -411,12 +411,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The resulting bytes.</returns>
public async Task<byte[]> GetResponseBody(CancellationToken cancellationToken = default)
{
if (!WebSession.Response.IsBodyRead)
if (!HttpClient.Response.IsBodyRead)
{
await readResponseBodyAsync(cancellationToken);
}
return WebSession.Response.Body;
return HttpClient.Response.Body;
}
/// <summary>
......@@ -426,12 +426,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The string body.</returns>
public async Task<string> GetResponseBodyAsString(CancellationToken cancellationToken = default)
{
if (!WebSession.Response.IsBodyRead)
if (!HttpClient.Response.IsBodyRead)
{
await readResponseBodyAsync(cancellationToken);
}
return WebSession.Response.BodyString;
return HttpClient.Response.BodyString;
}
/// <summary>
......@@ -440,12 +440,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The body bytes to set.</param>
public void SetResponseBody(byte[] body)
{
if (!WebSession.Request.Locked)
if (!HttpClient.Request.Locked)
{
throw new Exception("You cannot call this function before request is made to server.");
}
var response = WebSession.Response;
var response = HttpClient.Response;
response.Body = body;
}
......@@ -455,12 +455,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The body string to set.</param>
public void SetResponseBodyString(string body)
{
if (!WebSession.Request.Locked)
if (!HttpClient.Request.Locked)
{
throw new Exception("You cannot call this function before request is made to server.");
}
var bodyBytes = WebSession.Response.Encoding.GetBytes(body);
var bodyBytes = HttpClient.Response.Encoding.GetBytes(body);
SetResponseBody(bodyBytes);
}
......@@ -481,7 +481,7 @@ namespace Titanium.Web.Proxy.EventArguments
response.Headers.AddHeaders(headers);
}
response.HttpVersion = WebSession.Request.HttpVersion;
response.HttpVersion = HttpClient.Request.HttpVersion;
response.Body = response.Encoding.GetBytes(html ?? string.Empty);
Respond(response, closeServerConnection);
......@@ -499,7 +499,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
var response = new OkResponse();
response.Headers.AddHeaders(headers);
response.HttpVersion = WebSession.Request.HttpVersion;
response.HttpVersion = HttpClient.Request.HttpVersion;
response.Body = result;
Respond(response, closeServerConnection);
......@@ -518,7 +518,7 @@ namespace Titanium.Web.Proxy.EventArguments
Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false)
{
var response = new GenericResponse(status);
response.HttpVersion = WebSession.Request.HttpVersion;
response.HttpVersion = HttpClient.Request.HttpVersion;
response.Headers.AddHeaders(headers);
response.Body = response.Encoding.GetBytes(html ?? string.Empty);
......@@ -537,7 +537,7 @@ namespace Titanium.Web.Proxy.EventArguments
Dictionary<string, HttpHeader> headers, bool closeServerConnection = false)
{
var response = new GenericResponse(status);
response.HttpVersion = WebSession.Request.HttpVersion;
response.HttpVersion = HttpClient.Request.HttpVersion;
response.Headers.AddHeaders(headers);
response.Body = result;
......@@ -552,7 +552,7 @@ namespace Titanium.Web.Proxy.EventArguments
public void Redirect(string url, bool closeServerConnection = false)
{
var response = new RedirectResponse();
response.HttpVersion = WebSession.Request.HttpVersion;
response.HttpVersion = HttpClient.Request.HttpVersion;
response.Headers.AddHeader(KnownHeaders.Location, url);
response.Body = emptyData;
......@@ -567,10 +567,10 @@ namespace Titanium.Web.Proxy.EventArguments
public void Respond(Response response, bool closeServerConnection = false)
{
//request already send/ready to be sent.
if (WebSession.Request.Locked)
if (HttpClient.Request.Locked)
{
//response already received from server and ready to be sent to client.
if (WebSession.Response.Locked)
if (HttpClient.Response.Locked)
{
throw new Exception("You cannot call this function after response is sent to the client.");
}
......@@ -583,21 +583,21 @@ namespace Titanium.Web.Proxy.EventArguments
TerminateServerConnection();
}
response.SetOriginalHeaders(WebSession.Response);
response.SetOriginalHeaders(HttpClient.Response);
//response already received from server but not yet ready to sent to client.
WebSession.Response = response;
WebSession.Response.Locked = true;
HttpClient.Response = response;
HttpClient.Response.Locked = true;
}
//request not yet sent/not yet ready to be sent.
else
{
WebSession.Request.Locked = true;
WebSession.Request.CancelRequest = true;
HttpClient.Request.Locked = true;
HttpClient.Request.CancelRequest = true;
//set new response.
WebSession.Response = response;
WebSession.Response.Locked = true;
HttpClient.Response = response;
HttpClient.Response.Locked = true;
}
}
......@@ -607,7 +607,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public void TerminateServerConnection()
{
WebSession.CloseServerConnection = true;
HttpClient.CloseServerConnection = true;
}
/// <summary>
......
......@@ -8,6 +8,7 @@ using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.EventArguments
{
......@@ -19,8 +20,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public abstract class SessionEventArgsBase : EventArgs, IDisposable
{
internal readonly CancellationTokenSource CancellationTokenSource;
internal TcpServerConnection ServerConnection => HttpClient.Connection;
internal TcpClientConnection ClientConnection => ProxyClient.Connection;
protected readonly int bufferSize;
protected readonly IBufferPool bufferPool;
......@@ -50,10 +52,10 @@ namespace Titanium.Web.Proxy.EventArguments
CancellationTokenSource = cancellationTokenSource;
ProxyClient = new ProxyClient();
WebSession = new HttpWebClient(request);
HttpClient = new HttpWebClient(request);
LocalEndPoint = endPoint;
WebSession.ProcessId = new Lazy<int>(() =>
HttpClient.ProcessId = new Lazy<int>(() =>
{
if (RunTime.IsWindows)
{
......@@ -85,25 +87,27 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public object UserData
{
get => WebSession.UserData;
set => WebSession.UserData = value;
get => HttpClient.UserData;
set => HttpClient.UserData = value;
}
/// <summary>
/// Does this session uses SSL?
/// </summary>
public bool IsHttps => WebSession.Request.IsHttps;
public bool IsHttps => HttpClient.Request.IsHttps;
/// <summary>
/// Client End Point.
/// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.ClientConnection.RemoteEndPoint;
public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.Connection.RemoteEndPoint;
/// <summary>
/// A web session corresponding to a single request/response sequence
/// within a proxy connection.
/// The web client used to communicate with server for this session.
/// </summary>
public HttpWebClient WebSession { get; }
public HttpWebClient HttpClient { get; }
[Obsolete("Use HttpClient instead.")]
public HttpWebClient WebSession => HttpClient;
/// <summary>
/// Are we using a custom upstream HTTP(S) proxy?
......@@ -136,7 +140,7 @@ namespace Titanium.Web.Proxy.EventArguments
DataReceived = null;
Exception = null;
WebSession.FinishSession();
HttpClient.FinishSession();
}
/// <summary>
......
......@@ -16,7 +16,7 @@ namespace Titanium.Web.Proxy.EventArguments
CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, cancellationTokenSource, connectRequest)
{
WebSession.ConnectRequest = connectRequest;
HttpClient.ConnectRequest = connectRequest;
}
/// <summary>
......
......@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy
connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest,
cancellationTokenSource);
connectArgs.ProxyClient.ClientConnection = clientConnection;
connectArgs.ProxyClient.Connection = clientConnection;
connectArgs.ProxyClient.ClientStream = clientStream;
await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);
......@@ -83,9 +83,9 @@ namespace Titanium.Web.Proxy
if (connectArgs.DenyConnect)
{
if (connectArgs.WebSession.Response.StatusCode == 0)
if (connectArgs.HttpClient.Response.StatusCode == 0)
{
connectArgs.WebSession.Response = new Response
connectArgs.HttpClient.Response = new Response
{
HttpVersion = HttpHeader.Version11,
StatusCode = (int)HttpStatusCode.Forbidden,
......@@ -94,7 +94,7 @@ namespace Titanium.Web.Proxy
}
// send the response
await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response,
await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
cancellationToken: cancellationToken);
return;
}
......@@ -104,7 +104,7 @@ namespace Titanium.Web.Proxy
await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc);
// send the response
await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response,
await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
cancellationToken: cancellationToken);
return;
}
......@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy
// Set ContentLength explicitly to properly handle HTTP 1.0
response.ContentLength = 0;
response.Headers.FixProxyHeaders();
connectArgs.WebSession.Response = response;
connectArgs.HttpClient.Response = response;
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken);
......@@ -252,7 +252,7 @@ namespace Titanium.Web.Proxy
}
var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream, BufferPool, cancellationToken);
((ConnectResponse)connectArgs.WebSession.Response).ServerHelloInfo = serverHelloInfo;
((ConnectResponse)connectArgs.HttpClient.Response).ServerHelloInfo = serverHelloInfo;
}
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, BufferSize,
......@@ -321,7 +321,7 @@ namespace Titanium.Web.Proxy
calledRequestHandler = true;
// Now create the request
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest, prefetchConnectionTask);
cancellationTokenSource, connectHostname, connectArgs?.HttpClient.ConnectRequest, prefetchConnectionTask);
}
catch (ProxyException e)
{
......
......@@ -17,16 +17,16 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
public class HttpWebClient
{
internal HttpWebClient(Request request = null, Response response = null)
internal HttpWebClient(Request request)
{
Request = request ?? new Request();
Response = response ?? new Response();
Response = new Response();
}
/// <summary>
/// Connection to server
/// </summary>
internal TcpServerConnection ServerConnection { get; set; }
internal TcpServerConnection Connection { get; set; }
/// <summary>
/// Should we close the server connection at the end of this HTTP request/response session.
......@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Http
internal void SetConnection(TcpServerConnection serverConnection)
{
serverConnection.LastAccess = DateTime.Now;
ServerConnection = serverConnection;
Connection = serverConnection;
}
/// <summary>
......@@ -91,11 +91,11 @@ namespace Titanium.Web.Proxy.Http
internal async Task SendRequest(bool enable100ContinueBehaviour, bool isTransparent,
CancellationToken cancellationToken)
{
var upstreamProxy = ServerConnection.UpStreamProxy;
var upstreamProxy = Connection.UpStreamProxy;
bool useUpstreamProxy = upstreamProxy != null && ServerConnection.IsHttps == false;
bool useUpstreamProxy = upstreamProxy != null && Connection.IsHttps == false;
var writer = ServerConnection.StreamWriter;
var writer = Connection.StreamWriter;
// prepare the request & headers
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method,
......@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Http
// Send Authentication to Upstream proxy if needed
if (!isTransparent && upstreamProxy != null
&& ServerConnection.IsHttps == false
&& Connection.IsHttps == false
&& !string.IsNullOrEmpty(upstreamProxy.UserName)
&& upstreamProxy.Password != null)
{
......@@ -134,7 +134,7 @@ namespace Titanium.Web.Proxy.Http
string httpStatus;
try
{
httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken);
httpStatus = await Connection.Stream.ReadLineAsync(cancellationToken);
if (httpStatus == null)
{
throw new ServerConnectionException("Server connection was closed.");
......@@ -153,13 +153,13 @@ namespace Titanium.Web.Proxy.Http
&& responseStatusDescription.EqualsIgnoreCase("continue"))
{
Request.Is100Continue = true;
await ServerConnection.Stream.ReadLineAsync(cancellationToken);
await Connection.Stream.ReadLineAsync(cancellationToken);
}
else if (responseStatusCode == (int)HttpStatusCode.ExpectationFailed
&& responseStatusDescription.EqualsIgnoreCase("expectation failed"))
{
Request.ExpectationFailed = true;
await ServerConnection.Stream.ReadLineAsync(cancellationToken);
await Connection.Stream.ReadLineAsync(cancellationToken);
}
}
}
......@@ -180,7 +180,7 @@ namespace Titanium.Web.Proxy.Http
string httpStatus;
try
{
httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken);
httpStatus = await Connection.Stream.ReadLineAsync(cancellationToken);
if (httpStatus == null)
{
throw new ServerConnectionException("Server connection was closed.");
......@@ -193,7 +193,7 @@ namespace Titanium.Web.Proxy.Http
if (httpStatus == string.Empty)
{
httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken);
httpStatus = await Connection.Stream.ReadLineAsync(cancellationToken);
}
Response.ParseResponseLine(httpStatus, out var version, out int statusCode, out string statusDescription);
......@@ -209,7 +209,7 @@ namespace Titanium.Web.Proxy.Http
// Read the next line after 100-continue
Response.Is100Continue = true;
Response.StatusCode = 0;
await ServerConnection.Stream.ReadLineAsync(cancellationToken);
await Connection.Stream.ReadLineAsync(cancellationToken);
// now receive response
await ReceiveResponse(cancellationToken);
......@@ -222,7 +222,7 @@ namespace Titanium.Web.Proxy.Http
// read next line after expectation failed response
Response.ExpectationFailed = true;
Response.StatusCode = 0;
await ServerConnection.Stream.ReadLineAsync(cancellationToken);
await Connection.Stream.ReadLineAsync(cancellationToken);
// now receive response
await ReceiveResponse(cancellationToken);
......@@ -230,7 +230,7 @@ namespace Titanium.Web.Proxy.Http
}
// Read the response headers in to unique and non-unique header collections
await HeaderParser.ReadHeaders(ServerConnection.Stream, Response.Headers, cancellationToken);
await HeaderParser.ReadHeaders(Connection.Stream, Response.Headers, cancellationToken);
}
/// <summary>
......@@ -238,7 +238,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
internal void FinishSession()
{
ServerConnection = null;
Connection = null;
ConnectRequest?.FinishSession();
Request?.FinishSession();
......
......@@ -12,7 +12,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// TcpClient connection used to communicate with client
/// </summary>
internal TcpClientConnection ClientConnection { get; set; }
internal TcpClientConnection Connection { get; set; }
/// <summary>
/// Holds the stream to client
......
......@@ -98,10 +98,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
session.CustomUpStreamProxyUsed = customUpStreamProxy;
return GetConnectionCacheKey(
session.WebSession.Request.RequestUri.Host,
session.WebSession.Request.RequestUri.Port,
session.HttpClient.Request.RequestUri.Host,
session.HttpClient.Request.RequestUri.Port,
isHttps, applicationProtocols,
server, session.WebSession.UpStreamEndPoint ?? server.UpStreamEndPoint,
server, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint,
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy));
}
......@@ -148,11 +148,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
session.CustomUpStreamProxyUsed = customUpStreamProxy;
return await GetServerConnection(
session.WebSession.Request.RequestUri.Host,
session.WebSession.Request.RequestUri.Port,
session.WebSession.Request.HttpVersion,
session.HttpClient.Request.RequestUri.Host,
session.HttpClient.Request.RequestUri.Port,
session.HttpClient.Request.HttpVersion,
isHttps, applicationProtocols, isConnect,
server, session, session.WebSession.UpStreamEndPoint ?? server.UpStreamEndPoint,
server, session, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint,
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy),
noCache, cancellationToken);
}
......
......@@ -26,14 +26,14 @@ namespace Titanium.Web.Proxy
return true;
}
var httpHeaders = session.WebSession.Request.Headers;
var httpHeaders = session.HttpClient.Request.Headers;
try
{
var header = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization);
if (header == null)
{
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Required");
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Required");
return false;
}
......@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy
if (headerValueParts.Length != 2)
{
// Return not authorized
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false;
}
......@@ -57,7 +57,7 @@ namespace Titanium.Web.Proxy
if (result.Result == ProxyAuthenticationResult.ContinuationNeeded)
{
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid", result.Continuation);
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid", result.Continuation);
return false;
}
......@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy
httpHeaders));
// Return not authorized
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false;
}
}
......@@ -83,7 +83,7 @@ namespace Titanium.Web.Proxy
if (!headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic))
{
// Return not authorized
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false;
}
......@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy
if (colonIndex == -1)
{
// Return not authorized
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false;
}
......@@ -101,7 +101,7 @@ namespace Titanium.Web.Proxy
bool authenticated = await ProxyBasicAuthenticateFunc(session, username, password);
if (!authenticated)
{
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
}
return authenticated;
......
......@@ -679,7 +679,7 @@ namespace Titanium.Web.Proxy
/// <returns>The external proxy as task result.</returns>
private Task<ExternalProxy> getSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs)
{
var proxy = systemProxyResolver.GetProxy(sessionEventArgs.WebSession.Request.RequestUri);
var proxy = systemProxyResolver.GetProxy(sessionEventArgs.HttpClient.Request.RequestUri);
return Task.FromResult(proxy);
}
......
......@@ -15,6 +15,7 @@ using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared;
......@@ -71,8 +72,8 @@ namespace Titanium.Web.Proxy
var args = new SessionEventArgs(this, endPoint, cancellationTokenSource)
{
ProxyClient = { ClientConnection = clientConnection },
WebSession = { ConnectRequest = connectRequest }
ProxyClient = { Connection = clientConnection },
HttpClient = { ConnectRequest = connectRequest }
};
try
......@@ -83,7 +84,7 @@ namespace Titanium.Web.Proxy
out var version);
// Read the request headers in to unique and non-unique header collections
await HeaderParser.ReadHeaders(clientStream, args.WebSession.Request.Headers,
await HeaderParser.ReadHeaders(clientStream, args.HttpClient.Request.Headers,
cancellationToken);
Uri httpRemoteUri;
......@@ -100,7 +101,7 @@ namespace Titanium.Web.Proxy
}
else
{
string host = args.WebSession.Request.Host ?? httpsConnectHostname;
string host = args.HttpClient.Request.Host ?? httpsConnectHostname;
string hostAndPath = host;
if (httpUrl.StartsWith("/"))
{
......@@ -119,7 +120,7 @@ namespace Titanium.Web.Proxy
}
}
var request = args.WebSession.Request;
var request = args.HttpClient.Request;
request.RequestUri = httpRemoteUri;
request.OriginalUrl = httpUrl;
......@@ -136,7 +137,7 @@ namespace Titanium.Web.Proxy
await invokeBeforeResponse(args);
// send the response
await clientStreamWriter.WriteResponseAsync(args.WebSession.Response,
await clientStreamWriter.WriteResponseAsync(args.HttpClient.Response,
cancellationToken: cancellationToken);
return;
}
......@@ -161,7 +162,7 @@ namespace Titanium.Web.Proxy
// If user requested interception do it
await invokeBeforeRequest(args);
var response = args.WebSession.Response;
var response = args.HttpClient.Response;
if (request.CancelRequest)
{
......@@ -197,49 +198,51 @@ namespace Titanium.Web.Proxy
connection = null;
}
RetryResult result;
if (request.UpgradeToWebSocket)
{
//a connection generator task with captured parameters via closure.
Func<Task<TcpServerConnection>> generator = () =>
tcpConnectionFactory.GetServerConnection(this, args, isConnect: false,
applicationProtocol:clientConnection.NegotiatedApplicationProtocol,
applicationProtocol: clientConnection.NegotiatedApplicationProtocol,
noCache: false, cancellationToken: cancellationToken);
//for connection pool, retry fails until cache is exhausted.
var result = await retryPolicy<ServerConnectionException>().ExecuteAsync(async (serverConnection) =>
result = await retryPolicy<ServerConnectionException>().ExecuteAsync(async (serverConnection) =>
{
args.TimeLine["Connection Ready"] = DateTime.Now;
// if upgrading to websocket then relay the request without reading the contents
if (request.UpgradeToWebSocket)
{
await handleWebSocketUpgrade(httpCmd, args, request,
response, clientStream, clientStreamWriter,
serverConnection, cancellationTokenSource, cancellationToken);
closeServerConnection = true;
return false;
}
// construct the web request that we are going to issue on behalf of the client.
await handleHttpSessionRequest(serverConnection, args);
return true;
}, generator, connection);
}
else
{
result = await handleHttpSessionRequest(args, connection,
clientConnection.NegotiatedApplicationProtocol, cancellationToken);
}
//update connection to latest used
connection = result.LatestConnection;
//throw if exception happened
if(!result.IsSuccess)
if (!result.IsSuccess)
{
throw result.Exception;
}
if(!result.Continue)
if (!result.Continue)
{
return;
}
//user requested
if (args.WebSession.CloseServerConnection)
if (args.HttpClient.CloseServerConnection)
{
closeServerConnection = true;
return;
......@@ -262,7 +265,7 @@ namespace Titanium.Web.Proxy
//between sessions without using it.
//Do not release authenticated connections for performance reasons.
//Otherwise it will keep authenticating per session.
if (EnableConnectionPool && connection!=null
if (EnableConnectionPool && connection != null
&& !connection.IsWinAuthenticated)
{
await tcpConnectionFactory.Release(connection);
......@@ -297,6 +300,38 @@ namespace Titanium.Web.Proxy
}
}
private async Task<RetryResult> handleHttpSessionRequest(SessionEventArgs args,
TcpServerConnection connection,
SslApplicationProtocol protocol,
CancellationToken cancellationToken)
{
//host/scheme changed from ReRequest
if (args.ReRequest
&& (args.HttpClient.Request.IsHttps != connection.IsHttps
|| args.HttpClient.Request.Host != connection.HostName))
{
connection = null;
}
//a connection generator task with captured parameters via closure.
Func<Task<TcpServerConnection>> generator = () =>
tcpConnectionFactory.GetServerConnection(this, args, isConnect: false,
applicationProtocol: protocol,
noCache: false, cancellationToken: cancellationToken);
//for connection pool, retry fails until cache is exhausted.
return await retryPolicy<ServerConnectionException>().ExecuteAsync(async (serverConnection) =>
{
args.TimeLine["Connection Ready"] = DateTime.Now;
// construct the web request that we are going to issue on behalf of the client.
await handleHttpSessionRequest(serverConnection, args);
return true;
}, generator, connection);
}
/// <summary>
/// Handle a specific session (request/response sequence)
/// </summary>
......@@ -306,7 +341,7 @@ namespace Titanium.Web.Proxy
private async Task handleHttpSessionRequest(TcpServerConnection serverConnection, SessionEventArgs args)
{
var cancellationToken = args.CancellationTokenSource.Token;
var request = args.WebSession.Request;
var request = args.HttpClient.Request;
request.Locked = true;
var body = request.CompressBodyAndUpdateContentLength();
......@@ -315,8 +350,8 @@ namespace Titanium.Web.Proxy
// and see if server would return 100 conitinue
if (request.ExpectContinue)
{
args.WebSession.SetConnection(serverConnection);
await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
args.HttpClient.SetConnection(serverConnection);
await args.HttpClient.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
cancellationToken);
}
......@@ -327,13 +362,13 @@ namespace Titanium.Web.Proxy
if (request.Is100Continue)
{
await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpVersion,
await clientStreamWriter.WriteResponseStatusAsync(args.HttpClient.Response.HttpVersion,
(int)HttpStatusCode.Continue, "Continue", cancellationToken);
await clientStreamWriter.WriteLineAsync(cancellationToken);
}
else if (request.ExpectationFailed)
{
await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpVersion,
await clientStreamWriter.WriteResponseStatusAsync(args.HttpClient.Response.HttpVersion,
(int)HttpStatusCode.ExpectationFailed, "Expectation Failed", cancellationToken);
await clientStreamWriter.WriteLineAsync(cancellationToken);
}
......@@ -342,8 +377,8 @@ namespace Titanium.Web.Proxy
// If expect continue is not enabled then set the connectio and send request headers
if (!request.ExpectContinue)
{
args.WebSession.SetConnection(serverConnection);
await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
args.HttpClient.SetConnection(serverConnection);
await args.HttpClient.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
cancellationToken);
}
......@@ -352,7 +387,7 @@ namespace Titanium.Web.Proxy
{
if (request.IsBodyRead)
{
var writer = args.WebSession.ServerConnection.StreamWriter;
var writer = args.HttpClient.Connection.StreamWriter;
await writer.WriteBodyAsync(body, request.IsChunked, cancellationToken);
}
else
......@@ -361,7 +396,7 @@ namespace Titanium.Web.Proxy
{
if (request.HasBody)
{
HttpWriter writer = args.WebSession.ServerConnection.StreamWriter;
HttpWriter writer = args.HttpClient.Connection.StreamWriter;
await args.CopyRequestBodyAsync(writer, TransformationMode.None, cancellationToken);
}
}
......
......@@ -22,11 +22,11 @@ namespace Titanium.Web.Proxy
var cancellationToken = args.CancellationTokenSource.Token;
// read response & headers from server
await args.WebSession.ReceiveResponse(cancellationToken);
await args.HttpClient.ReceiveResponse(cancellationToken);
args.TimeLine["Response Received"] = DateTime.Now;
var response = args.WebSession.Response;
var response = args.HttpClient.Response;
args.ReRequest = false;
// check for windows authentication
......@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy
}
else
{
WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data);
WinAuthEndPoint.AuthenticatedResponse(args.HttpClient.Data);
}
}
......@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy
}
// it may changed in the user event
response = args.WebSession.Response;
response = args.HttpClient.Response;
var clientStreamWriter = args.ProxyClient.ClientStreamWriter;
......@@ -63,8 +63,8 @@ namespace Titanium.Web.Proxy
//write custom user response with body and return.
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken);
if(args.WebSession.ServerConnection != null
&& !args.WebSession.CloseServerConnection)
if(args.HttpClient.Connection != null
&& !args.HttpClient.CloseServerConnection)
{
// syphon out the original response body from server connection
// so that connection will be good to be reused.
......@@ -80,7 +80,8 @@ namespace Titanium.Web.Proxy
{
// clear current response
await args.ClearResponse(cancellationToken);
await handleHttpSessionRequest(args.WebSession.ServerConnection, args);
await handleHttpSessionRequest(args, args.HttpClient.Connection,
args.ClientConnection.NegotiatedApplicationProtocol, cancellationToken);
return;
}
......
......@@ -58,7 +58,7 @@ namespace Titanium.Web.Proxy
}
// If user requested call back then do it
if (!args.WebSession.Response.Locked)
if (!args.HttpClient.Response.Locked)
{
await invokeBeforeResponse(args);
}
......
......@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy
string headerName = null;
HttpHeader authHeader = null;
var response = args.WebSession.Response;
var response = args.HttpClient.Response;
// check in non-unique headers first
var header = response.Headers.NonUniqueHeaders.FirstOrDefault(x => authHeaderNames.Contains(x.Key));
......@@ -96,14 +96,14 @@ namespace Titanium.Web.Proxy
var expectedAuthState =
scheme == null ? State.WinAuthState.INITIAL_TOKEN : State.WinAuthState.UNAUTHORIZED;
if (!WinAuthEndPoint.ValidateWinAuthState(args.WebSession.Data, expectedAuthState))
if (!WinAuthEndPoint.ValidateWinAuthState(args.HttpClient.Data, expectedAuthState))
{
// Invalid state, create proper error message to client
await rewriteUnauthorizedResponse(args);
return;
}
var request = args.WebSession.Request;
var request = args.HttpClient.Request;
// clear any existing headers to avoid confusing bad servers
request.Headers.RemoveHeader(KnownHeaders.Authorization);
......@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy
// initial value will match exactly any of the schemes
if (scheme != null)
{
string clientToken = WinAuthHandler.GetInitialAuthToken(request.Host, scheme, args.WebSession.Data);
string clientToken = WinAuthHandler.GetInitialAuthToken(request.Host, scheme, args.HttpClient.Data);
string auth = string.Concat(scheme, clientToken);
......@@ -133,7 +133,7 @@ namespace Titanium.Web.Proxy
authHeader.Value.Length > x.Length + 1);
string serverToken = authHeader.Value.Substring(scheme.Length + 1);
string clientToken = WinAuthHandler.GetFinalAuthToken(request.Host, serverToken, args.WebSession.Data);
string clientToken = WinAuthHandler.GetFinalAuthToken(request.Host, serverToken, args.HttpClient.Data);
string auth = string.Concat(scheme, clientToken);
......@@ -146,7 +146,7 @@ namespace Titanium.Web.Proxy
request.ContentLength = request.Body.Length;
}
args.WebSession.ServerConnection.IsWinAuthenticated = true;
args.HttpClient.Connection.IsWinAuthenticated = true;
}
// Need to revisit this.
......@@ -165,7 +165,7 @@ namespace Titanium.Web.Proxy
/// <returns></returns>
private async Task rewriteUnauthorizedResponse(SessionEventArgs args)
{
var response = args.WebSession.Response;
var response = args.HttpClient.Response;
// Strip authentication headers to avoid credentials prompt in client web browser
foreach (string authHeaderName in authHeaderNames)
......@@ -176,7 +176,7 @@ namespace Titanium.Web.Proxy
// Add custom div to body to clarify that the proxy (not the client browser) failed authentication
string authErrorMessage =
"<div class=\"inserted-by-proxy\"><h2>NTLM authentication through Titanium.Web.Proxy (" +
args.ProxyClient.ClientConnection.LocalEndPoint +
args.ProxyClient.Connection.LocalEndPoint +
") failed. Please check credentials.</h2></div>";
string originalErrorMessage =
"<div class=\"inserted-by-proxy\"><h3>Response from remote web server below.</h3></div><br/>";
......
......@@ -46,9 +46,9 @@ namespace Titanium.Web.Proxy.IntegrationTests
public async Task OnRequest(object sender, SessionEventArgs e)
{
if (e.WebSession.Request.Url.Contains("interceptthis.com"))
if (e.HttpClient.Request.Url.Contains("interceptthis.com"))
{
if (e.WebSession.Request.HasBody)
if (e.HttpClient.Request.HasBody)
{
var body = await e.GetRequestBodyAsString();
}
......
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