Commit 4306e64c authored by Honfika's avatar Honfika

read the request body even when it was reditected

parent a2961205
...@@ -107,15 +107,18 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -107,15 +107,18 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Constructor to initialize the proxy /// Constructor to initialize the proxy
/// </summary> /// </summary>
internal SessionEventArgs(int bufferSize, internal SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ExceptionHandler exceptionFunc)
ProxyEndPoint endPoint, : this(bufferSize, endPoint, exceptionFunc, null)
ExceptionHandler exceptionFunc) {
}
protected SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ExceptionHandler exceptionFunc, Request request)
{ {
this.bufferSize = bufferSize; this.bufferSize = bufferSize;
this.exceptionFunc = exceptionFunc; this.exceptionFunc = exceptionFunc;
ProxyClient = new ProxyClient(); ProxyClient = new ProxyClient();
WebSession = new HttpWebClient(bufferSize); WebSession = new HttpWebClient(bufferSize, request);
LocalEndPoint = endPoint; LocalEndPoint = endPoint;
WebSession.ProcessId = new Lazy<int>(() => WebSession.ProcessId = new Lazy<int>(() =>
...@@ -138,6 +141,21 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -138,6 +141,21 @@ namespace Titanium.Web.Proxy.EventArguments
}); });
} }
private CustomBufferedStream GetStream(bool isRequest)
{
return isRequest ? ProxyClient.ClientStream : WebSession.ServerConnection.Stream;
}
private CustomBinaryReader GetStreamReader(bool isRequest)
{
return isRequest ? ProxyClient.ClientStreamReader : WebSession.ServerConnection.StreamReader;
}
private HttpWriter GetStreamWriter(bool isRequest)
{
return isRequest ? (HttpWriter)ProxyClient.ClientStreamWriter : WebSession.ServerConnection.StreamWriter;
}
/// <summary> /// <summary>
/// Read request body content as bytes[] for current session /// Read request body content as bytes[] for current session
/// </summary> /// </summary>
...@@ -240,34 +258,51 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -240,34 +258,51 @@ namespace Titanium.Web.Proxy.EventArguments
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
var writer = new HttpWriter(bodyStream, bufferSize); var writer = new HttpWriter(bodyStream, bufferSize);
if (isRequest) await ReadBodyAsync(writer, reader, isRequest);
{
await CopyRequestBodyAsync(writer, TransformationMode.Uncompress);
}
else
{
await CopyResponseBodyAsync(writer, TransformationMode.Uncompress);
}
return bodyStream.ToArray(); return bodyStream.ToArray();
} }
} }
internal async Task SiphonBodyAsync(bool isRequest)
{
var requestResponse = isRequest ? (RequestResponseBase)WebSession.Request : WebSession.Response;
if (requestResponse.IsBodyRead || !requestResponse.OriginalHasBody)
{
return;
}
var reader = GetStreamReader(isRequest);
using (var bodyStream = new MemoryStream())
{
var writer = new HttpWriter(bodyStream, bufferSize);
await ReadBodyAsync(writer, reader, isRequest);
}
}
private Task ReadBodyAsync(HttpWriter writer, CustomBinaryReader reader, bool isRequest)
{
if (isRequest)
{
return CopyRequestBodyAsync(writer, TransformationMode.Uncompress);
}
return CopyResponseBodyAsync(writer, TransformationMode.Uncompress);
}
/// <summary> /// <summary>
/// This is called when the request is PUT/POST/PATCH to read the body /// This is called when the request is PUT/POST/PATCH to read the body
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode transformation) internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode transformation)
{ {
// End the operation
var request = WebSession.Request; var request = WebSession.Request;
var reader = ProxyClient.ClientStreamReader;
long contentLength = request.ContentLength; long contentLength = request.ContentLength;
//send the request body bytes to server //send the request body bytes to server
if (contentLength > 0 && hasMulipartEventSubscribers && request.IsMultipartFormData) if (contentLength > 0 && hasMulipartEventSubscribers && request.IsMultipartFormData)
{ {
var reader = GetStreamReader(true);
string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType); string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);
using (var copyStream = new CopyStream(reader, writer, bufferSize)) using (var copyStream = new CopyStream(reader, writer, bufferSize))
...@@ -294,21 +329,22 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -294,21 +329,22 @@ namespace Titanium.Web.Proxy.EventArguments
} }
else else
{ {
await CopyBodyAsync(ProxyClient.ClientStream, reader, writer, request, transformation, OnDataSent); await CopyBodyAsync(true, writer, transformation, OnDataSent);
} }
} }
internal async Task CopyResponseBodyAsync(HttpWriter writer, TransformationMode transformation) internal async Task CopyResponseBodyAsync(HttpWriter writer, TransformationMode transformation)
{ {
var response = WebSession.Response; await CopyBodyAsync(false, writer, transformation, OnDataReceived);
var reader = WebSession.ServerConnection.StreamReader;
await CopyBodyAsync(WebSession.ServerConnection.Stream, reader, writer, response, transformation, OnDataReceived);
} }
private async Task CopyBodyAsync(CustomBufferedStream stream, CustomBinaryReader reader, HttpWriter writer, private async Task CopyBodyAsync(bool isRequest, HttpWriter writer, TransformationMode transformation, Action<byte[], int, int> onCopy)
RequestResponseBase requestResponse, TransformationMode transformation, Action<byte[], int, int> onCopy)
{ {
var stream = GetStream(isRequest);
var reader = GetStreamReader(isRequest);
var requestResponse = isRequest ? (RequestResponseBase)WebSession.Request : WebSession.Response;
bool isChunked = requestResponse.IsChunked; bool isChunked = requestResponse.IsChunked;
long contentLength = requestResponse.ContentLength; long contentLength = requestResponse.ContentLength;
if (transformation == TransformationMode.None) if (transformation == TransformationMode.None)
......
...@@ -11,9 +11,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -11,9 +11,8 @@ namespace Titanium.Web.Proxy.EventArguments
public bool IsHttpsConnect { get; internal set; } public bool IsHttpsConnect { get; internal set; }
internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, ExceptionHandler exceptionFunc) internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, ExceptionHandler exceptionFunc)
: base(bufferSize, endPoint, exceptionFunc) : base(bufferSize, endPoint, exceptionFunc, connectRequest)
{ {
WebSession.Request = connectRequest;
} }
} }
} }
...@@ -5,7 +5,6 @@ using System.Text; ...@@ -5,7 +5,6 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Helpers; using StreamExtended.Helpers;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
......
...@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Web Request. /// Web Request.
/// </summary> /// </summary>
public Request Request { get; internal set; } public Request Request { get; }
/// <summary> /// <summary>
/// Web Response. /// Web Response.
...@@ -56,13 +56,13 @@ namespace Titanium.Web.Proxy.Http ...@@ -56,13 +56,13 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public bool IsHttps => Request.IsHttps; public bool IsHttps => Request.IsHttps;
internal HttpWebClient(int bufferSize) internal HttpWebClient(int bufferSize, Request request = null, Response response = null)
{ {
this.bufferSize = bufferSize; this.bufferSize = bufferSize;
RequestId = Guid.NewGuid(); RequestId = Guid.NewGuid();
Request = new Request(); Request = request ?? new Request();
Response = new Response(); Response = response ?? new Response();
} }
/// <summary> /// <summary>
......
...@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Has request body? /// Has request body?
/// </summary> /// </summary>
public bool HasBody public override bool HasBody
{ {
get get
{ {
......
...@@ -134,6 +134,17 @@ namespace Titanium.Web.Proxy.Http ...@@ -134,6 +134,17 @@ namespace Titanium.Web.Proxy.Http
bodyString = null; bodyString = null;
} }
} }
/// <summary>
/// Has the request/response body?
/// </summary>
public abstract bool HasBody { get; }
/// <summary>
/// Store weather the original request/response has body or not, since the user may change the parameters
/// </summary>
internal bool OriginalHasBody;
internal abstract void EnsureBodyAvailable(bool throwWhenNotReadYet = true); internal abstract void EnsureBodyAvailable(bool throwWhenNotReadYet = true);
/// <summary> /// <summary>
......
...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Has response body? /// Has response body?
/// </summary> /// </summary>
public bool HasBody public override bool HasBody
{ {
get get
{ {
......
...@@ -347,11 +347,12 @@ namespace Titanium.Web.Proxy ...@@ -347,11 +347,12 @@ namespace Titanium.Web.Proxy
} }
} }
args.WebSession.Request.RequestUri = httpRemoteUri; var request = args.WebSession.Request;
args.WebSession.Request.OriginalUrl = httpUrl; request.RequestUri = httpRemoteUri;
request.OriginalUrl = httpUrl;
args.WebSession.Request.Method = httpMethod; request.Method = httpMethod;
args.WebSession.Request.HttpVersion = version; request.HttpVersion = version;
args.ProxyClient.ClientStream = clientStream; args.ProxyClient.ClientStream = clientStream;
args.ProxyClient.ClientStreamReader = clientStreamReader; args.ProxyClient.ClientStreamReader = clientStreamReader;
args.ProxyClient.ClientStreamWriter = clientStreamWriter; args.ProxyClient.ClientStreamWriter = clientStreamWriter;
...@@ -368,25 +369,28 @@ namespace Titanium.Web.Proxy ...@@ -368,25 +369,28 @@ namespace Titanium.Web.Proxy
if (!isTransparentEndPoint) if (!isTransparentEndPoint)
{ {
PrepareRequestHeaders(args.WebSession.Request.Headers); PrepareRequestHeaders(request.Headers);
args.WebSession.Request.Host = args.WebSession.Request.RequestUri.Authority; request.Host = request.RequestUri.Authority;
} }
//if win auth is enabled //if win auth is enabled
//we need a cache of request body //we need a cache of request body
//so that we can send it after authentication in WinAuthHandler.cs //so that we can send it after authentication in WinAuthHandler.cs
if (isWindowsAuthenticationEnabledAndSupported && args.WebSession.Request.HasBody) if (isWindowsAuthenticationEnabledAndSupported && request.HasBody)
{ {
await args.GetRequestBody(); await args.GetRequestBody();
} }
request.OriginalHasBody = request.HasBody;
//If user requested interception do it //If user requested interception do it
await InvokeBeforeRequest(args); await InvokeBeforeRequest(args);
var response = args.WebSession.Response; var response = args.WebSession.Response;
if (args.WebSession.Request.CancelRequest) if (request.CancelRequest)
{ {
await args.SiphonBodyAsync(true);
await HandleHttpSessionResponse(args); await HandleHttpSessionResponse(args);
if (!response.KeepAlive) if (!response.KeepAlive)
...@@ -413,7 +417,7 @@ namespace Titanium.Web.Proxy ...@@ -413,7 +417,7 @@ namespace Titanium.Web.Proxy
} }
//if upgrading to websocket then relay the requet without reading the contents //if upgrading to websocket then relay the requet without reading the contents
if (args.WebSession.Request.UpgradeToWebSocket) if (request.UpgradeToWebSocket)
{ {
//prepare the prefix content //prepare the prefix content
var requestHeaders = args.WebSession.Request.Headers; var requestHeaders = args.WebSession.Request.Headers;
......
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