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