Commit 27fc293a authored by titanium007's avatar titanium007

Merge remote-tracking branch 'refs/remotes/origin/master' into breaking-change

# Conflicts:
#	README.md
#	Titanium.Web.Proxy.Test/App.config
#	Titanium.Web.Proxy.Test/Properties/AssemblyInfo.cs
#	Titanium.Web.Proxy.sln
#	Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
#	Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
#	Titanium.Web.Proxy/Helpers/Tcp.cs
#	Titanium.Web.Proxy/Properties/AssemblyInfo.cs
#	Titanium.Web.Proxy/ProxyServer.cs
#	Titanium.Web.Proxy/RequestHandler.cs
#	Titanium.Web.Proxy/ResponseHandler.cs
#	Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
#	Titanium.Web.Proxy/packages.config
parent 4c3121ed
param (
[string]$Action="default",
[hashtable]$properties=@{},
[switch]$Help
)
$Here = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
Import-Module "$Here\Common"
Install-Chocolatey
Install-Psake
$psakeDirectory = (Resolve-Path $env:ChocolateyInstall\lib\Psake*)
Import-Module (Join-Path $psakeDirectory "tools\Psake.psm1")
if($Help)
{
try
{
Write-Host "Available build tasks:"
psake -nologo -docs | Out-Host -paging
}
catch {}
return
}
Invoke-Psake -buildFile "$Here\Default.ps1" -parameters $properties -tasklist $Action
\ No newline at end of file
###
### Common Profile functions for all users
###
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$SolutionRoot = Split-Path -Parent $ScriptPath
$ToolsPath = Join-Path -Path $SolutionRoot -ChildPath "lib"
Export-ModuleMember -Variable @('ScriptPath', 'SolutionRoot', 'ToolsPath')
function Install-Chocolatey()
{
if(-not $env:ChocolateyInstall -or -not (Test-Path "$env:ChocolateyInstall"))
{
Write-Output "Chocolatey Not Found, Installing..."
iex ((new-object net.webclient).DownloadString('http://chocolatey.org/install.ps1'))
}
}
function Install-Psake()
{
if(!(Test-Path $env:ChocolateyInstall\lib\Psake*))
{
choco install psake -y
}
}
Export-ModuleMember -Function *-*
\ No newline at end of file
$PSake.use_exit_on_error = $true
$Here = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$SolutionRoot = (Split-Path -parent $Here)
$ProjectName = "Titanium.Web.Proxy"
$SolutionFile = "$SolutionRoot\$ProjectName.sln"
## This comes from the build server iteration
if(!$BuildNumber) { $BuildNumber = $env:APPVEYOR_BUILD_NUMBER }
if(!$BuildNumber) { $BuildNumber = "1"}
## This comes from the Hg commit hash used to build
if(!$CommitHash) { $CommitHash = $env:APPVEYOR_REPO_COMMIT }
if(!$CommitHash) { $CommitHash = "local-build" }
## The build configuration, i.e. Debug/Release
if(!$Configuration) { $Configuration = $env:Configuration }
if(!$Configuration) { $Configuration = "Release" }
if(!$Version) { $Version = $env:APPVEYOR_BUILD_VERSION }
if(!$Version) { $Version = "1.0.$BuildNumber" }
Import-Module "$Here\Common" -DisableNameChecking
$NuGet = Join-Path $SolutionRoot ".nuget\nuget.exe"
$MSBuild ="${env:ProgramFiles(x86)}\MSBuild\12.0\Bin\msbuild.exe"
FormatTaskName (("-"*25) + "[{0}]" + ("-"*25))
Task default -depends Clean, Build, Package
Task Build -depends Restore-Packages {
exec { . $MSBuild $SolutionFile /t:Build /v:normal /p:Configuration=$Configuration }
exec { . $MSBuild $SolutionFile /t:Build /v:normal /p:Configuration=$Configuration-Net45 }
}
Task Package -depends Build {
exec { . $NuGet pack "$SolutionRoot\Titanium.Web.Proxy\Titanium.Web.Proxy.nuspec" -Properties Configuration=$Configuration -OutputDirectory "$SolutionRoot" -Version "$Version" }
}
Task Clean -depends Install-BuildTools {
Remove-Item -Path "$SolutionRoot\packages\*" -Exclude repositories.config -Recurse -Force
Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { Remove-Item $_.fullname -Force -Recurse }
exec { . $MSBuild $SolutionFile /t:Clean /v:quiet }
}
Task Restore-Packages {
exec { . $NuGet restore $SolutionFile }
}
Task Install-MSBuild {
if(!(Test-Path "${env:ProgramFiles(x86)}\MSBuild\12.0\Bin\msbuild.exe"))
{
cinst microsoft-build-tools -y
}
}
Task Install-BuildTools -depends Install-MSBuild
...@@ -2,7 +2,7 @@ Titanium ...@@ -2,7 +2,7 @@ Titanium
======== ========
A light weight http(s) proxy server written in C# A light weight http(s) proxy server written in C#
[![titanium MyGet Build Status](https://www.myget.org/BuildSource/Badge/titanium?identifier=36bd545d-87aa-4c0c-ae98-6de9a078b016)](https://www.myget.org/) ![Build Status](https://ci.appveyor.com/api/projects/status/rvlxv8xgj0m7lkr4?svg=true)
Kindly report only issues/bugs here . For programming help or questions use [StackOverflow](http://stackoverflow.com/questions/tagged/titanium-web-proxy) with the tag Titanium-Web-Proxy. Kindly report only issues/bugs here . For programming help or questions use [StackOverflow](http://stackoverflow.com/questions/tagged/titanium-web-proxy) with the tag Titanium-Web-Proxy.
...@@ -11,10 +11,9 @@ Kindly report only issues/bugs here . For programming help or questions use [Sta ...@@ -11,10 +11,9 @@ Kindly report only issues/bugs here . For programming help or questions use [Sta
Features Features
======== ========
* Supports Http(s) and all features of HTTP 1.1 * Supports Http(s) and most features of HTTP 1.1
* Supports relaying of WebSockets * Supports relaying of WebSockets
* Supports script injection * Supports script injection
* Async using HttpWebRequest class for better performance
Usage Usage
===== =====
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Http.Tests
{
class Program
{
static void Main(string[] args)
{
var t = Task.Factory.StartNew(Test);
t.Wait();
Console.Read();
}
public static async void Test()
{
var s = new HttpClient
{
Method = "GET",
Uri = new Uri("https://google.com"),
Version = "HTTP/1.1"
};
s.RequestHeaders.Add(new HttpHeader("Host", s.Uri.Host));
await s.SendRequest();
await s.ReceiveResponse();
}
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Titanium.Web.Http.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Titanium.Web.Http.Tests")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ef2b516c-1cc2-4688-af05-0758b40bb9df")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{95550A47-B2D2-43C4-8E79-17BDF09B797F}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Titanium.Web.Http.Tests</RootNamespace>
<AssemblyName>Titanium.Web.Http.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Titanium.Web.Http\Titanium.Web.Http.csproj">
<Project>{51f8273a-39e4-4c9f-9972-bc78f8b3b32e}</Project>
<Name>Titanium.Web.Http</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.8" targetFramework="net40" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net40" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net40" />
</packages>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Instrumentation;
using System.Net.Security;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Http
{
public class HttpClient
{
const string Space = " ";
public string Method { get; set; }
public Uri Uri { get; set; }
public string Version { get; set; }
public List<HttpHeader> RequestHeaders { get; set; }
public bool IsSecure
{
get { return this.Uri.Scheme == Uri.UriSchemeHttps; }
}
public TcpClient Client { get; set; }
public Stream Stream { get; set; }
public HttpClient()
{
RequestHeaders = new List<HttpHeader>();
ResponseHeaders = new List<HttpHeader>();
}
public async Task<Stream> GetStream()
{
if (Stream == null)
{
Client = new TcpClient(Uri.Host, Uri.Port);
Stream = Client.GetStream();
if (IsSecure)
{
SslStream sslStream = null;
try
{
sslStream = new SslStream(Stream);
await sslStream.AuthenticateAsClientAsync(Uri.Host);
Stream = sslStream;
}
catch
{
if (sslStream != null)
sslStream.Dispose();
throw;
}
}
}
return Stream;
}
public async Task SendRequest()
{
await GetStream();
var requestLines = new StringBuilder();
requestLines.Append(string.Join(Space, Method, Uri.AbsolutePath, Version));
requestLines.AppendLine();
foreach (var header in RequestHeaders)
{
requestLines.Append(header.Name + ':' + header.Value);
requestLines.AppendLine();
requestLines.AppendLine();
}
var request = requestLines.ToString();
var requestBytes = Encoding.ASCII.GetBytes(request);
await Stream.WriteAsync(requestBytes, 0, requestBytes.Length);
await Stream.FlushAsync();
}
public string Status { get; set; }
public List<HttpHeader> ResponseHeaders { get; set; }
public async Task ReceiveResponse()
{
var responseLines = await HttpStreamReader.ReadAllLines(Stream);
var responseStatus = responseLines[0].Split(' ');
Status = responseStatus[1] + Space + responseStatus[2];
for (int i = 1; i < responseLines.Count; i++)
{
var header = responseLines[i].Split(':');
ResponseHeaders.Add(new HttpHeader(header[0], header[1]));
}
}
public void Abort()
{
throw new NotImplementedException();
}
public int ContentLength { get; set; }
public bool SendChunked { get; set; }
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Titanium.Web.Http")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Titanium.Web.Http")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("e951d607-dfa6-43b2-ad9a-8dcdea29a0f1")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Titanium.Web.Http</RootNamespace>
<AssemblyName>Titanium.Web.Http</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CustomBinaryReader.cs" />
<Compile Include="HttpHeader.cs" />
<Compile Include="HttpClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.8" targetFramework="net40" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net40" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net40" />
</packages>
\ No newline at end of file
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" /> <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" /> <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
......
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
...@@ -10,7 +10,7 @@ using System.Runtime.InteropServices; ...@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Demo")] [assembly: AssemblyProduct("Demo")]
[assembly: AssemblyCopyright("Copyright ©2013 Telerik")] [assembly: AssemblyCopyright("Copyright ©2013 Telerik")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
...@@ -33,7 +33,7 @@ using System.Runtime.InteropServices; ...@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.1")]
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.1")]
[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.1")]
\ No newline at end of file
...@@ -10,9 +10,7 @@ ...@@ -10,9 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Titanium.Web.Proxy.Test</RootNamespace> <RootNamespace>Titanium.Web.Proxy.Test</RootNamespace>
<AssemblyName>Titanium.Web.Proxy.Test</AssemblyName> <AssemblyName>Titanium.Web.Proxy.Test</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
...@@ -22,6 +20,7 @@ ...@@ -22,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
...@@ -30,10 +29,31 @@ ...@@ -30,10 +29,31 @@
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject /> <StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Net45|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug-Net45\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release-Net45|AnyCPU'">
<OutputPath>bin\Release-Net45\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.ComponentModel.DataAnnotations" />
......
...@@ -16,66 +16,36 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6FD3B8 ...@@ -16,66 +16,36 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6FD3B8
.nuget\NuGet.targets = .nuget\NuGet.targets .nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HttpClient", "HttpClient", "{867333C8-3C44-41F4-913C-63802970CF82}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Http", "Titanium.Web.Http\Titanium.Web.Http.csproj", "{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Http.Tests", "Titanium.Web.Http.Tests\Titanium.Web.Http.Tests.csproj", "{95550A47-B2D2-43C4-8E79-17BDF09B797F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64 Debug-Net45|Any CPU = Debug-Net45|Any CPU
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64 Release-Net45|Any CPU = Release-Net45|Any CPU
Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.Build.0 = Debug|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|x64.ActiveCfg = Debug|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug-Net45|Any CPU.ActiveCfg = Debug-Net45|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|x86.ActiveCfg = Debug|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug-Net45|Any CPU.Build.0 = Debug-Net45|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.ActiveCfg = Release|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.Build.0 = Release|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.Build.0 = Release|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|x64.ActiveCfg = Release|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Release-Net45|Any CPU.ActiveCfg = Release-Net45|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|x86.ActiveCfg = Release|Any CPU {F3B7E553-1904-4E80-BDC7-212342B5C952}.Release-Net45|Any CPU.Build.0 = Release-Net45|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|x64.ActiveCfg = Debug|x64 {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug-Net45|Any CPU.ActiveCfg = Debug-Net45|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|x64.Build.0 = Debug|x64 {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug-Net45|Any CPU.Build.0 = Debug-Net45|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|x86.ActiveCfg = Debug|x86
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|x86.Build.0 = Debug|x86
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|Any CPU.Build.0 = Release|Any CPU {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|Any CPU.Build.0 = Release|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|x64.ActiveCfg = Release|x64 {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release-Net45|Any CPU.ActiveCfg = Release-Net45|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|x64.Build.0 = Release|x64 {8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release-Net45|Any CPU.Build.0 = Release-Net45|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|x86.ActiveCfg = Release|x86
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|x86.Build.0 = Release|x86
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Debug|x64.ActiveCfg = Debug|Any CPU
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Debug|x86.ActiveCfg = Debug|Any CPU
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Release|Any CPU.Build.0 = Release|Any CPU
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Release|x64.ActiveCfg = Release|Any CPU
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E}.Release|x86.ActiveCfg = Release|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Debug|x64.ActiveCfg = Debug|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Debug|x86.ActiveCfg = Debug|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Release|Any CPU.Build.0 = Release|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Release|x64.ActiveCfg = Release|Any CPU
{95550A47-B2D2-43C4-8E79-17BDF09B797F}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{F3B7E553-1904-4E80-BDC7-212342B5C952} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B} {F3B7E553-1904-4E80-BDC7-212342B5C952} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B}
{51F8273A-39E4-4C9F-9972-BC78F8B3B32E} = {867333C8-3C44-41F4-913C-63802970CF82}
{95550A47-B2D2-43C4-8E79-17BDF09B797F} = {867333C8-3C44-41F4-913C-63802970CF82}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35 EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
......
...@@ -6,10 +6,10 @@ using System.Linq; ...@@ -6,10 +6,10 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using Titanium.Web.Http;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
...@@ -24,6 +24,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -24,6 +24,7 @@ namespace Titanium.Web.Proxy.EventArguments
internal TcpClient Client { get; set; } internal TcpClient Client { get; set; }
internal Stream ClientStream { get; set; } internal Stream ClientStream { get; set; }
internal CustomBinaryReader ClientStreamReader { get; set; }
internal StreamWriter ClientStreamWriter { get; set; } internal StreamWriter ClientStreamWriter { get; set; }
...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy.EventArguments
internal bool RequestBodyRead { get; set; } internal bool RequestBodyRead { get; set; }
public List<HttpHeader> RequestHeaders { get; internal set; } public List<HttpHeader> RequestHeaders { get; internal set; }
internal bool RequestLocked { get; set; } internal bool RequestLocked { get; set; }
internal HttpClient ProxyRequest { get; set; } internal HttpWebClient ProxySession { get; set; }
internal Encoding ResponseEncoding { get; set; } internal Encoding ResponseEncoding { get; set; }
internal Stream ResponseStream { get; set; } internal Stream ResponseStream { get; set; }
...@@ -52,7 +53,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -52,7 +53,6 @@ namespace Titanium.Web.Proxy.EventArguments
internal bool ResponseBodyRead { get; set; } internal bool ResponseBodyRead { get; set; }
public List<HttpHeader> ResponseHeaders { get; internal set; } public List<HttpHeader> ResponseHeaders { get; internal set; }
internal bool ResponseLocked { get; set; } internal bool ResponseLocked { get; set; }
// internal HttpWebResponse ProxyRequest { get; set; }
public int RequestContentLength public int RequestContentLength
{ {
...@@ -69,13 +69,13 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -69,13 +69,13 @@ namespace Titanium.Web.Proxy.EventArguments
public string RequestMethod public string RequestMethod
{ {
get { return ProxyRequest.Method; } get { return ProxySession.Method; }
} }
public HttpStatusCode ResponseStatusCode public string ResponseStatusCode
{ {
get { return ProxyRequest.StatusCode; } get { return ProxySession.ResponseStatusCode; }
} }
public string ResponseContentType public string ResponseContentType
...@@ -90,19 +90,19 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -90,19 +90,19 @@ namespace Titanium.Web.Proxy.EventArguments
public void Dispose() public void Dispose()
{ {
if (ProxyRequest != null) //if (ProxyRequest != null)
ProxyRequest.Abort(); // ProxyRequest.Abort();
if (ResponseStream != null) if (ResponseStream != null)
ResponseStream.Dispose(); ResponseStream.Dispose();
if (ProxyRequest != null) //if (ServerResponse != null)
ProxyRequest.Close(); // ServerResponse.Close();
} }
private void ReadRequestBody() private void ReadRequestBody()
{ {
if ((ProxyRequest.Method.ToUpper() != "POST" && ProxyRequest.Method.ToUpper() != "PUT")) if ((ProxySession.Method.ToUpper() != "POST" && ProxySession.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.");
...@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.EventArguments
RequestBody = CompressionHelper.DecompressDeflate(requestBodyStream); RequestBody = CompressionHelper.DecompressDeflate(requestBodyStream);
break; break;
case "zlib": case "zlib":
RequestBody = CompressionHelper.DecompressGzip(requestBodyStream); RequestBody = CompressionHelper.DecompressZlib(requestBodyStream);
break; break;
default: default:
RequestBody = requestBodyStream.ToArray(); RequestBody = requestBodyStream.ToArray();
...@@ -189,7 +189,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -189,7 +189,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
if (ResponseBody == null) if (ResponseBody == null)
{ {
switch (ProxyRequest.ContentEncoding) switch ( ProxySession.ResponseContentEncoding)
{ {
case "gzip": case "gzip":
ResponseBody = CompressionHelper.DecompressGzip(ResponseStream); ResponseBody = CompressionHelper.DecompressGzip(ResponseStream);
...@@ -265,7 +265,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -265,7 +265,7 @@ namespace Titanium.Web.Proxy.EventArguments
public void SetRequestBodyString(string body) public void SetRequestBodyString(string body)
{ {
if (RequestLocked) throw new Exception("Youcannot 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 (!RequestBodyRead) if (!RequestBodyRead)
{ {
......
using System.Net; using System.Net;
using System.Text; using System.Text;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
public static class HttpWebRequestExtensions public static class HttpWebRequestExtensions
{ {
public static Encoding GetEncoding(this HttpWebRequest request) public static Encoding GetEncoding(this HttpWebClient request)
{ {
try try
{ {
if (request.ContentType == null) return Encoding.GetEncoding("ISO-8859-1"); if (request.RequestContentType == null) return Encoding.GetEncoding("ISO-8859-1");
var contentTypes = request.ContentType.Split(';'); var contentTypes = request.RequestContentType.Split(';');
foreach (var contentType in contentTypes) foreach (var contentType in contentTypes)
{ {
var encodingSplit = contentType.Split('='); var encodingSplit = contentType.Split('=');
......
using System.Net; using System.Net;
using System.Text; using System.Text;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
public static class HttpWebResponseExtensions public static class HttpWebResponseExtensions
{ {
public static Encoding GetEncoding(this HttpWebResponse response) public static Encoding GetResponseEncoding(this HttpWebClient response)
{ {
if (string.IsNullOrEmpty(response.CharacterSet)) return Encoding.GetEncoding("ISO-8859-1"); if (string.IsNullOrEmpty(response.ResponseCharacterSet)) return Encoding.GetEncoding("ISO-8859-1");
return Encoding.GetEncoding(response.CharacterSet.Replace(@"""",string.Empty)); return Encoding.GetEncoding(response.ResponseCharacterSet.Replace(@"""",string.Empty));
} }
} }
} }
\ No newline at end of file
...@@ -2,28 +2,39 @@ ...@@ -2,28 +2,39 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Http namespace Titanium.Web.Proxy.Helpers
{ {
public class HttpStreamReader public class CustomBinaryReader : BinaryReader
{ {
internal CustomBinaryReader(Stream stream, Encoding encoding)
: base(stream, encoding)
{
}
public async static Task<string> ReadLine(Stream stream) internal string ReadLine()
{ {
var buf = new byte[2];
var readBuffer = new StringBuilder(); var readBuffer = new StringBuilder();
try try
{ {
while ((await stream.ReadAsync(buf, 0, 2)) > 0) var lastChar = default(char);
var buffer = new char[1];
while (Read(buffer, 0, 1) > 0)
{ {
var charRead = System.Text.Encoding.ASCII.GetString(buf); if (lastChar == '\r' && buffer[0] == '\n')
if (charRead == Environment.NewLine) {
return readBuffer.Remove(readBuffer.Length - 1, 1).ToString();
}
if (buffer[0] == '\0')
{ {
return readBuffer.ToString(); return readBuffer.ToString();
} }
readBuffer.Append(charRead); readBuffer.Append(buffer);
lastChar = buffer[0];
} }
return readBuffer.ToString(); return readBuffer.ToString();
} }
catch (IOException) catch (IOException)
...@@ -32,12 +43,11 @@ namespace Titanium.Web.Http ...@@ -32,12 +43,11 @@ namespace Titanium.Web.Http
} }
} }
internal List<string> ReadAllLines()
public async static Task<List<string>> ReadAllLines(Stream stream)
{ {
string tmpLine; string tmpLine;
var requestLines = new List<string>(); var requestLines = new List<string>();
while (!string.IsNullOrEmpty(tmpLine = await ReadLine(stream))) while (!string.IsNullOrEmpty(tmpLine = ReadLine()))
{ {
requestLines.Add(tmpLine); requestLines.Add(tmpLine);
} }
......
...@@ -6,9 +6,8 @@ using System.Net.Security; ...@@ -6,9 +6,8 @@ using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Http;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Http
{
//public class HttpStreamReader
//{
// public static async Task<string> ReadLine(Stream stream)
// {
// var readBuffer = new StringBuilder();
// try
// {
// var lastChar = default(char);
// var buffer = new byte[1];
// while ((await stream.ReadAsync(buffer, 0, 1)) > 0)
// {
// if (lastChar == '\r' && buffer[0] == '\n')
// {
// return readBuffer.Remove(readBuffer.Length - 1, 1).ToString();
// }
// if (buffer[0] == '\0')
// {
// return readBuffer.ToString();
// }
// readBuffer.Append(Encoding.ASCII.GetString(buffer));
// lastChar = Encoding.ASCII.GetChars(buffer)[0];
// }
// return readBuffer.ToString();
// }
// catch (IOException)
// {
// return readBuffer.ToString();
// }
// }
// public static async Task<List<string>> ReadAllLines(Stream stream)
// {
// string tmpLine;
// var requestLines = new List<string>();
// while (!string.IsNullOrEmpty(tmpLine = await ReadLine(stream)))
// {
// requestLines.Add(tmpLine);
// }
// return requestLines;
// }
//}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http
{
public class HttpWebClient
{
private const string Space = " ";
public string Method { get; set; }
public Uri RequestUri { get; set; }
public string Version { get; set; }
public List<HttpHeader> RequestHeaders { get; set; }
public bool IsSecure
{
get
{
return this.RequestUri.Scheme == Uri.UriSchemeHttps;
}
}
public TcpClient Client { get; set; }
public string RequestStatus { get; set; }
public List<HttpHeader> ResponseHeaders { get; set; }
public int RequestContentLength { get; set; }
public bool RequestSendChunked { get; set; }
public HttpWebClient()
{
this.RequestHeaders = new List<HttpHeader>();
this.ResponseHeaders = new List<HttpHeader>();
}
public CustomBinaryReader ServerStreamReader { get; set; }
public async Task SendRequest()
{
Stream stream = Client.GetStream();
StringBuilder requestLines = new StringBuilder();
requestLines.AppendLine(string.Join(" ", new string[3]
{
this.Method,
this.RequestUri.AbsolutePath,
this.Version
}));
foreach (HttpHeader httpHeader in this.RequestHeaders)
{
requestLines.AppendLine(httpHeader.Name + ':' + httpHeader.Value);
}
requestLines.AppendLine();
requestLines.AppendLine();
string request = requestLines.ToString();
byte[] requestBytes = Encoding.ASCII.GetBytes(request);
await AsyncExtensions.WriteAsync((Stream)stream, requestBytes, 0, requestBytes.Length);
await AsyncExtensions.FlushAsync((Stream)stream);
}
public void ReceiveResponse()
{
Stream stream = Client.GetStream();
ServerStreamReader = new CustomBinaryReader(stream, Encoding.ASCII);
var httpResult = ServerStreamReader.ReadLine().Split(' ');
var httpVersion = httpResult[0];
Version version;
if (httpVersion == "HTTP/1.1")
{
version = new Version(1, 1);
}
else
{
version = new Version(1, 0);
}
this.ResponseProtocolVersion = version;
this.ResponseStatusCode = httpResult[1];
string status = httpResult[2];
for (int i = 3; i < httpResult.Length; i++)
{
status = status + Space + httpResult[i];
}
this.ResponseStatusDescription = status;
List<string> responseLines = ServerStreamReader.ReadAllLines();
for (int index = 0; index < responseLines.Count; ++index)
{
string[] strArray = responseLines[index].Split(':');
this.ResponseHeaders.Add(new HttpHeader(strArray[0], strArray[1]));
}
}
public string RequestContentType { get; set; }
public bool RequestKeepAlive { get; set; }
public string RequestHost { get; set; }
public string ResponseCharacterSet { get; set; }
public string ResponseContentEncoding { get; set; }
public System.Version ResponseProtocolVersion { get; set; }
public string ResponseStatusCode { get; set; }
public string ResponseStatusDescription { get; set; }
public bool ResponseKeepAlive { get; set; }
public string ResponseContentType { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.IO;
using System.Net.Security;
namespace Titanium.Web.Proxy.Http
{
internal class TcpConnectionManager
{
static ConcurrentDictionary<string, ConcurrentStack<TcpClient>> ConnectionCache = new ConcurrentDictionary<string, ConcurrentStack<TcpClient>>();
public static async Task<TcpClient> GetClient(string Hostname, int port, bool IsSecure)
{
var key = string.Concat(Hostname, ":", port, ":", IsSecure);
ConcurrentStack<TcpClient> connections;
if (!ConnectionCache.TryGetValue(key, out connections))
{
return await CreateClient(Hostname, port, IsSecure);
}
TcpClient client;
if (!connections.TryPop(out client))
{
return await CreateClient(Hostname, port, IsSecure);
}
return client;
}
private static async Task<TcpClient> CreateClient(string Hostname, int port, bool IsSecure)
{
var client = new TcpClient(Hostname, port);
var stream = (Stream)client.GetStream();
if (IsSecure)
{
var sslStream = (SslStream)null;
try
{
sslStream = new SslStream(stream);
await AsyncPlatformExtensions.AuthenticateAsClientAsync(sslStream, Hostname);
stream = (Stream)sslStream;
}
catch
{
if (sslStream != null)
sslStream.Dispose();
throw;
}
}
return client;
}
public static void AddClient(string Hostname, int port, bool IsSecure, TcpClient Client)
{
var key = string.Concat(Hostname, ":", port, ":", IsSecure);
ConcurrentStack<TcpClient> connections;
if (!ConnectionCache.TryGetValue(key, out connections))
{
connections = new ConcurrentStack<TcpClient>();
connections.Push(Client);
ConnectionCache.TryAdd(key, connections);
}
connections.Push(Client);
}
}
}
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Titanium.Web.Http namespace Titanium.Web.Proxy.Models
{ {
public class HttpHeader public class HttpHeader
{ {
public HttpHeader(string name, string value) public HttpHeader(string name, string value)
...@@ -24,4 +20,4 @@ namespace Titanium.Web.Http ...@@ -24,4 +20,4 @@ namespace Titanium.Web.Http
return string.Format("{0}: {1}", Name, Value); return string.Format("{0}: {1}", Name, Value);
} }
} }
} }
\ No newline at end of file
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
...@@ -10,7 +10,7 @@ using System.Runtime.InteropServices; ...@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Titanium.Web.Proxy.Properties")] [assembly: AssemblyProduct("Titanium.Web.Proxy.Properties")]
[assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
...@@ -32,5 +32,5 @@ using System.Runtime.InteropServices; ...@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Revision // Revision
// //
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.1")]
[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.1")]
\ No newline at end of file
...@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy ...@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy
{ {
ServicePointManager.Expect100Continue = false; ServicePointManager.Expect100Continue = false;
WebRequest.DefaultWebProxy = null; WebRequest.DefaultWebProxy = null;
ServicePointManager.DefaultConnectionLimit = 10; ServicePointManager.DefaultConnectionLimit = int.MaxValue;
ServicePointManager.DnsRefreshTimeout = 3 * 60 * 1000; //3 minutes ServicePointManager.DnsRefreshTimeout = 3 * 60 * 1000; //3 minutes
ServicePointManager.MaxServicePointIdleTime = 3 * 60 * 1000; ServicePointManager.MaxServicePointIdleTime = 3 * 60 * 1000;
...@@ -73,9 +73,11 @@ namespace Titanium.Web.Proxy ...@@ -73,9 +73,11 @@ namespace Titanium.Web.Proxy
return false; return false;
}; };
#if NET40
//Fix a bug in .NET 4.0 //Fix a bug in .NET 4.0
NetFrameworkHelper.UrlPeriodFix(); NetFrameworkHelper.UrlPeriodFix();
//useUnsafeHeaderParsing //useUnsafeHeaderParsing
#endif
NetFrameworkHelper.ToggleAllowUnsafeHeaderParsing(true); NetFrameworkHelper.ToggleAllowUnsafeHeaderParsing(true);
} }
...@@ -98,8 +100,11 @@ namespace Titanium.Web.Proxy ...@@ -98,8 +100,11 @@ namespace Titanium.Web.Proxy
{ {
SystemProxyHelper.EnableProxyHttp( SystemProxyHelper.EnableProxyHttp(
Equals(ListeningIpAddress, IPAddress.Any) ? "127.0.0.1" : ListeningIpAddress.ToString(), ListeningPort); Equals(ListeningIpAddress, IPAddress.Any) ? "127.0.0.1" : ListeningIpAddress.ToString(), ListeningPort);
#if !DEBUG
FireFoxHelper.AddFirefox(); FireFoxHelper.AddFirefox();
#endif
if (EnableSsl) if (EnableSsl)
{ {
...@@ -126,7 +131,7 @@ namespace Titanium.Web.Proxy ...@@ -126,7 +131,7 @@ namespace Titanium.Web.Proxy
_listener.BeginAcceptTcpClient(OnAcceptConnection, _listener); _listener.BeginAcceptTcpClient(OnAcceptConnection, _listener);
var client = _listener.EndAcceptTcpClient(asyn); var client = _listener.EndAcceptTcpClient(asyn);
var Task = HandleClient(client); Task.Factory.StartNew(() => HandleClient(client));
} }
catch catch
{ {
...@@ -140,7 +145,9 @@ namespace Titanium.Web.Proxy ...@@ -140,7 +145,9 @@ namespace Titanium.Web.Proxy
if (SetAsSystemProxy) if (SetAsSystemProxy)
{ {
SystemProxyHelper.DisableAllProxy(); SystemProxyHelper.DisableAllProxy();
#if !DEBUG
FireFoxHelper.RemoveFirefox(); FireFoxHelper.RemoveFirefox();
#endif
} }
_listener.Stop(); _listener.Stop();
......
...@@ -10,30 +10,32 @@ using System.Security.Authentication; ...@@ -10,30 +10,32 @@ using System.Security.Authentication;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Http;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
partial class ProxyServer partial class ProxyServer
{ {
private static async Task HandleClient(TcpClient client) private static void HandleClient(TcpClient client)
{ {
Stream clientStream = client.GetStream(); Stream clientStream = client.GetStream();
var clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII);
var clientStreamWriter = new StreamWriter(clientStream); var clientStreamWriter = new StreamWriter(clientStream);
Uri httpRemoteUri; Uri httpRemoteUri;
try try
{ {
//read the first line HTTP command //read the first line HTTP command
var httpCmd = await HttpStreamReader.ReadLine(clientStream); var httpCmd = clientStreamReader.ReadLine();
if (string.IsNullOrEmpty(httpCmd)) if (string.IsNullOrEmpty(httpCmd))
{ {
throw new EndOfStreamException(); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
return;
} }
//break up the line into three components (method, remote URL & Http Version) //break up the line into three components (method, remote URL & Http Version)
...@@ -54,7 +56,7 @@ namespace Titanium.Web.Proxy ...@@ -54,7 +56,7 @@ namespace Titanium.Web.Proxy
if (httpVerb.ToUpper() == "CONNECT" && !excluded && httpRemoteUri.Port == 443) if (httpVerb.ToUpper() == "CONNECT" && !excluded && httpRemoteUri.Port == 443)
{ {
httpRemoteUri = new Uri("https://" + httpCmdSplit[1]); httpRemoteUri = new Uri("https://" + httpCmdSplit[1]);
await HttpStreamReader.ReadAllLines(clientStream); clientStreamReader.ReadAllLines();
WriteConnectResponse(clientStreamWriter, httpVersion); WriteConnectResponse(clientStreamWriter, httpVersion);
...@@ -69,7 +71,7 @@ namespace Titanium.Web.Proxy ...@@ -69,7 +71,7 @@ namespace Titanium.Web.Proxy
sslStream.AuthenticateAsServer(certificate, false, sslStream.AuthenticateAsServer(certificate, false,
SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false); SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false);
clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII);
clientStreamWriter = new StreamWriter(sslStream); clientStreamWriter = new StreamWriter(sslStream);
//HTTPS server created - we can now decrypt the client's traffic //HTTPS server created - we can now decrypt the client's traffic
clientStream = sslStream; clientStream = sslStream;
...@@ -80,165 +82,176 @@ namespace Titanium.Web.Proxy ...@@ -80,165 +82,176 @@ namespace Titanium.Web.Proxy
if (sslStream != null) if (sslStream != null)
sslStream.Dispose(); sslStream.Dispose();
throw; Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
return;
} }
httpCmd = await HttpStreamReader.ReadLine(clientStream); httpCmd = clientStreamReader.ReadLine();
} }
else if (httpVerb.ToUpper() == "CONNECT") else if (httpVerb.ToUpper() == "CONNECT")
{ {
await HttpStreamReader.ReadAllLines(clientStream); clientStreamReader.ReadAllLines();
WriteConnectResponse(clientStreamWriter, httpVersion); WriteConnectResponse(clientStreamWriter, httpVersion);
TcpHelper.SendRaw(clientStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port, TcpHelper.SendRaw(clientStreamReader.BaseStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port,
false); false);
Dispose(client, clientStream, null, clientStreamWriter, null); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
return; return;
} }
//Now create the request //Now create the request
HandleHttpSessionRequest(client, httpCmd, clientStream, null, clientStreamWriter, HandleHttpSessionRequest(client, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
httpRemoteUri.Scheme == Uri.UriSchemeHttps ? httpRemoteUri.OriginalString : null); httpRemoteUri.Scheme == Uri.UriSchemeHttps ? httpRemoteUri.OriginalString : null);
} }
catch catch
{ {
Dispose(client, clientStream, null, clientStreamWriter, null); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
} }
} }
private static async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, private static async void HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
string clientStreamReader, StreamWriter clientStreamWriter, string secureTunnelHostName) CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string secureTunnelHostName)
{ {
if (string.IsNullOrEmpty(httpCmd)) while (true)
{ {
Dispose(client, clientStream, null, clientStreamWriter, null); if (string.IsNullOrEmpty(httpCmd))
return; {
} Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
return;
}
var args = new SessionEventArgs(BUFFER_SIZE); var args = new SessionEventArgs(BUFFER_SIZE);
args.Client = client; args.Client = client;
try
{
//break up the line into three components (method, remote URL & Http Version)
var httpCmdSplit = httpCmd.Split(SpaceSplit, 3);
try var httpMethod = httpCmdSplit[0];
{ var httpRemoteUri =
//break up the line into three components (method, remote URL & Http Version) new Uri(secureTunnelHostName == null ? httpCmdSplit[1] : (secureTunnelHostName + httpCmdSplit[1]));
var httpCmdSplit = httpCmd.Split(SpaceSplit, 3); var httpVersion = httpCmdSplit[2];
var httpMethod = httpCmdSplit[0]; Version version;
var httpRemoteUri = if (httpVersion == "HTTP/1.1")
new Uri(secureTunnelHostName == null ? httpCmdSplit[1] : (secureTunnelHostName + httpCmdSplit[1])); {
var httpVersion = httpCmdSplit[2]; version = new Version(1, 1);
}
else
{
version = new Version(1, 0);
}
Version version; if (httpRemoteUri.Scheme == Uri.UriSchemeHttps)
if (httpVersion == "HTTP/1.1") {
{ args.IsHttps = true;
version = new Version(1, 1); }
}
else
{
version = new Version(1, 0);
}
if (httpRemoteUri.Scheme == Uri.UriSchemeHttps) args.RequestHeaders = new List<HttpHeader>();
{
args.IsHttps = true;
}
args.RequestHeaders = new List<HttpHeader>(); string tmpLine;
string tmpLine; while (!string.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{
var header = tmpLine.Split(ColonSpaceSplit, 2, StringSplitOptions.None);
args.RequestHeaders.Add(new HttpHeader(header[0], header[1]));
}
while (!string.IsNullOrEmpty(tmpLine = await HttpStreamReader.ReadLine(clientStream))) for (var i = 0; i < args.RequestHeaders.Count; i++)
{ {
var header = tmpLine.Split(ColonSpaceSplit, 2, StringSplitOptions.None); var rawHeader = args.RequestHeaders[i];
args.RequestHeaders.Add(new HttpHeader(header[0], header[1]));
}
for (var i = 0; i < args.RequestHeaders.Count; i++)
{
var rawHeader = args.RequestHeaders[i];
//if request was upgrade to web-socket protocol then relay the request without proxying
if ((rawHeader.Name.ToLower() == "upgrade") && (rawHeader.Value.ToLower() == "websocket"))
{
TcpHelper.SendRaw(clientStreamReader.BaseStream, httpCmd, args.RequestHeaders,
httpRemoteUri.Host, httpRemoteUri.Port, httpRemoteUri.Scheme == Uri.UriSchemeHttps);
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
return;
}
}
//if request was upgrade to web-socket protocol then relay the request without proxying //construct the web request that we are going to issue on behalf of the client.
if ((rawHeader.Name.ToLower() == "upgrade") && (rawHeader.Value.ToLower() == "websocket")) args.ProxySession = new Http.HttpWebClient();
args.ProxySession.RequestUri = httpRemoteUri;
//args.ProxyRequest.Proxy = null;
//args.ProxyRequest.UseDefaultCredentials = true;
args.ProxySession.Method = httpMethod;
args.ProxySession.Version = httpVersion;
// args.ProxyRequest.ProtocolVersion = version;
args.ClientStream = clientStream;
args.ClientStreamReader = clientStreamReader;
args.ClientStreamWriter = clientStreamWriter;
// args.ProxyRequest.AllowAutoRedirect = false;
// args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None;
args.RequestHostname = args.ProxySession.RequestUri.Host;
args.RequestUrl = args.ProxySession.RequestUri.OriginalString;
args.ClientPort = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
args.ClientIpAddress = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
args.RequestHttpVersion = version;
//args.RequestIsAlive = args.ProxyRequest.KeepAlive;
//args.ProxyRequest.AllowWriteStreamBuffering = true;
args.Client = await TcpConnectionManager.GetClient(args.ProxySession.RequestUri.Host, args.ProxySession.RequestUri.Port, args.IsHttps);
args.ProxySession.Client = args.Client;
//If requested interception
if (BeforeRequest != null)
{ {
TcpHelper.SendRaw(clientStream, httpCmd, args.RequestHeaders, args.RequestEncoding = args.ProxySession.GetEncoding();
httpRemoteUri.Host, httpRemoteUri.Port, httpRemoteUri.Scheme == Uri.UriSchemeHttps); BeforeRequest(null, args);
Dispose(client, clientStream, null, clientStreamWriter, args);
return;
} }
}
//construct the web request that we are going to issue on behalf of the client. args.RequestLocked = true;
args.ProxyRequest = new HttpClient();
//args.ProxyRequest.Proxy = null;
//args.ProxyRequest.UseDefaultCredentials = true;
args.ProxyRequest.Method = httpMethod;
//args.ProxyRequest.ProtocolVersion = version;
args.ClientStream = clientStream;
//args.ClientStreamReader = clientStreamReader;
args.ClientStreamWriter = clientStreamWriter;
// args.ProxyRequest.AllowAutoRedirect = false;
//args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None;
//args.RequestHostname = args.ProxyRequest.RequestUri.Host;
//args.RequestUrl = args.ProxyRequest.RequestUri.OriginalString;
args.ClientPort = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
args.ClientIpAddress = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
args.RequestHttpVersion = version;
// args.RequestIsAlive = args.ProxyRequest.KeepAlive;
//args.ProxyRequest.ConnectionGroupName = args.RequestHostname;
//args.ProxyRequest.AllowWriteStreamBuffering = true;
if (args.CancelRequest)
{
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
return;
}
//If requested interception SetRequestHeaders(args.RequestHeaders, args.ProxySession);
if (BeforeRequest != null)
{
//args.RequestEncoding = args.ProxyRequest.GetEncoding();
//BeforeRequest(null, args);
}
args.RequestLocked = true; await args.ProxySession.SendRequest();
if (args.CancelRequest) //If request was modified by user
{ if (args.RequestBodyRead)
Dispose(client, clientStream, null, clientStreamWriter, args); {
return; args.ProxySession.RequestContentLength = args.RequestBody.Length;
} var newStream = args.ProxySession.ServerStreamReader.BaseStream;
newStream.Write(args.RequestBody, 0, args.RequestBody.Length);
}
else
{
//If its a post/put request, then read the client html body and send it to server
if (httpMethod.ToUpper() == "POST" || httpMethod.ToUpper() == "PUT")
{
SendClientRequestBody(args);
}
}
await HandleHttpSessionResponse(args);
SetRequestHeaders(args.RequestHeaders, args.ProxyRequest); //if connection is closing exit
if (args.ResponseHeaders.Any(x => x.Name.ToLower() == "connection" && x.Value.ToLower() == "close"))
{
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
return;
}
//If request was modified by user // read the next request
if (args.RequestBodyRead) httpCmd = clientStreamReader.ReadLine();
{
args.ProxyRequest.ContentLength = args.RequestBody.Length;
var newStream = await args.ProxyRequest.GetStream();
newStream.Write(args.RequestBody, 0, args.RequestBody.Length);
args.ProxyRequest.BeginGetResponse(HandleHttpSessionResponse, args);
} }
else catch
{ {
//If its a post/put request, then read the client html body and send it to server Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
if (httpMethod.ToUpper() == "POST" || httpMethod.ToUpper() == "PUT") return;
{
await SendClientRequestBody(args);
}
//Http request body sent, now wait asynchronously for response
args.ProxyRequest.BeginGetResponse(HandleHttpSessionResponse, args);
} }
//Now read the next request (if keep-Alive is enabled, otherwise exit this thread)
//If client is pipeling the request, this will be immediately hit before response for previous request was made
httpCmd = await HttpStreamReader.ReadLine(args.ClientStream);
//Http request body sent, now wait for next request
HandleHttpSessionRequest(args.Client, httpCmd, args.ClientStream, null,
args.ClientStreamWriter, secureTunnelHostName);
}
catch
{
Dispose(client, clientStream, null, clientStreamWriter, args);
} }
} }
...@@ -246,107 +259,109 @@ namespace Titanium.Web.Proxy ...@@ -246,107 +259,109 @@ namespace Titanium.Web.Proxy
{ {
clientStreamWriter.WriteLine(httpVersion + " 200 Connection established"); clientStreamWriter.WriteLine(httpVersion + " 200 Connection established");
clientStreamWriter.WriteLine("Timestamp: {0}", DateTime.Now); clientStreamWriter.WriteLine("Timestamp: {0}", DateTime.Now);
clientStreamWriter.WriteLine("connection:close"); //clientStreamWriter.WriteLine("connection:close");
clientStreamWriter.WriteLine(); clientStreamWriter.WriteLine();
clientStreamWriter.Flush(); clientStreamWriter.Flush();
} }
private static void SetRequestHeaders(List<HttpHeader> requestHeaders, HttpClient webRequest) private static void SetRequestHeaders(List<HttpHeader> requestHeaders, HttpWebClient webRequest)
{ {
for (var i = 0; i < requestHeaders.Count; i++) for (var i = 0; i < requestHeaders.Count; i++)
{ {
//switch (requestHeaders[i].Name.ToLower()) switch (requestHeaders[i].Name.ToLower())
//{ {
// case "accept": case "accept":
// webRequest.Accept = requestHeaders[i].Value; // webRequest.Accept = requestHeaders[i].Value;
// break; break;
// case "accept-encoding": case "accept-encoding":
// webRequest.Headers.Add("Accept-Encoding", "gzip,deflate,zlib"); requestHeaders[i].Value = "gzip,deflate,zlib";
// break; break;
// case "cookie": case "cookie":
// webRequest.Headers["Cookie"] = requestHeaders[i].Value; //webRequest.Headers["Cookie"] = requestHeaders[i].Value;
// break; break;
// case "connection": case "connection":
// if (requestHeaders[i].Value.ToLower() == "keep-alive") if (requestHeaders[i].Value.ToLower() == "keep-alive")
// webRequest.KeepAlive = true; webRequest.RequestKeepAlive = true;
break;
// break; case "content-length":
// case "content-length": int contentLen;
// int contentLen; int.TryParse(requestHeaders[i].Value, out contentLen);
// int.TryParse(requestHeaders[i].Value, out contentLen); if (contentLen != 0)
// if (contentLen != 0) webRequest.RequestContentLength = contentLen;
// webRequest.ContentLength = contentLen; break;
// break; case "content-type":
// case "content-type": webRequest.RequestContentType = requestHeaders[i].Value;
// webRequest.ContentType = requestHeaders[i].Value; break;
// break; case "expect":
// case "expect": //if (requestHeaders[i].Value.ToLower() == "100-continue")
// if (requestHeaders[i].Value.ToLower() == "100-continue") // webRequest.ServicePoint.Expect100Continue = true;
// webRequest.ServicePoint.Expect100Continue = true; // else
// else // webRequest.Expect = requestHeaders[i].Value;
// webRequest.Expect = requestHeaders[i].Value; break;
// break; case "host":
// case "host": webRequest.RequestHost = requestHeaders[i].Value;
// webRequest.Host = requestHeaders[i].Value; break;
// break; case "if-modified-since":
// case "if-modified-since": // var sb = requestHeaders[i].Value.Trim().Split(SemiSplit);
// var sb = requestHeaders[i].Value.Trim().Split(SemiSplit); // DateTime d;
// DateTime d; // if (DateTime.TryParse(sb[0], out d))
// if (DateTime.TryParse(sb[0], out d)) // webRequest.IfModifiedSince = d;
// webRequest.IfModifiedSince = d; break;
// break; case "proxy-connection":
// case "proxy-connection": if (requestHeaders[i].Value.ToLower() == "keep-alive")
// if (requestHeaders[i].Value.ToLower() == "keep-alive") webRequest.RequestKeepAlive = true;
// webRequest.KeepAlive = true; else if (requestHeaders[i].Value.ToLower() == "close")
// break; webRequest.RequestKeepAlive = false;
// case "range": break;
// var startEnd = requestHeaders[i].Value.Replace(Environment.NewLine, "").Remove(0, 6).Split('-'); case "range":
// if (startEnd.Length > 1) // var startEnd = requestHeaders[i].Value.Replace(Environment.NewLine, "").Remove(0, 6).Split('-');
// { // if (startEnd.Length > 1)
// if (!string.IsNullOrEmpty(startEnd[1])) // {
// webRequest.AddRange(int.Parse(startEnd[0]), int.Parse(startEnd[1])); // if (!string.IsNullOrEmpty(startEnd[1]))
// else webRequest.AddRange(int.Parse(startEnd[0])); // webRequest.AddRange(int.Parse(startEnd[0]), int.Parse(startEnd[1]));
// } // else webRequest.AddRange(int.Parse(startEnd[0]));
// else // }
// webRequest.AddRange(int.Parse(startEnd[0])); // else
// break; // webRequest.AddRange(int.Parse(startEnd[0]));
// case "referer": break;
// webRequest.Referer = requestHeaders[i].Value; case "referer":
// break; // webRequest.Referer = requestHeaders[i].Value;
// case "user-agent": break;
// webRequest.UserAgent = requestHeaders[i].Value; case "user-agent":
// break; // webRequest.UserAgent = requestHeaders[i].Value;
break;
// //revisit this, transfer-encoding is not a request header according to spec
// //But how to identify if client is sending chunked body for PUT/POST? //revisit this, transfer-encoding is not a request header according to spec
// case "transfer-encoding": //But how to identify if client is sending chunked body for PUT/POST?
// if (requestHeaders[i].Value.ToLower().Contains("chunked")) case "transfer-encoding":
// webRequest.SendChunked = true; if (requestHeaders[i].Value.ToLower().Contains("chunked"))
// else webRequest.RequestSendChunked = true;
// webRequest.SendChunked = false; else
// break; webRequest.RequestSendChunked = false;
// case "upgrade": break;
// if (requestHeaders[i].Value.ToLower() == "http/1.1") case "upgrade":
// webRequest.Headers.Add("Upgrade", requestHeaders[i].Value); // if (requestHeaders[i].Value.ToLower() == "http/1.1")
// break; // webRequest.Headers.Add("Upgrade", requestHeaders[i].Value);
break;
// default:
// webRequest.Headers.Add(requestHeaders[i].Name, requestHeaders[i].Value); default:
// webRequest.Headers.Add(requestHeaders[i].Name, requestHeaders[i].Value);
// break;
//} break;
requestHeaders.Add(new HttpHeader(requestHeaders[i].Name, requestHeaders[i].Value)); }
} }
webRequest.RequestHeaders = requestHeaders;
} }
//This is called when the request is PUT/POST to read the body //This is called when the request is PUT/POST to read the body
private static async Task SendClientRequestBody(SessionEventArgs args) private static void SendClientRequestBody(SessionEventArgs args)
{ {
// End the operation // End the operation
var postStream = args.ProxyRequest.Stream; var postStream = args.ProxySession.ServerStreamReader;
if (args.ProxyRequest.ContentLength > 0) if (args.ProxySession.RequestContentLength > 0)
{ {
//args.ProxyRequest.AllowWriteStreamBuffering = true; //args.ProxyRequest.AllowWriteStreamBuffering = true;
try try
...@@ -354,26 +369,25 @@ namespace Titanium.Web.Proxy ...@@ -354,26 +369,25 @@ namespace Titanium.Web.Proxy
var totalbytesRead = 0; var totalbytesRead = 0;
int bytesToRead; int bytesToRead;
if (args.ProxyRequest.ContentLength < BUFFER_SIZE) if (args.ProxySession.RequestContentLength < BUFFER_SIZE)
{ {
bytesToRead = (int)args.ProxyRequest.ContentLength; bytesToRead = (int)args.ProxySession.RequestContentLength;
} }
else else
bytesToRead = BUFFER_SIZE; bytesToRead = BUFFER_SIZE;
while (totalbytesRead < (int)args.ProxyRequest.ContentLength) while (totalbytesRead < (int)args.ProxySession.RequestContentLength)
{ {
var buffer = new byte[bytesToRead]; var buffer = args.ClientStreamReader.ReadBytes(bytesToRead);
args.ClientStream.Read(buffer, 0, bytesToRead);
totalbytesRead += buffer.Length; totalbytesRead += buffer.Length;
var remainingBytes = (int)args.ProxyRequest.ContentLength - totalbytesRead; var remainingBytes = (int)args.ProxySession.RequestContentLength - totalbytesRead;
if (remainingBytes < bytesToRead) if (remainingBytes < bytesToRead)
{ {
bytesToRead = remainingBytes; bytesToRead = remainingBytes;
} }
postStream.Write(buffer, 0, buffer.Length); postStream.BaseStream.Write(buffer, 0, buffer.Length);
} }
postStream.Close(); postStream.Close();
...@@ -386,33 +400,32 @@ namespace Titanium.Web.Proxy ...@@ -386,33 +400,32 @@ namespace Titanium.Web.Proxy
} }
} }
//Need to revist, find any potential bugs //Need to revist, find any potential bugs
else if (args.ProxyRequest.SendChunked) else if (args.ProxySession.RequestSendChunked)
{ {
// args.ProxyRequest.AllowWriteStreamBuffering = true; //args.ProxyRequest.AllowWriteStreamBuffering = true;
try try
{ {
while (true) while (true)
{ {
var chuchkHead = await HttpStreamReader.ReadLine(args.ClientStream); var chuchkHead = args.ClientStreamReader.ReadLine();
var chunkSize = int.Parse(chuchkHead, NumberStyles.HexNumber); var chunkSize = int.Parse(chuchkHead, NumberStyles.HexNumber);
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = new byte[chunkSize]; var buffer = args.ClientStreamReader.ReadBytes(chunkSize);
args.ClientStream.Read(buffer,0,chunkSize); postStream.BaseStream.Write(buffer, 0, buffer.Length);
postStream.Write(buffer, 0, buffer.Length);
//chunk trail //chunk trail
await HttpStreamReader.ReadLine(args.ClientStream); args.ClientStreamReader.ReadLine();
} }
else else
{ {
await HttpStreamReader.ReadLine(args.ClientStream); args.ClientStreamReader.ReadLine();
break; break;
} }
} }
postStream.Close(); postStream.Close();
} }
catch catch
......
...@@ -6,11 +6,11 @@ using System.Net; ...@@ -6,11 +6,11 @@ using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Http;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -18,67 +18,65 @@ namespace Titanium.Web.Proxy ...@@ -18,67 +18,65 @@ namespace Titanium.Web.Proxy
{ {
//Called asynchronously when a request was successfully and we received the response //Called asynchronously when a request was successfully and we received the response
private static async Task HandleHttpSessionResponse(SessionEventArgs args) private static async Task HandleHttpSessionResponse(SessionEventArgs args)
{ {
await args.ProxyRequest.ReceiveResponse(); args.ProxySession.ReceiveResponse();
try try
{ {
if (args.ProxyRequest != null)
{
args.ResponseHeaders = ReadResponseHeaders(args.ProxyRequest);
args.ResponseStream = args.ProxyRequest.GetResponseStream();
args.ResponseHeaders = ReadResponseHeaders(args.ProxySession);
args.ResponseStream = args.ProxySession.ServerStreamReader.BaseStream;
if (BeforeResponse != null)
{
args.ResponseEncoding = args.ProxyRequest.GetEncoding();
BeforeResponse(null, args);
}
args.ResponseLocked = true; if (BeforeResponse != null)
{
args.ResponseEncoding = args.ProxySession.GetResponseEncoding();
BeforeResponse(null, args);
}
if (args.ResponseBodyRead) args.ResponseLocked = true;
{
var isChunked = args.ProxyRequest.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked");
var contentEncoding = args.ProxyRequest.ContentEncoding;
switch (contentEncoding.ToLower()) if (args.ResponseBodyRead)
{ {
case "gzip": var isChunked = args.ProxySession.ResponseHeaders.Any(x => x.Name.ToLower() == "transfer-encoding" && x.Value.ToLower().Contains("chunked"));
args.ResponseBody = CompressionHelper.CompressGzip(args.ResponseBody); var contentEncoding = args.ProxySession.ResponseContentEncoding;
break;
case "deflate":
args.ResponseBody = CompressionHelper.CompressDeflate(args.ResponseBody);
break;
case "zlib":
args.ResponseBody = CompressionHelper.CompressZlib(args.ResponseBody);
break;
}
WriteResponseStatus(args.ProxyRequest.ProtocolVersion, args.ProxyRequest.StatusCode, switch (contentEncoding.ToLower())
args.ProxyRequest.StatusDescription, args.ClientStreamWriter);
WriteResponseHeaders(args.ClientStreamWriter, args.ResponseHeaders, args.ResponseBody.Length,
isChunked);
WriteResponseBody(args.ClientStream, args.ResponseBody, isChunked);
}
else
{ {
var isChunked = args.ProxyRequest.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked"); case "gzip":
args.ResponseBody = CompressionHelper.CompressGzip(args.ResponseBody);
WriteResponseStatus(args.ProxyRequest.ProtocolVersion, args.ProxyRequest.StatusCode, break;
args.ProxyRequest.StatusDescription, args.ClientStreamWriter); case "deflate":
WriteResponseHeaders(args.ClientStreamWriter, args.ResponseHeaders); args.ResponseBody = CompressionHelper.CompressDeflate(args.ResponseBody);
WriteResponseBody(args.ResponseStream, args.ClientStream, isChunked); break;
case "zlib":
args.ResponseBody = CompressionHelper.CompressZlib(args.ResponseBody);
break;
} }
args.ClientStream.Flush(); WriteResponseStatus(args.ProxySession.ResponseProtocolVersion, args.ProxySession.ResponseStatusCode,
args.ProxySession.ResponseStatusDescription, args.ClientStreamWriter);
WriteResponseHeaders(args.ClientStreamWriter, args.ResponseHeaders, args.ResponseBody.Length,
isChunked);
WriteResponseBody(args.ClientStream, args.ResponseBody, isChunked);
}
else
{
// var isChunked = args.ProxySession.ResponseHeaders.Any(x => x.Name.ToLower() == "transfer-encoding" && x.Value.ToLower().Contains("chunked"));
WriteResponseStatus(args.ProxySession.ResponseProtocolVersion, args.ProxySession.ResponseStatusCode,
args.ProxySession.ResponseStatusDescription, args.ClientStreamWriter);
WriteResponseHeaders(args.ClientStreamWriter, args.ResponseHeaders);
WriteResponseBody(args.ResponseStream, args.ClientStream, false);
} }
args.ClientStream.Flush();
} }
catch catch
{ {
Dispose(args.Client, args.ClientStream, null, args.ClientStreamWriter, args); Dispose(args.Client, args.ClientStream, args.ClientStreamReader, args.ClientStreamWriter, args);
} }
finally finally
{ {
...@@ -86,39 +84,43 @@ namespace Titanium.Web.Proxy ...@@ -86,39 +84,43 @@ namespace Titanium.Web.Proxy
} }
} }
private static List<HttpHeader> ReadResponseHeaders(HttpWebResponse response) private static List<HttpHeader> ReadResponseHeaders(HttpWebClient response)
{ {
var returnHeaders = new List<HttpHeader>(); for (var i = 0; i < response.ResponseHeaders.Count; i++)
string cookieHeaderName = null;
string cookieHeaderValue = null;
foreach (string headerKey in response.Headers.Keys)
{ {
if (headerKey.ToLower() == "set-cookie") switch (response.ResponseHeaders[i].Name.ToLower())
{ {
cookieHeaderName = headerKey; case "content-encoding":
cookieHeaderValue = response.Headers[headerKey]; response.ResponseContentEncoding = response.ResponseHeaders[i].Value;
} break;
else
returnHeaders.Add(new HttpHeader(headerKey, response.Headers[headerKey]));
}
if (!string.IsNullOrWhiteSpace(cookieHeaderValue)) case "content-type":
{ if (response.ResponseHeaders[i].Value.Contains(";"))
response.Headers.Remove(cookieHeaderName); {
var cookies = CookieSplitRegEx.Split(cookieHeaderValue); response.ResponseContentType = response.ResponseHeaders[i].Value.Split(';')[0].Trim();
foreach (var cookie in cookies) response.ResponseCharacterSet = response.ResponseHeaders[i].Value.Split(';')[1].Replace("charset=", string.Empty).Trim();
returnHeaders.Add(new HttpHeader("Set-Cookie", cookie)); }
} else
response.ResponseContentType = response.ResponseHeaders[i].Value.Trim();
break;
return returnHeaders; case "connection":
break;
default:
break;
}
}
// response.ResponseHeaders.RemoveAll(x => x.Name.ToLower() == "connection");
return response.ResponseHeaders;
} }
private static void WriteResponseStatus(Version version, HttpStatusCode code, string description, private static void WriteResponseStatus(Version version, string code, string description,
StreamWriter responseWriter) StreamWriter responseWriter)
{ {
var s = string.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, (int)code, description); var s = string.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, code, description);
responseWriter.WriteLine(s); responseWriter.WriteLine(s);
} }
...@@ -126,6 +128,8 @@ namespace Titanium.Web.Proxy ...@@ -126,6 +128,8 @@ namespace Titanium.Web.Proxy
{ {
if (headers != null) if (headers != null)
{ {
//FixProxyHeaders(headers);
foreach (var header in headers) foreach (var header in headers)
{ {
responseWriter.WriteLine(header.ToString()); responseWriter.WriteLine(header.ToString());
...@@ -135,10 +139,24 @@ namespace Titanium.Web.Proxy ...@@ -135,10 +139,24 @@ namespace Titanium.Web.Proxy
responseWriter.WriteLine(); responseWriter.WriteLine();
responseWriter.Flush(); responseWriter.Flush();
} }
private static void FixProxyHeaders(List<HttpHeader> headers)
{
//If proxy-connection close was returned inform to close the connection
if (headers.Any(x => x.Name.ToLower() == "proxy-connection" && x.Value.ToLower() == "close"))
if (headers.Any(x => x.Name.ToLower() == "connection") == false)
{
headers.Add(new HttpHeader("connection", "close"));
headers.RemoveAll(x => x.Name.ToLower() == "proxy-connection");
}
else
headers.Find(x => x.Name.ToLower() == "connection").Value = "close";
}
private static void WriteResponseHeaders(StreamWriter responseWriter, List<HttpHeader> headers, int length, private static void WriteResponseHeaders(StreamWriter responseWriter, List<HttpHeader> headers, int length,
bool isChunked) bool isChunked)
{ {
FixProxyHeaders(headers);
if (!isChunked) if (!isChunked)
{ {
if (headers.Any(x => x.Name.ToLower() == "content-length") == false) if (headers.Any(x => x.Name.ToLower() == "content-length") == false)
......
...@@ -10,68 +10,51 @@ ...@@ -10,68 +10,51 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Titanium.Web.Proxy</RootNamespace> <RootNamespace>Titanium.Web.Proxy</RootNamespace>
<AssemblyName>Titanium.Web.Proxy</AssemblyName> <AssemblyName>Titanium.Web.Proxy</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages> <RestorePackages>true</RestorePackages>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject /> <StartupObject />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG</DefineConstants> <DefineConstants>DEBUG;NET40</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<DefineConstants>NET40</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Net45|AnyCPU'">
<OutputPath>bin\x64\Debug\</OutputPath> <DebugSymbols>true</DebugSymbols>
<PlatformTarget>x64</PlatformTarget> <OutputPath>bin\Debug-Net45\</OutputPath>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets> <DefineConstants>DEBUG</DefineConstants>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules> <PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release-Net45|AnyCPU'">
<OutputPath>bin\x64\Release\</OutputPath> <OutputPath>bin\Release-Net45\</OutputPath>
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Ionic.Zip"> <Reference Include="Ionic.Zip, Version=1.9.7.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
<HintPath>..\packages\DotNetZip.1.9.3\lib\net20\Ionic.Zip.dll</HintPath> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\DotNetZip.1.9.7\lib\net20\Ionic.Zip.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Threading.Tasks"> <Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions"> <Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop"> <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
...@@ -80,14 +63,14 @@ ...@@ -80,14 +63,14 @@
<Reference Include="System.configuration" /> <Reference Include="System.configuration" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.IO"> <Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.IO.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Net" /> <Reference Include="System.Net" />
<Reference Include="System.Runtime"> <Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.Runtime.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Threading.Tasks"> <Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\net40\System.Threading.Tasks.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
...@@ -102,9 +85,13 @@ ...@@ -102,9 +85,13 @@
<Compile Include="Helpers\CertificateManager.cs" /> <Compile Include="Helpers\CertificateManager.cs" />
<Compile Include="Helpers\Firefox.cs" /> <Compile Include="Helpers\Firefox.cs" />
<Compile Include="Helpers\SystemProxy.cs" /> <Compile Include="Helpers\SystemProxy.cs" />
<Compile Include="Http\TcpConnectionManager.cs" />
<Compile Include="Models\HttpHeader.cs" />
<Compile Include="Http\HttpWebClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RequestHandler.cs" /> <Compile Include="RequestHandler.cs" />
<Compile Include="ResponseHandler.cs" /> <Compile Include="ResponseHandler.cs" />
<Compile Include="Helpers\CustomBinaryReader.cs" />
<Compile Include="Helpers\NetFramework.cs" /> <Compile Include="Helpers\NetFramework.cs" />
<Compile Include="Helpers\Compression.cs" /> <Compile Include="Helpers\Compression.cs" />
<Compile Include="ProxyServer.cs" /> <Compile Include="ProxyServer.cs" />
...@@ -112,12 +99,7 @@ ...@@ -112,12 +99,7 @@
<Compile Include="Helpers\Tcp.cs" /> <Compile Include="Helpers\Tcp.cs" />
<Compile Include="Extensions\StreamExtensions.cs" /> <Compile Include="Extensions\StreamExtensions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup />
<ProjectReference Include="..\Titanium.Web.Http\Titanium.Web.Http.csproj">
<Project>{51f8273a-39e4-4c9f-9972-bc78f8b3b32e}</Project>
<Name>Titanium.Web.Http</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
......
...@@ -13,11 +13,14 @@ ...@@ -13,11 +13,14 @@
<releaseNotes></releaseNotes> <releaseNotes></releaseNotes>
<copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright> <copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright>
<tags></tags> <tags></tags>
<dependencies>
<dependency id="DotNetZip" version="1.9.7" />
</dependencies>
</metadata> </metadata>
<files> <files>
<file src="Titanium.Web.Proxy\bin\$configuration$\Titanium.Web.Proxy.dll" target="lib\net40\" /> <file src="bin\$configuration$\Titanium.Web.Proxy.dll" target="lib\net40" />
<file src="Titanium.Web.Proxy\bin\$configuration$\Ionic.Zip.dll" target="lib\net40\" /> <file src="bin\$configuration$-Net45\Titanium.Web.Proxy.dll" target="lib\net45" />
<file src="Titanium.Web.Proxy\bin\$configuration$\makecert.exe" target="content" /> <file src="bin\$configuration$\makecert.exe" target="content" />
<file src="Titanium.Web.Proxy\bin\$configuration$\Titanium_Proxy_Test_Root.cer" target="content" /> <file src="bin\$configuration$\Titanium_Proxy_Test_Root.cer" target="content" />
</files> </files>
</package> </package>
\ No newline at end of file
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" /> <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" /> <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="DotNetZip" version="1.9.3" targetFramework="net40-Client" /> <package id="DotNetZip" version="1.9.7" targetFramework="net40" />
<package id="Microsoft.Bcl" version="1.1.8" targetFramework="net40-Client" /> <package id="DotNetZip" version="1.9.7" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net40-Client" /> <package id="Microsoft.Bcl" version="1.1.10" targetFramework="net40" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net40-Client" /> <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net40" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net40" />
</packages> </packages>
\ No newline at end of file
# AppVeyor CI build file
# Notes:
# - Minimal appveyor.yml file is an empty file. All sections are optional.
# - Indent each level of configuration with 2 spaces. Do not use tabs!
# - All section names are case-sensitive.
# - Section names should be unique on each level.
# version format
version: 1.1.{build}
shallow_clone: true
#---------------------------------#
# build configuration #
#---------------------------------#
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
platform: Any CPU
# build Configuration, i.e. Debug, Release, etc.
configuration: Release
# to run your custom scripts instead of automatic MSBuild
build_script:
- cmd: .\build.bat Package
assembly_info:
patch: true
file: AssemblyInfo.*
assembly_version: "{version}"
assembly_file_version: "{version}"
assembly_informational_version: "{version}"
# to disable automatic tests
test: off
# skip building commits that add tags (such as release tag)
skip_tags: true
#---------------------------------#
# artifacts configuration #
#---------------------------------#
nuget:
account_feed: true
project_feed: true
disable_publish_on_pr: true # disable publishing of .nupkg artifacts to account/project feeds for pull request builds
artifacts:
- path: '**\Titanium.Web.Proxy.*.nupkg'
deploy:
- provider: GitHub
auth_token:
secure: ItVm+50ASpDXx1w+FCe2NTpZxqCbjRWfugLjk/bqBIi00DvPnSGOV1rIQ5hnwBW3
on:
branch: master
- provider: NuGet
api_key:
secure: ZbRmjOcp+TDllRV1wxqLZjdRV7hld388rXlWVJuGGiQleomP9Ku+Nsy3a75E7/9k
on:
branch: master
\ No newline at end of file
@echo Off @echo off
set config=%1
if "%config%" == "" ( if '%1'=='/?' goto help
set config=Release if '%1'=='-help' goto help
) if '%1'=='-h' goto help
set version=1.0.0 powershell -NoProfile -ExecutionPolicy bypass -Command "%~dp0.build\bootstrap.ps1 %*; if ($psake.build_success -eq $false) { exit 1 } else { exit 0 }"
if not "%PackageVersion%" == "" ( exit /B %errorlevel%
set version=%PackageVersion%
) :help
powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0.build\bootstrap.ps1' -help"
set nuget= \ No newline at end of file
if "%nuget%" == "" (
set nuget=.nuget\nuget.exe
)
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild Titanium.Web.Proxy.sln /p:Configuration="%config%" /m /v:M /fl /flp:LogFile=msbuild.log;Verbosity=diag /nr:false
mkdir Build
mkdir Build\lib
mkdir Build\lib\net40
%nuget% pack "Titanium.Web.Proxy.nuspec" -NoPackageAnalysis -verbosity detailed -o Build -Version %version% -p Configuration="%config%"
\ 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