Commit ee9a0929 authored by justcoding121's avatar justcoding121 Committed by justcoding121

Fix POST chunked file upload

parent 1379388d
...@@ -57,9 +57,9 @@ Sample request and response event handlers ...@@ -57,9 +57,9 @@ Sample request and response event handlers
{ {
Console.WriteLine(e.RequestURL); Console.WriteLine(e.RequestURL);
//modify request headers //read request headers
var requestHeaders = e.RequestHeaders; var requestHeaders = e.RequestHeaders;
if ((e.RequestMethod.ToUpper() == "POST" || e.RequestMethod.ToUpper() == "PUT") && e.RequestContentLength > 0) if ((e.RequestMethod.ToUpper() == "POST" || e.RequestMethod.ToUpper() == "PUT") && e.RequestContentLength > 0)
...@@ -87,9 +87,10 @@ Sample request and response event handlers ...@@ -87,9 +87,10 @@ Sample request and response event handlers
public void OnResponse(object sender, SessionEventArgs e) public void OnResponse(object sender, SessionEventArgs e)
{ {
//modify response headers //read response headers
var responseHeaders = e.ResponseHeaders; var responseHeaders = e.ResponseHeaders;
if (e.ResponseStatusCode == HttpStatusCode.OK) if (e.ResponseStatusCode == HttpStatusCode.OK)
{ {
if (e.ResponseContentType.Trim().ToLower().Contains("text/html")) if (e.ResponseContentType.Trim().ToLower().Contains("text/html"))
...@@ -101,7 +102,7 @@ Sample request and response event handlers ...@@ -101,7 +102,7 @@ Sample request and response event handlers
//Get response body as string //Get response body as string
string responseBody = e.GetResponseBodyAsString(); string responseBody = e.GetResponseBodyAsString();
//Inject script in to body //Modify e.ServerResponse
Regex rex = new Regex("</body>", RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.Multiline); Regex rex = new Regex("</body>", RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.Multiline);
string modified = rex.Replace(responseBody, "<script type =\"text/javascript\">alert('Response was modified by this script!');</script></body>", 1); string modified = rex.Replace(responseBody, "<script type =\"text/javascript\">alert('Response was modified by this script!');</script></body>", 1);
......
...@@ -60,10 +60,10 @@ namespace Titanium.Web.Proxy.Test ...@@ -60,10 +60,10 @@ namespace Titanium.Web.Proxy.Test
Console.WriteLine(e.RequestURL); Console.WriteLine(e.RequestURL);
////modify request headers ////read request headers
//var requestHeaders = e.RequestHeaders; //var requestHeaders = e.RequestHeaders;
//if ((e.RequestMethod.ToUpper() == "POST" || e.RequestMethod.ToUpper() == "PUT") && e.RequestContentLength > 0) //if ((e.RequestMethod.ToUpper() == "POST" || e.RequestMethod.ToUpper() == "PUT"))
//{ //{
// //Get/Set request body bytes // //Get/Set request body bytes
// byte[] bodyBytes = e.GetRequestBody(); // byte[] bodyBytes = e.GetRequestBody();
...@@ -89,9 +89,9 @@ namespace Titanium.Web.Proxy.Test ...@@ -89,9 +89,9 @@ namespace Titanium.Web.Proxy.Test
//Insert script to read the Browser URL and send it back to proxy //Insert script to read the Browser URL and send it back to proxy
public void OnResponse(object sender, SessionEventArgs e) public void OnResponse(object sender, SessionEventArgs e)
{ {
////modify response headers ////read response headers
//var responseHeaders = e.ResponseHeaders; //var responseHeaders = e.ResponseHeaders;
//if (e.ResponseStatusCode == HttpStatusCode.OK) //if (e.ResponseStatusCode == HttpStatusCode.OK)
//{ //{
......
...@@ -21,6 +21,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -21,6 +21,14 @@ namespace Titanium.Web.Proxy.EventArguments
internal CustomBinaryReader clientStreamReader { get; set; } internal CustomBinaryReader clientStreamReader { get; set; }
internal StreamWriter clientStreamWriter { get; set; } internal StreamWriter clientStreamWriter { get; set; }
internal bool isHttps { get; set; }
internal string requestURL { get; set; }
internal string requestHostname { get; set; }
internal int clientPort { get; set; }
internal IPAddress clientIpAddress { get; set; }
internal Encoding requestEncoding { get; set; } internal Encoding requestEncoding { get; set; }
internal Version requestHttpVersion { get; set; } internal Version requestHttpVersion { get; set; }
internal bool requestIsAlive { get; set; } internal bool requestIsAlive { get; set; }
...@@ -28,25 +36,19 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -28,25 +36,19 @@ namespace Titanium.Web.Proxy.EventArguments
internal byte[] requestBody { get; set; } internal byte[] requestBody { get; set; }
internal string requestBodyString { get; set; } internal string requestBodyString { get; set; }
internal bool requestBodyRead { get; set; } internal bool requestBodyRead { get; set; }
internal List<HttpHeader> requestHeaders { get; set; }
internal bool RequestLocked { get; set; }
internal HttpWebRequest proxyRequest { get; set; }
internal Encoding responseEncoding { get; set; } internal Encoding responseEncoding { get; set; }
internal Stream responseStream { get; set; } internal Stream responseStream { get; set; }
internal byte[] responseBody { get; set; } internal byte[] responseBody { get; set; }
internal string responseBodyString { get; set; } internal string responseBodyString { get; set; }
internal bool responseBodyRead { get; set; } internal bool responseBodyRead { get; set; }
internal List<HttpHeader> responseHeaders { get; set; }
internal bool RequestLocked { get; set; }
internal HttpWebRequest proxyRequest { get; set; }
internal bool ResponseLocked { get; set; } internal bool ResponseLocked { get; set; }
internal HttpWebResponse serverResponse { get; set; } internal HttpWebResponse serverResponse { get; set; }
internal bool isHttps { get; set; }
internal string requestURL { get; set; }
internal string requestHostname { get; set; }
internal int clientPort { get; set; }
internal IPAddress clientIpAddress { get; set; }
public int ClientPort { get { return this.clientPort; } } public int ClientPort { get { return this.clientPort; } }
public IPAddress ClientIpAddress { get { return this.clientIpAddress; } } public IPAddress ClientIpAddress { get { return this.clientIpAddress; } }
...@@ -56,14 +58,17 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -56,14 +58,17 @@ namespace Titanium.Web.Proxy.EventArguments
public string RequestURL { get { return this.requestURL; } } public string RequestURL { get { return this.requestURL; } }
public string RequestHostname { get { return this.requestHostname; } } public string RequestHostname { get { return this.requestHostname; } }
public List<HttpHeader> RequestHeaders { get { return this.requestHeaders; } }
public List<HttpHeader> ResponseHeaders { get { return this.responseHeaders; } }
public int RequestContentLength public int RequestContentLength
{ {
get get
{ {
if (this.RequestHeaders.Any(x => x.Name.ToLower() == "content-length")) if (this.requestHeaders.Any(x => x.Name.ToLower() == "content-length"))
{ {
int contentLen; int contentLen;
int.TryParse(this.RequestHeaders.First(x => x.Name.ToLower() == "content-length").Value, out contentLen); int.TryParse(this.requestHeaders.First(x => x.Name.ToLower() == "content-length").Value, out contentLen);
if (contentLen != 0) if (contentLen != 0)
return contentLen; return contentLen;
} }
...@@ -72,11 +77,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -72,11 +77,11 @@ namespace Titanium.Web.Proxy.EventArguments
} }
public string RequestMethod { get { return this.proxyRequest.Method; } } public string RequestMethod { get { return this.proxyRequest.Method; } }
public List<HttpHeader> RequestHeaders { get; set; }
public HttpStatusCode ResponseStatusCode { get { return this.serverResponse.StatusCode; } } public HttpStatusCode ResponseStatusCode { get { return this.serverResponse.StatusCode; } }
public string ResponseContentType { get { return this.ResponseHeaders.Any(x => x.Name.ToLower() == "content-type") ? this.ResponseHeaders.First(x => x.Name.ToLower() == "content-type").Value : null; } } public string ResponseContentType { get { return this.responseHeaders.Any(x => x.Name.ToLower() == "content-type") ? this.responseHeaders.First(x => x.Name.ToLower() == "content-type").Value : null; } }
public List<HttpHeader> ResponseHeaders { get; set; }
internal SessionEventArgs(int bufferSize) internal SessionEventArgs(int bufferSize)
{ {
...@@ -85,9 +90,88 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -85,9 +90,88 @@ namespace Titanium.Web.Proxy.EventArguments
private void readRequestBody() private void readRequestBody()
{ {
if ((proxyRequest.Method.ToUpper() != "POST" && proxyRequest.Method.ToUpper() != "PUT"))
{
throw new BodyNotFoundException("Request don't have a body." +
"Please verify that this request is a Http POST/PUT and request content length is greater than zero before accessing the body.");
}
if (requestBody == null) if (requestBody == null)
{ {
requestBody = clientStreamReader.ReadBytes(RequestContentLength); bool isChunked = false;
string requestContentEncoding = null;
if (requestHeaders.Any(x => x.Name.ToLower() == "content-encoding"))
{
requestContentEncoding = requestHeaders.First(x => x.Name.ToLower() == "content-encoding").Value;
}
if (requestHeaders.Any(x => x.Name.ToLower() == "transfer-encoding"))
{
var transferEncoding = requestHeaders.First(x => x.Name.ToLower() == "transfer-encoding").Value.ToLower();
if (transferEncoding.Contains("chunked"))
{
isChunked = true;
}
}
if (requestContentEncoding == null && !isChunked)
requestBody = clientStreamReader.ReadBytes(RequestContentLength);
else
{
using (var requestBodyStream = new MemoryStream())
{
if (isChunked)
{
while (true)
{
var chuchkHead = clientStreamReader.ReadLine();
var chunkSize = int.Parse(chuchkHead, System.Globalization.NumberStyles.HexNumber);
if (chunkSize != 0)
{
var buffer = clientStreamReader.ReadBytes(chunkSize);
requestBodyStream.Write(buffer, 0, buffer.Length);
var chunkTrail = clientStreamReader.ReadLine();
}
else
{
clientStreamReader.ReadLine();
break;
}
}
}
try
{
switch (requestContentEncoding)
{
case "gzip":
requestBody = CompressionHelper.DecompressGzip(requestBodyStream);
break;
case "deflate":
requestBody = CompressionHelper.DecompressDeflate(requestBodyStream);
break;
case "zlib":
requestBody = CompressionHelper.DecompressGzip(requestBodyStream);
break;
default:
requestBody = requestBodyStream.ToArray();
break;
}
}
catch {
requestBody = requestBodyStream.ToArray();
}
}
}
} }
requestBodyRead = true; requestBodyRead = true;
} }
...@@ -95,6 +179,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -95,6 +179,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
if (responseBody == null) if (responseBody == null)
{ {
switch (serverResponse.ContentEncoding) switch (serverResponse.ContentEncoding)
{ {
case "gzip": case "gzip":
...@@ -144,34 +229,25 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -144,34 +229,25 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
if (RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
if ((proxyRequest.Method.ToUpper() == "POST" || proxyRequest.Method.ToUpper() == "PUT") && RequestContentLength > 0) readRequestBody();
{ return requestBody;
readRequestBody();
return requestBody;
}
else
throw new BodyNotFoundException("Request don't have a body." +
"Please verify that this request is a Http POST/PUT and request content length is greater than zero before accessing the body.");
} }
public string GetRequestBodyAsString() public string GetRequestBodyAsString()
{ {
if (RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
if ((proxyRequest.Method.ToUpper() == "POST" || proxyRequest.Method.ToUpper() == "PUT") && RequestContentLength > 0)
{
readRequestBody();
if (requestBodyString == null) readRequestBody();
{
requestBodyString = requestEncoding.GetString(requestBody); if (requestBodyString == null)
} {
return requestBodyString; requestBodyString = requestEncoding.GetString(requestBody);
} }
else return requestBodyString;
throw new BodyNotFoundException("Request don't have a body." +
"Please verify that this request is a Http POST/PUT and request content length is greater than zero before accessing the body.");
} }
...@@ -302,7 +378,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -302,7 +378,6 @@ namespace Titanium.Web.Proxy.EventArguments
} }
} }
} }
\ No newline at end of file
...@@ -59,7 +59,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -59,7 +59,7 @@ namespace Titanium.Web.Proxy.Helpers
public static byte[] DecompressGzip(Stream input) public static byte[] DecompressGzip(Stream input)
{ {
using (System.IO.Compression.GZipStream decompressor = new System.IO.Compression.GZipStream(input, System.IO.Compression.CompressionMode.Decompress)) using (var decompressor = new System.IO.Compression.GZipStream(input, System.IO.Compression.CompressionMode.Decompress))
{ {
int read = 0; int read = 0;
......
This diff is collapsed.
...@@ -38,10 +38,10 @@ namespace Titanium.Web.Proxy ...@@ -38,10 +38,10 @@ namespace Titanium.Web.Proxy
{ {
if (args.serverResponse != null) if (args.serverResponse != null)
{ {
args.ResponseHeaders = ReadResponseHeaders(args.serverResponse); args.responseHeaders = ReadResponseHeaders(args.serverResponse);
args.responseStream = args.serverResponse.GetResponseStream(); args.responseStream = args.serverResponse.GetResponseStream();
if (BeforeResponse != null) if (BeforeResponse != null)
{ {
args.responseEncoding = args.serverResponse.GetEncoding(); args.responseEncoding = args.serverResponse.GetEncoding();
...@@ -52,11 +52,11 @@ namespace Titanium.Web.Proxy ...@@ -52,11 +52,11 @@ namespace Titanium.Web.Proxy
if (args.responseBodyRead) if (args.responseBodyRead)
{ {
bool isChunked = args.ResponseHeaders.Any(x => x.Name.ToLower() == "transfer-encoding") == false ? false : args.ResponseHeaders.First(x => x.Name.ToLower() == "transfer-encoding").Value.ToLower() == "chunked" ? true : false; bool isChunked = args.serverResponse.GetResponseHeader("transfer-encoding") == null ? false : args.serverResponse.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked") ? true : false;
var contentEncoding = args.ResponseHeaders.FirstOrDefault(x => x.Name.ToLower() == "content-encoding"); var contentEncoding = args.serverResponse.ContentEncoding;
if (contentEncoding != null) if (contentEncoding != null)
switch (contentEncoding.Value.ToLower()) switch (contentEncoding.ToLower())
{ {
case "gzip": case "gzip":
args.responseBody = CompressionHelper.CompressGzip(args.responseBody); args.responseBody = CompressionHelper.CompressGzip(args.responseBody);
...@@ -68,20 +68,20 @@ namespace Titanium.Web.Proxy ...@@ -68,20 +68,20 @@ namespace Titanium.Web.Proxy
args.responseBody = CompressionHelper.CompressZlib(args.responseBody); args.responseBody = CompressionHelper.CompressZlib(args.responseBody);
break; break;
default: default:
throw new Exception("Specified content-encoding header is not supported"); break;
} }
WriteResponseStatus(args.serverResponse.ProtocolVersion, args.serverResponse.StatusCode, args.serverResponse.StatusDescription, args.clientStreamWriter); WriteResponseStatus(args.serverResponse.ProtocolVersion, args.serverResponse.StatusCode, args.serverResponse.StatusDescription, args.clientStreamWriter);
WriteResponseHeaders(args.clientStreamWriter, args.ResponseHeaders, args.responseBody.Length, isChunked); WriteResponseHeaders(args.clientStreamWriter, args.responseHeaders, args.responseBody.Length, isChunked);
WriteResponseBody(args.clientStream, args.responseBody, isChunked); WriteResponseBody(args.clientStream, args.responseBody, isChunked);
} }
else else
{ {
bool isChunked = args.serverResponse.GetResponseHeader("transfer-encoding") == null ? false : args.serverResponse.GetResponseHeader("transfer-encoding").ToLower() == "chunked" ? true : false; bool isChunked = args.serverResponse.GetResponseHeader("transfer-encoding") == null ? false : args.serverResponse.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked") ? true : false;
WriteResponseStatus(args.serverResponse.ProtocolVersion, args.serverResponse.StatusCode, args.serverResponse.StatusDescription, args.clientStreamWriter); WriteResponseStatus(args.serverResponse.ProtocolVersion, args.serverResponse.StatusCode, args.serverResponse.StatusDescription, args.clientStreamWriter);
WriteResponseHeaders(args.clientStreamWriter, args.ResponseHeaders); WriteResponseHeaders(args.clientStreamWriter, args.responseHeaders);
WriteResponseBody(args.responseStream, args.clientStream, isChunked); WriteResponseBody(args.responseStream, args.clientStream, isChunked);
} }
......
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