Commit aabea620 authored by justcoding121's avatar justcoding121

Merge pull request #46 from justcoding121/release

Release
parents 637707ca 39bdfe5d
...@@ -27,7 +27,6 @@ Install by nuget: ...@@ -27,7 +27,6 @@ Install by nuget:
After installing nuget package mark following files to be copied to app directory After installing nuget package mark following files to be copied to app directory
* makecert.exe * makecert.exe
* Titanium_Proxy_Test_Root.cer
Setup HTTP proxy: Setup HTTP proxy:
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// This class wraps Tcp connection to Server
/// </summary>
public class ProxyClient
{
/// <summary>
/// TcpClient used to communicate with server
/// </summary>
internal TcpClient TcpClient { get; set; }
/// <summary>
/// holds the stream to server
/// </summary>
internal Stream ClientStream { get; set; }
/// <summary>
/// Used to read line by line from server
/// </summary>
internal CustomBinaryReader ClientStreamReader { get; set; }
/// <summary>
/// used to write line by line to server
/// </summary>
internal StreamWriter ClientStreamWriter { get; set; }
}
}
...@@ -13,35 +13,48 @@ using Titanium.Web.Proxy.Models; ...@@ -13,35 +13,48 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
public class Client
{
internal TcpClient TcpClient { get; set; }
internal Stream ClientStream { get; set; }
internal CustomBinaryReader ClientStreamReader { get; set; }
internal StreamWriter ClientStreamWriter { get; set; }
public int ClientPort { get; internal set; }
public IPAddress ClientIpAddress { get; internal set; }
} /// <summary>
/// Holds info related to a single proxy session (single request/response sequence)
/// A proxy session is bounded to a single connection from client
/// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy
/// </summary>
public class SessionEventArgs : EventArgs, IDisposable public class SessionEventArgs : EventArgs, IDisposable
{ {
readonly int _bufferSize; readonly int _bufferSize;
/// <summary>
/// Constructor to initialize the proxy
/// </summary>
internal SessionEventArgs(int bufferSize) internal SessionEventArgs(int bufferSize)
{ {
_bufferSize = bufferSize; _bufferSize = bufferSize;
Client = new Client(); Client = new ProxyClient();
ProxySession = new HttpWebSession(); ProxySession = new HttpWebSession();
} }
internal Client Client { get; set; } /// <summary>
/// Holds a reference to server connection
/// </summary>
internal ProxyClient Client { get; set; }
/// <summary>
/// Does this session uses SSL
/// </summary>
public bool IsHttps { get; internal set; } public bool IsHttps { get; internal set; }
/// <summary>
/// A web session corresponding to a single request/response sequence
/// within a proxy connection
/// </summary>
public HttpWebSession ProxySession { get; set; } public HttpWebSession ProxySession { get; set; }
/// <summary>
/// A shortcut to get the request content length
/// </summary>
public int RequestContentLength public int RequestContentLength
{ {
get get
...@@ -50,17 +63,25 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -50,17 +63,25 @@ namespace Titanium.Web.Proxy.EventArguments
} }
} }
/// <summary>
/// A shortcut to get the request Method (GET/POST/PUT etc)
/// </summary>
public string RequestMethod public string RequestMethod
{ {
get { return ProxySession.Request.Method; } get { return ProxySession.Request.Method; }
} }
/// <summary>
/// A shortcut to get the response status code (200 OK, 404 etc)
/// </summary>
public string ResponseStatusCode public string ResponseStatusCode
{ {
get { return ProxySession.Response.ResponseStatusCode; } get { return ProxySession.Response.ResponseStatusCode; }
} }
/// <summary>
/// A shortcut to get the response content type
/// </summary>
public string ResponseContentType public string ResponseContentType
{ {
get get
...@@ -69,30 +90,39 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -69,30 +90,39 @@ namespace Titanium.Web.Proxy.EventArguments
} }
} }
/// <summary>
/// implement any cleanup here
/// </summary>
public void Dispose() public void Dispose()
{ {
} }
/// <summary>
/// Read request body content as bytes[] for current session
/// </summary>
private void ReadRequestBody() private void ReadRequestBody()
{ {
//GET request don't have a request body to read
if ((ProxySession.Request.Method.ToUpper() != "POST" && ProxySession.Request.Method.ToUpper() != "PUT")) if ((ProxySession.Request.Method.ToUpper() != "POST" && ProxySession.Request.Method.ToUpper() != "PUT"))
{ {
throw new BodyNotFoundException("Request don't have a body." + 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."); "Please verify that this request is a Http POST/PUT and request content length is greater than zero before accessing the body.");
} }
//Caching check
if (ProxySession.Request.RequestBody == null) if (ProxySession.Request.RequestBody == null)
{ {
var isChunked = false; var isChunked = false;
string requestContentEncoding = null; string requestContentEncoding = null;
//get compression method (gzip, zlib etc)
if (ProxySession.Request.RequestHeaders.Any(x => x.Name.ToLower() == "content-encoding")) if (ProxySession.Request.RequestHeaders.Any(x => x.Name.ToLower() == "content-encoding"))
{ {
requestContentEncoding = ProxySession.Request.RequestHeaders.First(x => x.Name.ToLower() == "content-encoding").Value; requestContentEncoding = ProxySession.Request.RequestHeaders.First(x => x.Name.ToLower() == "content-encoding").Value;
} }
//check if the request have chunked body (body send chunck by chunck without a fixed length)
if (ProxySession.Request.RequestHeaders.Any(x => x.Name.ToLower() == "transfer-encoding")) if (ProxySession.Request.RequestHeaders.Any(x => x.Name.ToLower() == "transfer-encoding"))
{ {
var transferEncoding = var transferEncoding =
...@@ -103,13 +133,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -103,13 +133,14 @@ namespace Titanium.Web.Proxy.EventArguments
} }
} }
//If not chunked then its easy just read the whole body with the content length mentioned in the request header
if (requestContentEncoding == null && !isChunked) if (requestContentEncoding == null && !isChunked)
ProxySession.Request.RequestBody = this.Client.ClientStreamReader.ReadBytes(RequestContentLength); ProxySession.Request.RequestBody = this.Client.ClientStreamReader.ReadBytes(RequestContentLength);
else else
{ {
using (var requestBodyStream = new MemoryStream()) using (var requestBodyStream = new MemoryStream())
{ {
//For chunked request we need to read data as they arrive, until we reach a chunk end symbol
if (isChunked) if (isChunked)
{ {
while (true) while (true)
...@@ -126,6 +157,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -126,6 +157,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
else else
{ {
//chunk end
this.Client.ClientStreamReader.ReadLine(); this.Client.ClientStreamReader.ReadLine();
break; break;
} }
...@@ -134,6 +166,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -134,6 +166,7 @@ namespace Titanium.Web.Proxy.EventArguments
try try
{ {
//decompress
switch (requestContentEncoding) switch (requestContentEncoding)
{ {
case "gzip": case "gzip":
...@@ -152,20 +185,29 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -152,20 +185,29 @@ namespace Titanium.Web.Proxy.EventArguments
} }
catch catch
{ {
//if decompression fails, just assign the body stream as it it
//Not a safe option
ProxySession.Request.RequestBody = requestBodyStream.ToArray(); ProxySession.Request.RequestBody = requestBodyStream.ToArray();
} }
} }
} }
} }
//Now set the flag to true
//So that next time we can deliver body from cache
ProxySession.Request.RequestBodyRead = true; ProxySession.Request.RequestBodyRead = true;
} }
/// <summary>
/// Read response body as byte[] for current response
/// </summary>
private void ReadResponseBody() private void ReadResponseBody()
{ {
//If not already read (not cached yet)
if (ProxySession.Response.ResponseBody == null) if (ProxySession.Response.ResponseBody == null)
{ {
using (var responseBodyStream = new MemoryStream()) using (var responseBodyStream = new MemoryStream())
{ {
//If chuncked the read chunk by chunk until we hit chunk end symbol
if (ProxySession.Response.IsChunked) if (ProxySession.Response.IsChunked)
{ {
while (true) while (true)
...@@ -182,6 +224,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -182,6 +224,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
else else
{ {
//chuck end
ProxySession.ProxyClient.ServerStreamReader.ReadLine(); ProxySession.ProxyClient.ServerStreamReader.ReadLine();
break; break;
} }
...@@ -189,10 +232,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -189,10 +232,11 @@ namespace Titanium.Web.Proxy.EventArguments
} }
else else
{ {
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response
var buffer = ProxySession.ProxyClient.ServerStreamReader.ReadBytes(ProxySession.Response.ContentLength); var buffer = ProxySession.ProxyClient.ServerStreamReader.ReadBytes(ProxySession.Response.ContentLength);
responseBodyStream.Write(buffer, 0, buffer.Length); responseBodyStream.Write(buffer, 0, buffer.Length);
} }
//decompress
switch (ProxySession.Response.ContentEncoding) switch (ProxySession.Response.ContentEncoding)
{ {
case "gzip": case "gzip":
...@@ -209,19 +253,15 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -209,19 +253,15 @@ namespace Titanium.Web.Proxy.EventArguments
break; break;
} }
} }
//set this to true for caching
ProxySession.Response.ResponseBodyRead = true; ProxySession.Response.ResponseBodyRead = true;
} }
} }
/// <summary>
public Encoding GetRequestBodyEncoding() /// Gets the request body as bytes
{ /// </summary>
if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server."); /// <returns></returns>
return ProxySession.Request.Encoding;
}
public byte[] GetRequestBody() public byte[] GetRequestBody()
{ {
if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
...@@ -229,7 +269,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -229,7 +269,10 @@ namespace Titanium.Web.Proxy.EventArguments
ReadRequestBody(); ReadRequestBody();
return ProxySession.Request.RequestBody; return ProxySession.Request.RequestBody;
} }
/// <summary>
/// Gets the request body as string
/// </summary>
/// <returns></returns>
public string GetRequestBodyAsString() public string GetRequestBodyAsString()
{ {
if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
...@@ -237,13 +280,19 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -237,13 +280,19 @@ namespace Titanium.Web.Proxy.EventArguments
ReadRequestBody(); ReadRequestBody();
//Use the encoding specified in request to decode the byte[] data to string
return ProxySession.Request.RequestBodyString ?? (ProxySession.Request.RequestBodyString = ProxySession.Request.Encoding.GetString(ProxySession.Request.RequestBody)); return ProxySession.Request.RequestBodyString ?? (ProxySession.Request.RequestBodyString = ProxySession.Request.Encoding.GetString(ProxySession.Request.RequestBody));
} }
/// <summary>
/// Sets the request body
/// </summary>
/// <param name="body"></param>
public void SetRequestBody(byte[] body) public void SetRequestBody(byte[] body)
{ {
if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
//syphon out the request body from client before setting the new body
if (!ProxySession.Request.RequestBodyRead) if (!ProxySession.Request.RequestBodyRead)
{ {
ReadRequestBody(); ReadRequestBody();
...@@ -253,10 +302,15 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -253,10 +302,15 @@ namespace Titanium.Web.Proxy.EventArguments
ProxySession.Request.RequestBodyRead = true; ProxySession.Request.RequestBodyRead = true;
} }
/// <summary>
/// Sets the body with the specified string
/// </summary>
/// <param name="body"></param>
public void SetRequestBodyString(string body) public void SetRequestBodyString(string body)
{ {
if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
//syphon out the request body from client before setting the new body
if (!ProxySession.Request.RequestBodyRead) if (!ProxySession.Request.RequestBodyRead)
{ {
ReadRequestBody(); ReadRequestBody();
...@@ -266,13 +320,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -266,13 +320,10 @@ namespace Titanium.Web.Proxy.EventArguments
ProxySession.Request.RequestBodyRead = true; ProxySession.Request.RequestBodyRead = true;
} }
public Encoding GetResponseBodyEncoding() /// <summary>
{ /// Gets the response body as byte array
if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server."); /// </summary>
/// <returns></returns>
return ProxySession.Response.Encoding;
}
public byte[] GetResponseBody() public byte[] GetResponseBody()
{ {
if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
...@@ -281,6 +332,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -281,6 +332,10 @@ namespace Titanium.Web.Proxy.EventArguments
return ProxySession.Response.ResponseBody; return ProxySession.Response.ResponseBody;
} }
/// <summary>
/// Gets the response body as string
/// </summary>
/// <returns></returns>
public string GetResponseBodyAsString() public string GetResponseBodyAsString()
{ {
if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
...@@ -290,10 +345,15 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -290,10 +345,15 @@ namespace Titanium.Web.Proxy.EventArguments
return ProxySession.Response.ResponseBodyString ?? (ProxySession.Response.ResponseBodyString = ProxySession.Response.Encoding.GetString(ProxySession.Response.ResponseBody)); return ProxySession.Response.ResponseBodyString ?? (ProxySession.Response.ResponseBodyString = ProxySession.Response.Encoding.GetString(ProxySession.Response.ResponseBody));
} }
/// <summary>
/// Set the response body bytes
/// </summary>
/// <param name="body"></param>
public void SetResponseBody(byte[] body) public void SetResponseBody(byte[] body)
{ {
if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
//syphon out the response body from server before setting the new body
if (ProxySession.Response.ResponseBody == null) if (ProxySession.Response.ResponseBody == null)
{ {
GetResponseBody(); GetResponseBody();
...@@ -302,10 +362,15 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -302,10 +362,15 @@ namespace Titanium.Web.Proxy.EventArguments
ProxySession.Response.ResponseBody = body; ProxySession.Response.ResponseBody = body;
} }
/// <summary>
/// Replace the response body with the specified string
/// </summary>
/// <param name="body"></param>
public void SetResponseBodyString(string body) public void SetResponseBodyString(string body)
{ {
if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
//syphon out the response body from server before setting the new body
if (ProxySession.Response.ResponseBody == null) if (ProxySession.Response.ResponseBody == null)
{ {
GetResponseBody(); GetResponseBody();
...@@ -316,6 +381,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -316,6 +381,14 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary>
/// Before request is made to server
/// Respond with the specified HTML string to client
/// and ignore the request
/// Marking as obsolete, need to comeup with a generic responder method in future
/// </summary>
/// <param name="html"></param>
// [Obsolete]
public void Ok(string html) public void Ok(string html)
{ {
if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (ProxySession.Request.RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
namespace Titanium.Web.Proxy.Exceptions namespace Titanium.Web.Proxy.Exceptions
{ {
/// <summary>
/// An expception thrown when body is unexpectedly empty
/// </summary>
public class BodyNotFoundException : Exception public class BodyNotFoundException : Exception
{ {
public BodyNotFoundException(string message) public BodyNotFoundException(string message)
......
...@@ -4,14 +4,20 @@ using Titanium.Web.Proxy.Network; ...@@ -4,14 +4,20 @@ using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
/// <summary>
/// Extensions on HttpWebSession object
/// </summary>
public static class HttpWebRequestExtensions public static class HttpWebRequestExtensions
{ {
//Get encoding of the HTTP request
public static Encoding GetEncoding(this HttpWebSession request) public static Encoding GetEncoding(this HttpWebSession request)
{ {
try try
{ {
//return default if not specified
if (request.Request.ContentType == null) return Encoding.GetEncoding("ISO-8859-1"); if (request.Request.ContentType == null) return Encoding.GetEncoding("ISO-8859-1");
//extract the encoding by finding the charset
var contentTypes = request.Request.ContentType.Split(';'); var contentTypes = request.Request.ContentType.Split(';');
foreach (var contentType in contentTypes) foreach (var contentType in contentTypes)
{ {
...@@ -24,9 +30,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -24,9 +30,11 @@ namespace Titanium.Web.Proxy.Extensions
} }
catch catch
{ {
//parsing errors
// ignored // ignored
} }
//return default if not specified
return Encoding.GetEncoding("ISO-8859-1"); return Encoding.GetEncoding("ISO-8859-1");
} }
} }
......
...@@ -4,10 +4,16 @@ using Ionic.Zlib; ...@@ -4,10 +4,16 @@ using Ionic.Zlib;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
/// <summary>
/// A helper to handle compression/decompression (gzip, zlib & deflate)
/// </summary>
public class CompressionHelper public class CompressionHelper
{ {
private const int BufferSize = 8192; /// <summary>
/// compress the given bytes using zlib compression
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static byte[] CompressZlib(byte[] bytes) public static byte[] CompressZlib(byte[] bytes)
{ {
...@@ -22,6 +28,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -22,6 +28,11 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
/// <summary>
/// compress the given bytes using deflate compression
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static byte[] CompressDeflate(byte[] bytes) public static byte[] CompressDeflate(byte[] bytes)
{ {
...@@ -36,6 +47,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -36,6 +47,11 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
/// <summary>
/// compress the given bytes using gzip compression
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static byte[] CompressGzip(byte[] bytes) public static byte[] CompressGzip(byte[] bytes)
{ {
...@@ -50,12 +66,17 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -50,12 +66,17 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
/// <summary>
/// decompression the gzip compressed byte array
/// </summary>
/// <param name="gzip"></param>
/// <returns></returns>
//identify why passing stream instead of bytes returns empty result //identify why passing stream instead of bytes returns empty result
public static byte[] DecompressGzip(byte[] gzip) public static byte[] DecompressGzip(byte[] gzip)
{ {
using (var decompressor = new System.IO.Compression.GZipStream(new MemoryStream(gzip), System.IO.Compression.CompressionMode.Decompress)) using (var decompressor = new System.IO.Compression.GZipStream(new MemoryStream(gzip), System.IO.Compression.CompressionMode.Decompress))
{ {
var buffer = new byte[BufferSize]; var buffer = new byte[ProxyServer.BUFFER_SIZE];
using (var output = new MemoryStream()) using (var output = new MemoryStream())
{ {
...@@ -69,11 +90,16 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -69,11 +90,16 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
/// <summary>
/// decompress the deflate byte stream
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static byte[] DecompressDeflate(Stream input) public static byte[] DecompressDeflate(Stream input)
{ {
using (var decompressor = new DeflateStream(input, CompressionMode.Decompress)) using (var decompressor = new DeflateStream(input, CompressionMode.Decompress))
{ {
var buffer = new byte[BufferSize]; var buffer = new byte[ProxyServer.BUFFER_SIZE];
using (var output = new MemoryStream()) using (var output = new MemoryStream())
{ {
...@@ -87,11 +113,16 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -87,11 +113,16 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
/// <summary>
/// decompress the zlib byte stream
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static byte[] DecompressZlib(Stream input) public static byte[] DecompressZlib(Stream input)
{ {
using (var decompressor = new ZlibStream(input, CompressionMode.Decompress)) using (var decompressor = new ZlibStream(input, CompressionMode.Decompress))
{ {
var buffer = new byte[BufferSize]; var buffer = new byte[ProxyServer.BUFFER_SIZE];
using (var output = new MemoryStream()) using (var output = new MemoryStream())
{ {
......
...@@ -5,6 +5,11 @@ using System.Text; ...@@ -5,6 +5,11 @@ using System.Text;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
/// <summary>
/// A custom binary reader that would allo us to read string line by line
/// using the specified encoding
/// as well as to read bytes as required
/// </summary>
public class CustomBinaryReader : BinaryReader public class CustomBinaryReader : BinaryReader
{ {
internal CustomBinaryReader(Stream stream, Encoding encoding) internal CustomBinaryReader(Stream stream, Encoding encoding)
...@@ -12,6 +17,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -12,6 +17,10 @@ namespace Titanium.Web.Proxy.Helpers
{ {
} }
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
internal string ReadLine() internal string ReadLine()
{ {
var readBuffer = new StringBuilder(); var readBuffer = new StringBuilder();
...@@ -43,6 +52,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -43,6 +52,10 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
/// <summary>
/// Read until the last new line
/// </summary>
/// <returns></returns>
internal List<string> ReadAllLines() internal List<string> ReadAllLines()
{ {
string tmpLine; string tmpLine;
......
...@@ -3,6 +3,9 @@ using System.IO; ...@@ -3,6 +3,9 @@ using System.IO;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
/// <summary>
/// A helper class to set proxy settings for firefox
/// </summary>
public class FireFoxHelper public class FireFoxHelper
{ {
public static void AddFirefox() public static void AddFirefox()
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
{ {
/// <summary>
/// Http Header object used by proxy
/// </summary>
public class HttpHeader public class HttpHeader
{ {
public HttpHeader(string name, string value) public HttpHeader(string name, string value)
...@@ -15,6 +18,10 @@ namespace Titanium.Web.Proxy.Models ...@@ -15,6 +18,10 @@ namespace Titanium.Web.Proxy.Models
public string Name { get; set; } public string Name { get; set; }
public string Value { get; set; } public string Value { get; set; }
/// <summary>
/// Returns header as a valid header string
/// </summary>
/// <returns></returns>
public override string ToString() public override string ToString()
{ {
return string.Format("{0}: {1}", Name, Value); return string.Format("{0}: {1}", Name, Value);
......
...@@ -21,7 +21,7 @@ namespace Titanium.Web.Proxy ...@@ -21,7 +21,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public partial class ProxyServer public partial class ProxyServer
{ {
private static readonly int BUFFER_SIZE = 8192;
private static readonly char[] SemiSplit = { ';' }; private static readonly char[] SemiSplit = { ';' };
private static readonly string[] ColonSpaceSplit = { ": " }; private static readonly string[] ColonSpaceSplit = { ": " };
...@@ -34,17 +34,16 @@ namespace Titanium.Web.Proxy ...@@ -34,17 +34,16 @@ namespace Titanium.Web.Proxy
private static readonly byte[] ChunkEnd = private static readonly byte[] ChunkEnd =
Encoding.ASCII.GetBytes(0.ToString("x2") + Environment.NewLine + Environment.NewLine); Encoding.ASCII.GetBytes(0.ToString("x2") + Environment.NewLine + Environment.NewLine);
public static readonly int BUFFER_SIZE = 8192;
#if NET45 #if NET45
internal static SslProtocols SupportedProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Ssl3; internal static SslProtocols SupportedProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Ssl3;
#else #else
public static SslProtocols SupportedProtocols = SslProtocols.Tls | SslProtocols.Ssl3; internal static SslProtocols SupportedProtocols = SslProtocols.Tls | SslProtocols.Ssl3;
#endif #endif
static ProxyServer() static ProxyServer()
{ {
CertManager = new CertificateManager("Titanium",
"Titanium Root Certificate Authority");
ProxyEndPoints = new List<ProxyEndPoint>(); ProxyEndPoints = new List<ProxyEndPoint>();
Initialize(); Initialize();
...@@ -55,6 +54,7 @@ namespace Titanium.Web.Proxy ...@@ -55,6 +54,7 @@ namespace Titanium.Web.Proxy
private static bool certTrusted { get; set; } private static bool certTrusted { get; set; }
private static bool proxyRunning { get; set; } private static bool proxyRunning { get; set; }
public static string RootCertificateIssuerName { get; set; }
public static string RootCertificateName { get; set; } public static string RootCertificateName { get; set; }
public static event EventHandler<SessionEventArgs> BeforeRequest; public static event EventHandler<SessionEventArgs> BeforeRequest;
...@@ -123,7 +123,6 @@ namespace Titanium.Web.Proxy ...@@ -123,7 +123,6 @@ namespace Titanium.Web.Proxy
//clear any settings previously added //clear any settings previously added
ProxyEndPoints.OfType<ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpsProxy = false); ProxyEndPoints.OfType<ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpsProxy = false);
RootCertificateName = RootCertificateName ?? "Titanium_Proxy_Test_Root";
//If certificate was trusted by the machine //If certificate was trusted by the machine
if (certTrusted) if (certTrusted)
...@@ -156,6 +155,12 @@ namespace Titanium.Web.Proxy ...@@ -156,6 +155,12 @@ namespace Titanium.Web.Proxy
if (proxyRunning) if (proxyRunning)
throw new Exception("Proxy is already running."); throw new Exception("Proxy is already running.");
RootCertificateName = RootCertificateName ?? "Titanium Root Certificate Authority";
RootCertificateIssuerName = RootCertificateIssuerName ?? "Titanium";
CertManager = new CertificateManager(RootCertificateIssuerName,
RootCertificateName);
EnableSsl = ProxyEndPoints.Any(x => x.EnableSsl); EnableSsl = ProxyEndPoints.Any(x => x.EnableSsl);
if (EnableSsl) if (EnableSsl)
......
...@@ -239,8 +239,6 @@ namespace Titanium.Web.Proxy ...@@ -239,8 +239,6 @@ namespace Titanium.Web.Proxy
args.Client.ClientStreamWriter = clientStreamWriter; args.Client.ClientStreamWriter = clientStreamWriter;
args.ProxySession.Request.Hostname = args.ProxySession.Request.RequestUri.Host; args.ProxySession.Request.Hostname = args.ProxySession.Request.RequestUri.Host;
args.ProxySession.Request.Url = args.ProxySession.Request.RequestUri.OriginalString; args.ProxySession.Request.Url = args.ProxySession.Request.RequestUri.OriginalString;
args.Client.ClientPort = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
args.Client.ClientIpAddress = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
//If requested interception //If requested interception
......
...@@ -80,6 +80,7 @@ ...@@ -80,6 +80,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="EventArguments\ProxyClient.cs" />
<Compile Include="Exceptions\BodyNotFoundException.cs" /> <Compile Include="Exceptions\BodyNotFoundException.cs" />
<Compile Include="Extensions\HttpWebResponseExtensions.cs" /> <Compile Include="Extensions\HttpWebResponseExtensions.cs" />
<Compile Include="Extensions\HttpWebRequestExtensions.cs" /> <Compile Include="Extensions\HttpWebRequestExtensions.cs" />
...@@ -105,9 +106,6 @@ ...@@ -105,9 +106,6 @@
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="Titanium_Proxy_Test_Root.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="makecert.exe"> <None Include="makecert.exe">
......
...@@ -21,6 +21,5 @@ ...@@ -21,6 +21,5 @@
<file src="bin\$configuration$\Titanium.Web.Proxy.dll" target="lib\net40" /> <file src="bin\$configuration$\Titanium.Web.Proxy.dll" target="lib\net40" />
<file src="bin\$configuration$-Net45\Titanium.Web.Proxy.dll" target="lib\net45" /> <file src="bin\$configuration$-Net45\Titanium.Web.Proxy.dll" target="lib\net45" />
<file src="bin\$configuration$\makecert.exe" target="content" /> <file src="bin\$configuration$\makecert.exe" target="content" />
<file src="bin\$configuration$\Titanium_Proxy_Test_Root.cer" target="content" />
</files> </files>
</package> </package>
\ No newline at end of file
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