Unverified Commit 79542b52 authored by justcoding121's avatar justcoding121 Committed by GitHub

Merge pull request #418 from justcoding121/master

Beta release with API metadata updates
parents b69506ef 31db5eb6
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\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
...@@ -5,59 +5,119 @@ $Here = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" ...@@ -5,59 +5,119 @@ $Here = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$SolutionRoot = (Split-Path -parent $Here) $SolutionRoot = (Split-Path -parent $Here)
$ProjectName = "Titanium.Web.Proxy" $ProjectName = "Titanium.Web.Proxy"
$GitHubProjectName = "Titanium-Web-Proxy"
$GitHubUserName = "justcoding121"
$SolutionFile = "$SolutionRoot\$ProjectName.sln" $SolutionFile = "$SolutionRoot\$ProjectName.sln"
## This comes from the build server iteration ## This comes from the build server iteration
if(!$BuildNumber) { $BuildNumber = $env:APPVEYOR_BUILD_NUMBER } if(!$BuildNumber) { $BuildNumber = $env:APPVEYOR_BUILD_NUMBER }
if(!$BuildNumber) { $BuildNumber = "1"} if(!$BuildNumber) { $BuildNumber = "0"}
## The build configuration, i.e. Debug/Release ## The build configuration, i.e. Debug/Release
if(!$Configuration) { $Configuration = $env:Configuration } if(!$Configuration) { $Configuration = $env:Configuration }
if(!$Configuration) { $Configuration = "Release" } if(!$Configuration) { $Configuration = "Release" }
if(!$Version) { $Version = $env:APPVEYOR_BUILD_VERSION } if(!$Version) { $Version = $env:APPVEYOR_BUILD_VERSION }
if(!$Version) { $Version = "1.0.$BuildNumber" } if(!$Version) { $Version = "0.0.$BuildNumber" }
if(!$Branch) { $Branch = $env:APPVEYOR_REPO_BRANCH } if(!$Branch) { $Branch = $env:APPVEYOR_REPO_BRANCH }
if(!$Branch) { $Branch = "local" } if(!$Branch) { $Branch = "local" }
if($Branch -eq "beta" ) { $Version = "$Version-beta" } if($Branch -eq "beta" ) { $Version = "$Version-beta" }
Import-Module "$Here\Common" -DisableNameChecking
$NuGet = Join-Path $SolutionRoot ".nuget\nuget.exe" $NuGet = Join-Path $SolutionRoot ".nuget\nuget.exe"
$MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" $MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe"
$MSBuild -replace ' ', '` ' $MSBuild -replace ' ', '` '
FormatTaskName (("-"*25) + "[{0}]" + ("-"*25)) FormatTaskName (("-"*25) + "[{0}]" + ("-"*25))
Task default -depends Clean, Build, Package #default task
Task default -depends Clean, Build, Document, Package
Task Build -depends Restore-Packages{
exec { . $MSBuild $SolutionFile /t:Build /v:normal /p:Configuration=$Configuration /t:restore }
}
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 { #cleans obj, b
Task Clean {
Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { Remove-Item $_.fullname -Force -Recurse } Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { Remove-Item $_.fullname -Force -Recurse }
exec { . $MSBuild $SolutionFile /t:Clean /v:quiet } exec { . $MSBuild $SolutionFile /t:Clean /v:quiet }
} }
Task Restore-Packages { #install build tools
exec { . dotnet restore "$SolutionRoot\Titanium.Web.Proxy.sln" } Task Install-BuildTools -depends Clean {
}
Task Install-MSBuild {
if(!(Test-Path $MSBuild)) if(!(Test-Path $MSBuild))
{ {
cinst microsoft-build-tools -y cinst microsoft-build-tools -y
} }
} }
Task Install-BuildTools -depends Install-MSBuild #restore nuget packages
\ No newline at end of file Task Restore-Packages -depends Install-BuildTools {
exec { . dotnet restore "$SolutionRoot\$ProjectName.sln" }
}
#build
Task Build -depends Restore-Packages{
exec { . $MSBuild $SolutionFile /t:Build /v:normal /p:Configuration=$Configuration /t:restore }
}
#publish API documentation changes for GitHub pages under master\docs directory
Task Document -depends Build {
if($Branch -eq "master")
{
#use docfx to generate API documentation from source metadata
docfx docfx.json
#patch index.json so that it is always sorted
#otherwise git will think file was changed
$IndexJsonFile = "$SolutionRoot\docs\index.json"
$unsorted = Get-Content $IndexJsonFile | Out-String
[Reflection.Assembly]::LoadFile("$Here\lib\Newtonsoft.Json.dll")
[System.Reflection.Assembly]::LoadWithPartialName("System")
$hashTable = [Newtonsoft.Json.JsonConvert]::DeserializeObject($unsorted, [System.Collections.Generic.SortedDictionary[[string],[object]]])
$obj = [Newtonsoft.Json.JsonConvert]::SerializeObject($hashTable, [Newtonsoft.Json.Formatting]::Indented)
Set-Content -Path $IndexJsonFile -Value $obj
#setup clone directory
$TEMP_REPO_DIR =(Split-Path -parent $SolutionRoot) + "\temp-repo-clone"
If(test-path $TEMP_REPO_DIR)
{
Remove-Item $TEMP_REPO_DIR -Force -Recurse
}
New-Item -ItemType Directory -Force -Path $TEMP_REPO_DIR
#clone
git clone https://github.com/$GitHubUserName/$GitHubProjectName.git --branch master $TEMP_REPO_DIR
If(test-path "$TEMP_REPO_DIR\docs")
{
Remove-Item "$TEMP_REPO_DIR\docs" -Force -Recurse
}
New-Item -ItemType Directory -Force -Path "$TEMP_REPO_DIR\docs"
#cd to docs folder
cd "$TEMP_REPO_DIR\docs"
#copy docs to clone directory\docs
Copy-Item -Path "$SolutionRoot\docs\*" -Destination "$TEMP_REPO_DIR\docs" -Recurse -Force
#push changes to master
git config --global credential.helper store
Add-Content "$HOME\.git-credentials" "https://$($env:github_access_token):x-oauth-basic@github.com`n"
git config --global user.email $env:github_email
git config --global user.name "buildbot121"
git add . -A
git commit -m "API documentation update by build server"
git push origin master
#move cd back to current location
cd $Here
}
}
#package nuget files
Task Package -depends Document {
exec { . $NuGet pack "$SolutionRoot\$ProjectName\$ProjectName.nuspec" -Properties Configuration=$Configuration -OutputDirectory "$SolutionRoot" -Version "$Version" }
}
{
"metadata": [
{
"src": [
{
"files": [ "Titanium.Web.Proxy.Docs.sln"],
"src": "../"
}
],
"dest": "obj/api"
}
],
"build": {
"content": [
{
"files": [ "**/*.yml" ],
"src": "obj/api",
"dest": "api"
},
{
"files": [ "*.md" ]
}
],
"resource": [
{
"files": [ ""]
}
],
"overwrite": "specs/*.md",
"globalMetadata": {
"_appTitle": "Titanium Web Proxy",
"_enableSearch": true
},
"dest": "../docs",
"xrefService": [ "https://xref.docs.microsoft.com/query?uid={uid}" ]
}
}
### param (
### Common Profile functions for all users [string]$Action="default",
### [hashtable]$properties=@{},
[switch]$Help
$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() function Install-Chocolatey()
{ {
...@@ -20,6 +11,7 @@ function Install-Chocolatey() ...@@ -20,6 +11,7 @@ function Install-Chocolatey()
Write-Output "Chocolatey Not Found, Installing..." Write-Output "Chocolatey Not Found, Installing..."
iex ((new-object net.webclient).DownloadString('http://chocolatey.org/install.ps1')) iex ((new-object net.webclient).DownloadString('http://chocolatey.org/install.ps1'))
} }
$env:Path += ";${env:ChocolateyInstall}"
} }
function Install-Psake() function Install-Psake()
...@@ -30,4 +22,60 @@ function Install-Psake() ...@@ -30,4 +22,60 @@ function Install-Psake()
} }
} }
Export-ModuleMember -Function *-* function Install-Git()
\ No newline at end of file {
if(!((Test-Path ${env:ProgramFiles(x86)}\Git*) -Or (Test-Path ${env:ProgramFiles}\Git*)))
{
choco install git.install
}
$env:Path += ";${env:ProgramFiles(x86)}\Git"
$env:Path += ";${env:ProgramFiles}\Git"
}
function Install-DocFx()
{
if(!(Test-Path $env:ChocolateyInstall\lib\docfx\tools*))
{
choco install docfx
}
$env:Path += ";$env:ChocolateyInstall\lib\docfx\tools"
}
#current directory
$Here = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$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"
if(-not $env:ChocolateyInstall)
{
$env:ChocolateyInstall = "${env:ALLUSERSPROFILE}\chocolatey";
}
Install-Chocolatey
Install-Psake
Install-Git
Install-DocFx
$psakeDirectory = (Resolve-Path $env:ChocolateyInstall\lib\Psake*)
#appveyor for some reason have different location for psake (it has older psake version?)
if(Test-Path $psakeDirectory\tools\Psake\Psake.psm*)
{
Import-Module (Join-Path $psakeDirectory "tools\Psake\Psake.psm1")
}
else
{
Import-Module (Join-Path $psakeDirectory "tools\Psake.psm1")
}
#invoke the task
Invoke-Psake -buildFile "$Here\build.ps1" -parameters $properties -tasklist $Action
...@@ -203,3 +203,6 @@ FakesAssemblies/ ...@@ -203,3 +203,6 @@ FakesAssemblies/
# Visual Studio 6 workspace options file # Visual Studio 6 workspace options file
*.opt *.opt
# Docfx
docs/manifest.json
\ No newline at end of file
...@@ -6,15 +6,16 @@ A light weight HTTP(S) proxy server written in C# ...@@ -6,15 +6,16 @@ A light weight HTTP(S) proxy server written in C#
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.
([Wiki & Contribution guidelines](https://github.com/justcoding121/Titanium-Web-Proxy/wiki)) * [API Documentation](https://justcoding121.github.io/Titanium-Web-Proxy/docs/api/Titanium.Web.Proxy.ProxyServer.html)
* [Wiki & Contribution guidelines](https://github.com/justcoding121/Titanium-Web-Proxy/wiki)
**Console example application screenshot** **Console example application screenshot**
![alt tag](https://raw.githubusercontent.com/justcoding121/Titanium-Web-Proxy/develop/Examples/Titanium.Web.Proxy.Examples.Basic/Capture.PNG) ![alt tag](https://raw.githubusercontent.com/justcoding121/Titanium-Web-Proxy/master/Examples/Titanium.Web.Proxy.Examples.Basic/Capture.PNG)
**GUI example application screenshot** **GUI example application screenshot**
![alt tag](https://raw.githubusercontent.com/justcoding121/Titanium-Web-Proxy/develop/Examples/Titanium.Web.Proxy.Examples.Wpf/Capture.PNG) ![alt tag](https://raw.githubusercontent.com/justcoding121/Titanium-Web-Proxy/master/Examples/Titanium.Web.Proxy.Examples.Wpf/Capture.PNG)
### Features ### Features
......

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6FD3B84B-9283-4E9C-8C43-A234E9AA3EAA}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.Config = .nuget\NuGet.Config
.nuget\NuGet.exe = .nuget\NuGet.exe
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.Docs", "Titanium.Web.Proxy\Titanium.Web.Proxy.Docs.csproj", "{EBF2EA46-EA00-4350-BE1D-D86AFD699DB3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EBF2EA46-EA00-4350-BE1D-D86AFD699DB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBF2EA46-EA00-4350-BE1D-D86AFD699DB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBF2EA46-EA00-4350-BE1D-D86AFD699DB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBF2EA46-EA00-4350-BE1D-D86AFD699DB3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A250E1E5-3ABA-4FED-9A0E-6C63EB0261E0}
EndGlobalSection
EndGlobal
...@@ -12,7 +12,7 @@ namespace Titanium.Web.Proxy.Compression ...@@ -12,7 +12,7 @@ namespace Titanium.Web.Proxy.Compression
private static readonly ICompression gzip = new GZipCompression(); private static readonly ICompression gzip = new GZipCompression();
private static readonly ICompression deflate = new DeflateCompression(); private static readonly ICompression deflate = new DeflateCompression();
public static ICompression GetCompression(string type) internal static ICompression GetCompression(string type)
{ {
switch (type) switch (type)
{ {
......
...@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Decompression
private static readonly IDecompression deflate = new DeflateDecompression(); private static readonly IDecompression deflate = new DeflateDecompression();
public static IDecompression Create(string type) internal static IDecompression Create(string type)
{ {
switch (type) switch (type)
{ {
......
...@@ -2,5 +2,12 @@ ...@@ -2,5 +2,12 @@
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary>
/// A generic asynchronous event handler used by the proxy.
/// </summary>
/// <typeparam name="TEventArgs">Event argument type.</typeparam>
/// <param name="sender">The proxy server instance.</param>
/// <param name="e">The event arguments.</param>
/// <returns></returns>
public delegate Task AsyncEventHandler<in TEventArgs>(object sender, TEventArgs e); public delegate Task AsyncEventHandler<in TEventArgs>(object sender, TEventArgs e);
} }
...@@ -3,6 +3,9 @@ using System.Threading; ...@@ -3,6 +3,9 @@ using System.Threading;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary>
/// This is used in transparent endpoint before authenticating client.
/// </summary>
public class BeforeSslAuthenticateEventArgs : EventArgs public class BeforeSslAuthenticateEventArgs : EventArgs
{ {
internal readonly CancellationTokenSource TaskCancellationSource; internal readonly CancellationTokenSource TaskCancellationSource;
...@@ -12,10 +15,21 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -12,10 +15,21 @@ namespace Titanium.Web.Proxy.EventArguments
TaskCancellationSource = taskCancellationSource; TaskCancellationSource = taskCancellationSource;
} }
/// <summary>
/// The server name indication hostname if available. Otherwise the generic certificate hostname of TransparentEndPoint.
/// </summary>
public string SniHostName { get; internal set; } public string SniHostName { get; internal set; }
/// <summary>
/// Should we decrypt the SSL request?
/// If true we decrypt with fake certificate.
/// If false we relay the connection to the hostname mentioned in SniHostname.
/// </summary>
public bool DecryptSsl { get; set; } = true; public bool DecryptSsl { get; set; } = true;
/// <summary>
/// Terminate the request abruptly by closing client/server connections.
/// </summary>
public void TerminateSession() public void TerminateSession()
{ {
TaskCancellationSource.Cancel(); TaskCancellationSource.Cancel();
......
...@@ -4,37 +4,37 @@ using System.Security.Cryptography.X509Certificates; ...@@ -4,37 +4,37 @@ using System.Security.Cryptography.X509Certificates;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary> /// <summary>
/// An argument passed on to user for client certificate selection during mutual SSL authentication /// An argument passed on to user for client certificate selection during mutual SSL authentication.
/// </summary> /// </summary>
public class CertificateSelectionEventArgs : EventArgs public class CertificateSelectionEventArgs : EventArgs
{ {
/// <summary> /// <summary>
/// Sender object. /// The proxy server instance.
/// </summary> /// </summary>
public object Sender { get; internal set; } public object Sender { get; internal set; }
/// <summary> /// <summary>
/// Target host. /// The remote hostname to which we are authenticating against.
/// </summary> /// </summary>
public string TargetHost { get; internal set; } public string TargetHost { get; internal set; }
/// <summary> /// <summary>
/// Local certificates. /// Local certificates in store with matching issuers requested by TargetHost website.
/// </summary> /// </summary>
public X509CertificateCollection LocalCertificates { get; internal set; } public X509CertificateCollection LocalCertificates { get; internal set; }
/// <summary> /// <summary>
/// Remote certificate. /// Certificate of the remote server.
/// </summary> /// </summary>
public X509Certificate RemoteCertificate { get; internal set; } public X509Certificate RemoteCertificate { get; internal set; }
/// <summary> /// <summary>
/// Acceptable issuers. /// Acceptable issuers as listed by remoted server.
/// </summary> /// </summary>
public string[] AcceptableIssuers { get; internal set; } public string[] AcceptableIssuers { get; internal set; }
/// <summary> /// <summary>
/// Client Certificate. /// Client Certificate we selected. Set this value to override.
/// </summary> /// </summary>
public X509Certificate ClientCertificate { get; set; } public X509Certificate ClientCertificate { get; set; }
} }
......
...@@ -5,17 +5,18 @@ using System.Security.Cryptography.X509Certificates; ...@@ -5,17 +5,18 @@ using System.Security.Cryptography.X509Certificates;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary> /// <summary>
/// An argument passed on to the user for validating the server certificate during SSL authentication /// An argument passed on to the user for validating the server certificate
/// during SSL authentication.
/// </summary> /// </summary>
public class CertificateValidationEventArgs : EventArgs public class CertificateValidationEventArgs : EventArgs
{ {
/// <summary> /// <summary>
/// Certificate /// Server certificate.
/// </summary> /// </summary>
public X509Certificate Certificate { get; internal set; } public X509Certificate Certificate { get; internal set; }
/// <summary> /// <summary>
/// Certificate chain /// Certificate chain.
/// </summary> /// </summary>
public X509Chain Chain { get; internal set; } public X509Chain Chain { get; internal set; }
...@@ -25,7 +26,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -25,7 +26,7 @@ namespace Titanium.Web.Proxy.EventArguments
public SslPolicyErrors SslPolicyErrors { get; internal set; } public SslPolicyErrors SslPolicyErrors { get; internal set; }
/// <summary> /// <summary>
/// is a valid certificate? /// Is the given server certificate valid?
/// </summary> /// </summary>
public bool IsValid { get; set; } public bool IsValid { get; set; }
} }
......
...@@ -2,6 +2,9 @@ using System; ...@@ -2,6 +2,9 @@ using System;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary>
/// Wraps the data sent/received by a proxy server instance.
/// </summary>
public class DataEventArgs : EventArgs public class DataEventArgs : EventArgs
{ {
internal DataEventArgs(byte[] buffer, int offset, int count) internal DataEventArgs(byte[] buffer, int offset, int count)
...@@ -11,10 +14,19 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -11,10 +14,19 @@ namespace Titanium.Web.Proxy.EventArguments
Count = count; Count = count;
} }
/// <summary>
/// The buffer with data.
/// </summary>
public byte[] Buffer { get; } public byte[] Buffer { get; }
/// <summary>
/// Offset in buffer from which valid data begins.
/// </summary>
public int Offset { get; } public int Offset { get; }
/// <summary>
/// Length from offset in buffer with valid data.
/// </summary>
public int Count { get; } public int Count { get; }
} }
} }
...@@ -54,7 +54,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -54,7 +54,7 @@ namespace Titanium.Web.Proxy.EventArguments
readChunkTrail = true; readChunkTrail = true;
string chunkHead = baseReader.ReadLineAsync().Result; string chunkHead = baseReader.ReadLineAsync().Result;
int idx = chunkHead.IndexOf(";"); int idx = chunkHead.IndexOf(";", StringComparison.Ordinal);
if (idx >= 0) if (idx >= 0)
{ {
chunkHead = chunkHead.Substring(0, idx); chunkHead = chunkHead.Substring(0, idx);
...@@ -68,7 +68,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -68,7 +68,7 @@ namespace Titanium.Web.Proxy.EventArguments
bytesRemaining = -1; bytesRemaining = -1;
//chunk trail //chunk trail
string s = baseReader.ReadLineAsync().Result; baseReader.ReadLineAsync().Wait();
} }
} }
......
...@@ -3,16 +3,25 @@ using Titanium.Web.Proxy.Http; ...@@ -3,16 +3,25 @@ using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary>
/// Class that wraps the multipart sent request arguments.
/// </summary>
public class MultipartRequestPartSentEventArgs : EventArgs public class MultipartRequestPartSentEventArgs : EventArgs
{ {
public MultipartRequestPartSentEventArgs(string boundary, HeaderCollection headers) internal MultipartRequestPartSentEventArgs(string boundary, HeaderCollection headers)
{ {
Boundary = boundary; Boundary = boundary;
Headers = headers; Headers = headers;
} }
/// <summary>
/// Boundary.
/// </summary>
public string Boundary { get; } public string Boundary { get; }
/// <summary>
/// The header collection.
/// </summary>
public HeaderCollection Headers { get; } public HeaderCollection Headers { get; }
} }
} }
...@@ -15,10 +15,10 @@ using Titanium.Web.Proxy.Models; ...@@ -15,10 +15,10 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary> /// <summary>
/// Holds info related to a single proxy session (single request/response sequence) /// Holds info related to a single proxy session (single request/response sequence).
/// A proxy session is bounded to a single connection from client /// A proxy session is bounded to a single connection from client.
/// A proxy session ends when client terminates connection to proxy /// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy /// or when server terminates connection from proxy.
/// </summary> /// </summary>
public class SessionEventArgs : SessionEventArgsBase public class SessionEventArgs : SessionEventArgsBase
{ {
...@@ -47,7 +47,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -47,7 +47,7 @@ namespace Titanium.Web.Proxy.EventArguments
private bool hasMulipartEventSubscribers => MultipartRequestPartSent != null; private bool hasMulipartEventSubscribers => MultipartRequestPartSent != null;
/// <summary> /// <summary>
/// Should we send the request again /// Should we send the request again ?
/// </summary> /// </summary>
public bool ReRequest public bool ReRequest
{ {
...@@ -346,9 +346,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -346,9 +346,10 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Gets the request body as bytes /// Gets the request body as bytes.
/// </summary> /// </summary>
/// <returns></returns> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The body as bytes.</returns>
public async Task<byte[]> GetRequestBody(CancellationToken cancellationToken = default) public async Task<byte[]> GetRequestBody(CancellationToken cancellationToken = default)
{ {
if (!WebSession.Request.IsBodyRead) if (!WebSession.Request.IsBodyRead)
...@@ -360,9 +361,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -360,9 +361,10 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Gets the request body as string /// Gets the request body as string.
/// </summary> /// </summary>
/// <returns></returns> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The body as string.</returns>
public async Task<string> GetRequestBodyAsString(CancellationToken cancellationToken = default) public async Task<string> GetRequestBodyAsString(CancellationToken cancellationToken = default)
{ {
if (!WebSession.Request.IsBodyRead) if (!WebSession.Request.IsBodyRead)
...@@ -374,9 +376,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -374,9 +376,9 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Sets the request body /// Sets the request body.
/// </summary> /// </summary>
/// <param name="body"></param> /// <param name="body">The request body bytes.</param>
public void SetRequestBody(byte[] body) public void SetRequestBody(byte[] body)
{ {
var request = WebSession.Request; var request = WebSession.Request;
...@@ -389,9 +391,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -389,9 +391,9 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Sets the body with the specified string /// Sets the body with the specified string.
/// </summary> /// </summary>
/// <param name="body"></param> /// <param name="body">The request body string to set.</param>
public void SetRequestBodyString(string body) public void SetRequestBodyString(string body)
{ {
if (WebSession.Request.Locked) if (WebSession.Request.Locked)
...@@ -402,10 +404,12 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -402,10 +404,12 @@ namespace Titanium.Web.Proxy.EventArguments
SetRequestBody(WebSession.Request.Encoding.GetBytes(body)); SetRequestBody(WebSession.Request.Encoding.GetBytes(body));
} }
/// <summary> /// <summary>
/// Gets the response body as byte array /// Gets the response body as bytes.
/// </summary> /// </summary>
/// <returns></returns> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The resulting bytes.</returns>
public async Task<byte[]> GetResponseBody(CancellationToken cancellationToken = default) public async Task<byte[]> GetResponseBody(CancellationToken cancellationToken = default)
{ {
if (!WebSession.Response.IsBodyRead) if (!WebSession.Response.IsBodyRead)
...@@ -417,9 +421,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -417,9 +421,10 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Gets the response body as string /// Gets the response body as string.
/// </summary> /// </summary>
/// <returns></returns> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The string body.</returns>
public async Task<string> GetResponseBodyAsString(CancellationToken cancellationToken = default) public async Task<string> GetResponseBodyAsString(CancellationToken cancellationToken = default)
{ {
if (!WebSession.Response.IsBodyRead) if (!WebSession.Response.IsBodyRead)
...@@ -431,9 +436,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -431,9 +436,9 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Set the response body bytes /// Set the response body bytes.
/// </summary> /// </summary>
/// <param name="body"></param> /// <param name="body">The body bytes to set.</param>
public void SetResponseBody(byte[] body) public void SetResponseBody(byte[] body)
{ {
if (!WebSession.Request.Locked) if (!WebSession.Request.Locked)
...@@ -446,9 +451,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -446,9 +451,9 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Replace the response body with the specified string /// Replace the response body with the specified string.
/// </summary> /// </summary>
/// <param name="body"></param> /// <param name="body">The body string to set.</param>
public void SetResponseBodyString(string body) public void SetResponseBodyString(string body)
{ {
if (!WebSession.Request.Locked) if (!WebSession.Request.Locked)
...@@ -462,12 +467,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -462,12 +467,11 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Before request is made to server /// Before request is made to server respond with the specified HTML string to client
/// Respond with the specified HTML string to client /// and ignore the request.
/// and ignore the request
/// </summary> /// </summary>
/// <param name="html"></param> /// <param name="html">HTML content to sent.</param>
/// <param name="headers"></param> /// <param name="headers">HTTP response headers.</param>
public void Ok(string html, Dictionary<string, HttpHeader> headers = null) public void Ok(string html, Dictionary<string, HttpHeader> headers = null)
{ {
var response = new OkResponse(); var response = new OkResponse();
...@@ -483,12 +487,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -483,12 +487,11 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Before request is made to server /// Before request is made to server respond with the specified byte[] to client
/// Respond with the specified byte[] to client /// and ignore the request.
/// and ignore the request
/// </summary> /// </summary>
/// <param name="result"></param> /// <param name="result">The html content bytes.</param>
/// <param name="headers"></param> /// <param name="headers">The HTTP headers.</param>
public void Ok(byte[] result, Dictionary<string, HttpHeader> headers = null) public void Ok(byte[] result, Dictionary<string, HttpHeader> headers = null)
{ {
var response = new OkResponse(); var response = new OkResponse();
...@@ -501,13 +504,12 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -501,13 +504,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Before request is made to server  /// Before request is made to server 
/// Respond with the specified HTML string to client /// respond with the specified HTML string and the specified status to client.
/// and the specified status /// And then ignore the request. 
/// and ignore the request 
/// </summary> /// </summary>
/// <param name="html"></param> /// <param name="html">The html content.</param>
/// <param name="status"></param> /// <param name="status">The HTTP status code.</param>
/// <param name="headers"></param> /// <param name="headers">The HTTP headers.</param>
/// <returns></returns> /// <returns></returns>
public void GenericResponse(string html, HttpStatusCode status, Dictionary<string, HttpHeader> headers = null) public void GenericResponse(string html, HttpStatusCode status, Dictionary<string, HttpHeader> headers = null)
{ {
...@@ -520,14 +522,12 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -520,14 +522,12 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Before request is made to server /// Before request is made to server respond with the specified byte[],
/// Respond with the specified byte[] to client /// the specified status to client. And then ignore the request.
/// and the specified status
/// and ignore the request
/// </summary> /// </summary>
/// <param name="result"></param> /// <param name="result">The bytes to sent.</param>
/// <param name="status"></param> /// <param name="status">The HTTP status code.</param>
/// <param name="headers"></param> /// <param name="headers">The HTTP headers.</param>
/// <returns></returns> /// <returns></returns>
public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary<string, HttpHeader> headers) public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary<string, HttpHeader> headers)
{ {
...@@ -540,9 +540,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -540,9 +540,9 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Redirect to URL. /// Redirect to provided URL.
/// </summary> /// </summary>
/// <param name="url"></param> /// <param name="url">The URL to redirect.</param>
/// <returns></returns> /// <returns></returns>
public void Redirect(string url) public void Redirect(string url)
{ {
...@@ -554,7 +554,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -554,7 +554,10 @@ namespace Titanium.Web.Proxy.EventArguments
Respond(response); Respond(response);
} }
/// a generic responder method /// <summary>
/// Respond with given response object to client.
/// </summary>
/// <param name="response">The response object.</param>
public void Respond(Response response) public void Respond(Response response)
{ {
if (WebSession.Request.Locked) if (WebSession.Request.Locked)
...@@ -579,13 +582,16 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -579,13 +582,16 @@ namespace Titanium.Web.Proxy.EventArguments
} }
} }
/// <summary>
/// Terminate the connection to server.
/// </summary>
public void TerminateServerConnection() public void TerminateServerConnection()
{ {
WebSession.Response.TerminateResponse = true; WebSession.Response.TerminateResponse = true;
} }
/// <summary> /// <summary>
/// implement any cleanup here /// Implement any cleanup here
/// </summary> /// </summary>
public override void Dispose() public override void Dispose()
{ {
......
...@@ -9,10 +9,10 @@ using Titanium.Web.Proxy.Network; ...@@ -9,10 +9,10 @@ using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary> /// <summary>
/// Holds info related to a single proxy session (single request/response sequence) /// Holds info related to a single proxy session (single request/response sequence).
/// A proxy session is bounded to a single connection from client /// A proxy session is bounded to a single connection from client.
/// A proxy session ends when client terminates connection to proxy /// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy /// or when server terminates connection from proxy.
/// </summary> /// </summary>
public abstract class SessionEventArgsBase : EventArgs, IDisposable public abstract class SessionEventArgsBase : EventArgs, IDisposable
{ {
...@@ -73,13 +73,13 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -73,13 +73,13 @@ namespace Titanium.Web.Proxy.EventArguments
internal ProxyClient ProxyClient { get; } internal ProxyClient ProxyClient { get; }
/// <summary> /// <summary>
/// Returns a unique Id for this request/response session /// Returns a unique Id for this request/response session which is
/// same as RequestId of WebSession /// same as the RequestId of WebSession.
/// </summary> /// </summary>
public Guid Id => WebSession.RequestId; public Guid Id => WebSession.RequestId;
/// <summary> /// <summary>
/// Does this session uses SSL /// Does this session uses SSL?
/// </summary> /// </summary>
public bool IsHttps => WebSession.Request.IsHttps; public bool IsHttps => WebSession.Request.IsHttps;
...@@ -90,7 +90,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -90,7 +90,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// A web session corresponding to a single request/response sequence /// A web session corresponding to a single request/response sequence
/// within a proxy connection /// within a proxy connection.
/// </summary> /// </summary>
public HttpWebClient WebSession { get; } public HttpWebClient WebSession { get; }
...@@ -99,14 +99,23 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -99,14 +99,23 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public ExternalProxy CustomUpStreamProxyUsed { get; internal set; } public ExternalProxy CustomUpStreamProxyUsed { get; internal set; }
/// <summary>
/// Local endpoint via which we make the request.
/// </summary>
public ProxyEndPoint LocalEndPoint { get; } public ProxyEndPoint LocalEndPoint { get; }
/// <summary>
/// Is this a transparent endpoint?
/// </summary>
public bool IsTransparent => LocalEndPoint is TransparentProxyEndPoint; public bool IsTransparent => LocalEndPoint is TransparentProxyEndPoint;
/// <summary>
/// The last exception that happened.
/// </summary>
public Exception Exception { get; internal set; } public Exception Exception { get; internal set; }
/// <summary> /// <summary>
/// implement any cleanup here /// Implements cleanup here.
/// </summary> /// </summary>
public virtual void Dispose() public virtual void Dispose()
{ {
...@@ -119,8 +128,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -119,8 +128,14 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.FinishSession(); WebSession.FinishSession();
} }
/// <summary>
/// Fired when data is sent within this session to server/client.
/// </summary>
public event EventHandler<DataEventArgs> DataSent; public event EventHandler<DataEventArgs> DataSent;
/// <summary>
/// Fired when data is received within this session from client/server.
/// </summary>
public event EventHandler<DataEventArgs> DataReceived; public event EventHandler<DataEventArgs> DataReceived;
internal void OnDataSent(byte[] buffer, int offset, int count) internal void OnDataSent(byte[] buffer, int offset, int count)
...@@ -148,7 +163,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -148,7 +163,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
/// <summary> /// <summary>
/// Terminates the session abruptly by terminating client/server connections /// Terminates the session abruptly by terminating client/server connections.
/// </summary> /// </summary>
public void TerminateSession() public void TerminateSession()
{ {
......
...@@ -5,6 +5,9 @@ using Titanium.Web.Proxy.Models; ...@@ -5,6 +5,9 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary>
/// A class that wraps the state when a tunnel connect event happen for Explicit endpoints.
/// </summary>
public class TunnelConnectSessionEventArgs : SessionEventArgsBase public class TunnelConnectSessionEventArgs : SessionEventArgsBase
{ {
private bool? isHttpsConnect; private bool? isHttpsConnect;
...@@ -16,13 +19,20 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -16,13 +19,20 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.ConnectRequest = connectRequest; WebSession.ConnectRequest = connectRequest;
} }
/// <summary>
/// Should we decrypt the Ssl or relay it to server?
/// Default is true.
/// </summary>
public bool DecryptSsl { get; set; } = true; public bool DecryptSsl { get; set; } = true;
/// <summary> /// <summary>
/// Denies the connect request with a Forbidden status /// When set to true it denies the connect request with a Forbidden status.
/// </summary> /// </summary>
public bool DenyConnect { get; set; } public bool DenyConnect { get; set; }
/// <summary>
/// Is this a connect request to secure HTTP server? Or is it to someother protocol.
/// </summary>
public bool IsHttpsConnect public bool IsHttpsConnect
{ {
get => isHttpsConnect ?? throw new Exception("The value of this property is known in the BeforeTunnectConnectResponse event"); get => isHttpsConnect ?? throw new Exception("The value of this property is known in the BeforeTunnectConnectResponse event");
......
...@@ -2,5 +2,9 @@ using System; ...@@ -2,5 +2,9 @@ using System;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
/// <summary>
/// A delegate to catch exceptions occuring in proxy.
/// </summary>
/// <param name="exception">The exception occurred in proxy.</param>
public delegate void ExceptionHandler(Exception exception); public delegate void ExceptionHandler(Exception exception);
} }
namespace Titanium.Web.Proxy.Exceptions namespace Titanium.Web.Proxy.Exceptions
{ {
/// <summary> /// <summary>
/// An expception thrown when body is unexpectedly empty /// An exception thrown when body is unexpectedly empty.
/// </summary> /// </summary>
public class BodyNotFoundException : ProxyException public class BodyNotFoundException : ProxyException
{ {
......
...@@ -6,14 +6,14 @@ using Titanium.Web.Proxy.Models; ...@@ -6,14 +6,14 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Exceptions namespace Titanium.Web.Proxy.Exceptions
{ {
/// <summary> /// <summary>
/// Proxy authorization exception /// Proxy authorization exception.
/// </summary> /// </summary>
public class ProxyAuthorizationException : ProxyException public class ProxyAuthorizationException : ProxyException
{ {
/// <summary> /// <summary>
/// Instantiate new instance /// Instantiate new instance.
/// </summary> /// </summary>
/// <param name="message">Exception message</param> /// <param name="message">Exception message.</param>
/// <param name="session">The <see cref="SessionEventArgs" /> instance containing the event data.</param> /// <param name="session">The <see cref="SessionEventArgs" /> instance containing the event data.</param>
/// <param name="innerException">Inner exception associated to upstream proxy authorization</param> /// <param name="innerException">Inner exception associated to upstream proxy authorization</param>
/// <param name="headers">Http's headers associated</param> /// <param name="headers">Http's headers associated</param>
...@@ -24,10 +24,13 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -24,10 +24,13 @@ namespace Titanium.Web.Proxy.Exceptions
Headers = headers; Headers = headers;
} }
/// <summary>
/// The current session within which this error happened.
/// </summary>
public SessionEventArgsBase Session { get; } public SessionEventArgsBase Session { get; }
/// <summary> /// <summary>
/// Headers associated with the authorization exception /// Headers associated with the authorization exception.
/// </summary> /// </summary>
public IEnumerable<HttpHeader> Headers { get; } public IEnumerable<HttpHeader> Headers { get; }
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Titanium.Web.Proxy.Exceptions namespace Titanium.Web.Proxy.Exceptions
{ {
/// <summary> /// <summary>
/// Base class exception associated with this proxy implementation /// Base class exception associated with this proxy server.
/// </summary> /// </summary>
public abstract class ProxyException : Exception public abstract class ProxyException : Exception
{ {
......
...@@ -4,7 +4,7 @@ using Titanium.Web.Proxy.EventArguments; ...@@ -4,7 +4,7 @@ using Titanium.Web.Proxy.EventArguments;
namespace Titanium.Web.Proxy.Exceptions namespace Titanium.Web.Proxy.Exceptions
{ {
/// <summary> /// <summary>
/// Proxy HTTP exception /// Proxy HTTP exception.
/// </summary> /// </summary>
public class ProxyHttpException : ProxyException public class ProxyHttpException : ProxyException
{ {
...@@ -21,10 +21,10 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -21,10 +21,10 @@ namespace Titanium.Web.Proxy.Exceptions
} }
/// <summary> /// <summary>
/// Gets session info associated to the exception /// Gets session info associated to the exception.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This object should not be edited /// This object properties should not be edited.
/// </remarks> /// </remarks>
public SessionEventArgs SessionEventArgs { get; } public SessionEventArgs SessionEventArgs { get; }
} }
......
...@@ -6,14 +6,14 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -6,14 +6,14 @@ namespace Titanium.Web.Proxy.Extensions
{ {
internal static class FuncExtensions internal static class FuncExtensions
{ {
public static async Task InvokeAsync<T>(this AsyncEventHandler<T> callback, object sender, T args, internal static async Task InvokeAsync<T>(this AsyncEventHandler<T> callback, object sender, T args,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
var invocationList = callback.GetInvocationList(); var invocationList = callback.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++) foreach (var @delegate in invocationList)
{ {
await InternalInvokeAsync((AsyncEventHandler<T>)invocationList[i], sender, args, exceptionFunc); await InternalInvokeAsync((AsyncEventHandler<T>)@delegate, sender, args, exceptionFunc);
} }
} }
......
...@@ -13,9 +13,9 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -13,9 +13,9 @@ namespace Titanium.Web.Proxy.Extensions
{ {
internal static class SslExtensions internal static class SslExtensions
{ {
public static readonly List<SslApplicationProtocol> Http11ProtocolAsList = new List<SslApplicationProtocol> { SslApplicationProtocol.Http11 }; internal static readonly List<SslApplicationProtocol> Http11ProtocolAsList = new List<SslApplicationProtocol> { SslApplicationProtocol.Http11 };
public static string GetServerName(this ClientHelloInfo clientHelloInfo) internal static string GetServerName(this ClientHelloInfo clientHelloInfo)
{ {
if (clientHelloInfo.Extensions != null && if (clientHelloInfo.Extensions != null &&
clientHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension)) clientHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension))
...@@ -27,7 +27,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -27,7 +27,7 @@ namespace Titanium.Web.Proxy.Extensions
} }
#if NETCOREAPP2_1 #if NETCOREAPP2_1
public static List<SslApplicationProtocol> GetAlpn(this ClientHelloInfo clientHelloInfo) internal static List<SslApplicationProtocol> GetAlpn(this ClientHelloInfo clientHelloInfo)
{ {
if (clientHelloInfo.Extensions != null && clientHelloInfo.Extensions.TryGetValue("ALPN", out var alpnExtension)) if (clientHelloInfo.Extensions != null && clientHelloInfo.Extensions.TryGetValue("ALPN", out var alpnExtension))
{ {
...@@ -55,17 +55,17 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -55,17 +55,17 @@ namespace Titanium.Web.Proxy.Extensions
return null; return null;
} }
#else #else
public static List<SslApplicationProtocol> GetAlpn(this ClientHelloInfo clientHelloInfo) internal static List<SslApplicationProtocol> GetAlpn(this ClientHelloInfo clientHelloInfo)
{ {
return Http11ProtocolAsList; return Http11ProtocolAsList;
} }
public static Task AuthenticateAsClientAsync(this SslStream sslStream, SslClientAuthenticationOptions option, CancellationToken token) internal static Task AuthenticateAsClientAsync(this SslStream sslStream, SslClientAuthenticationOptions option, CancellationToken token)
{ {
return sslStream.AuthenticateAsClientAsync(option.TargetHost, option.ClientCertificates, option.EnabledSslProtocols, option.CertificateRevocationCheckMode != X509RevocationMode.NoCheck); return sslStream.AuthenticateAsClientAsync(option.TargetHost, option.ClientCertificates, option.EnabledSslProtocols, option.CertificateRevocationCheckMode != X509RevocationMode.NoCheck);
} }
public static Task AuthenticateAsServerAsync(this SslStream sslStream, SslServerAuthenticationOptions options, CancellationToken token) internal static Task AuthenticateAsServerAsync(this SslStream sslStream, SslServerAuthenticationOptions options, CancellationToken token)
{ {
return sslStream.AuthenticateAsServerAsync(options.ServerCertificate, options.ClientCertificateRequired, options.EnabledSslProtocols, options.CertificateRevocationCheckMode != X509RevocationMode.NoCheck); return sslStream.AuthenticateAsServerAsync(options.ServerCertificate, options.ClientCertificateRequired, options.EnabledSslProtocols, options.CertificateRevocationCheckMode != X509RevocationMode.NoCheck);
} }
...@@ -73,49 +73,49 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -73,49 +73,49 @@ namespace Titanium.Web.Proxy.Extensions
} }
#if !NETCOREAPP2_1 #if !NETCOREAPP2_1
public enum SslApplicationProtocol internal enum SslApplicationProtocol
{ {
Http11, Http2 Http11, Http2
} }
public class SslClientAuthenticationOptions internal class SslClientAuthenticationOptions
{ {
public bool AllowRenegotiation { get; set; } internal bool AllowRenegotiation { get; set; }
public string TargetHost { get; set; } internal string TargetHost { get; set; }
public X509CertificateCollection ClientCertificates { get; set; } internal X509CertificateCollection ClientCertificates { get; set; }
public LocalCertificateSelectionCallback LocalCertificateSelectionCallback { get; set; } internal LocalCertificateSelectionCallback LocalCertificateSelectionCallback { get; set; }
public SslProtocols EnabledSslProtocols { get; set; } internal SslProtocols EnabledSslProtocols { get; set; }
public X509RevocationMode CertificateRevocationCheckMode { get; set; } internal X509RevocationMode CertificateRevocationCheckMode { get; set; }
public List<SslApplicationProtocol> ApplicationProtocols { get; set; } internal List<SslApplicationProtocol> ApplicationProtocols { get; set; }
public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; } internal RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; }
public EncryptionPolicy EncryptionPolicy { get; set; } internal EncryptionPolicy EncryptionPolicy { get; set; }
} }
public class SslServerAuthenticationOptions internal class SslServerAuthenticationOptions
{ {
public bool AllowRenegotiation { get; set; } internal bool AllowRenegotiation { get; set; }
public X509Certificate ServerCertificate { get; set; } internal X509Certificate ServerCertificate { get; set; }
public bool ClientCertificateRequired { get; set; } internal bool ClientCertificateRequired { get; set; }
public SslProtocols EnabledSslProtocols { get; set; } internal SslProtocols EnabledSslProtocols { get; set; }
public X509RevocationMode CertificateRevocationCheckMode { get; set; } internal X509RevocationMode CertificateRevocationCheckMode { get; set; }
public List<SslApplicationProtocol> ApplicationProtocols { get; set; } internal List<SslApplicationProtocol> ApplicationProtocols { get; set; }
public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; } internal RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; }
public EncryptionPolicy EncryptionPolicy { get; set; } internal EncryptionPolicy EncryptionPolicy { get; set; }
} }
#endif #endif
} }
...@@ -7,18 +7,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -7,18 +7,18 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpRequestWriter : HttpWriter internal sealed class HttpRequestWriter : HttpWriter
{ {
public HttpRequestWriter(Stream stream, int bufferSize) : base(stream, bufferSize) internal HttpRequestWriter(Stream stream, int bufferSize) : base(stream, bufferSize)
{ {
} }
/// <summary> /// <summary>
/// Writes the request. /// Writes the request.
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request">The request object.</param>
/// <param name="flush"></param> /// <param name="flush">Should we flush after write?</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
public async Task WriteRequestAsync(Request request, bool flush = true, internal async Task WriteRequestAsync(Request request, bool flush = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.OriginalUrl, request.HttpVersion), await WriteLineAsync(Request.CreateRequestLine(request.Method, request.OriginalUrl, request.HttpVersion),
......
...@@ -8,18 +8,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -8,18 +8,18 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpResponseWriter : HttpWriter internal sealed class HttpResponseWriter : HttpWriter
{ {
public HttpResponseWriter(Stream stream, int bufferSize) : base(stream, bufferSize) internal HttpResponseWriter(Stream stream, int bufferSize) : base(stream, bufferSize)
{ {
} }
/// <summary> /// <summary>
/// Writes the response. /// Writes the response.
/// </summary> /// </summary>
/// <param name="response"></param> /// <param name="response">The response object.</param>
/// <param name="flush"></param> /// <param name="flush">Should we flush after write?</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns></returns> /// <returns>The Task.</returns>
public async Task WriteResponseAsync(Response response, bool flush = true, internal async Task WriteResponseAsync(Response response, bool flush = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
await WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription, await WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription,
...@@ -30,12 +30,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -30,12 +30,12 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// Write response status /// Write response status
/// </summary> /// </summary>
/// <param name="version"></param> /// <param name="version">The Http version.</param>
/// <param name="code"></param> /// <param name="code">The HTTP status code.</param>
/// <param name="description"></param> /// <param name="description">The HTTP status description.</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns></returns> /// <returns>The Task.</returns>
public Task WriteResponseStatusAsync(Version version, int code, string description, CancellationToken cancellationToken) internal Task WriteResponseStatusAsync(Version version, int code, string description, CancellationToken cancellationToken)
{ {
return WriteLineAsync(Response.CreateResponseLine(version, code, description), cancellationToken); return WriteLineAsync(Response.CreateResponseLine(version, code, description), cancellationToken);
} }
......
...@@ -27,14 +27,19 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -27,14 +27,19 @@ namespace Titanium.Web.Proxy.Helpers
charBuffer = new char[BufferSize - 1]; charBuffer = new char[BufferSize - 1];
} }
public int BufferSize { get; } internal int BufferSize { get; }
public Task WriteLineAsync(CancellationToken cancellationToken = default) /// <summary>
/// Writes a line async
/// </summary>
/// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns></returns>
internal Task WriteLineAsync(CancellationToken cancellationToken = default)
{ {
return WriteAsync(newLine, cancellationToken: cancellationToken); return WriteAsync(newLine, cancellationToken: cancellationToken);
} }
public Task WriteAsync(string value, CancellationToken cancellationToken = default) internal Task WriteAsync(string value, CancellationToken cancellationToken = default)
{ {
return WriteAsyncInternal(value, false, cancellationToken); return WriteAsyncInternal(value, false, cancellationToken);
} }
...@@ -81,7 +86,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -81,7 +86,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
public Task WriteLineAsync(string value, CancellationToken cancellationToken = default) internal Task WriteLineAsync(string value, CancellationToken cancellationToken = default)
{ {
return WriteAsyncInternal(value, true, cancellationToken); return WriteAsyncInternal(value, true, cancellationToken);
} }
...@@ -93,7 +98,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -93,7 +98,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="flush"></param> /// <param name="flush"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public async Task WriteHeadersAsync(HeaderCollection headers, bool flush = true, CancellationToken cancellationToken = default) internal async Task WriteHeadersAsync(HeaderCollection headers, bool flush = true, CancellationToken cancellationToken = default)
{ {
foreach (var header in headers) foreach (var header in headers)
{ {
...@@ -107,7 +112,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -107,7 +112,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
public async Task WriteAsync(byte[] data, bool flush = false, CancellationToken cancellationToken = default) internal async Task WriteAsync(byte[] data, bool flush = false, CancellationToken cancellationToken = default)
{ {
await WriteAsync(data, 0, data.Length, cancellationToken); await WriteAsync(data, 0, data.Length, cancellationToken);
if (flush) if (flush)
...@@ -116,7 +121,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -116,7 +121,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
public async Task WriteAsync(byte[] data, int offset, int count, bool flush, CancellationToken cancellationToken = default) internal async Task WriteAsync(byte[] data, int offset, int count, bool flush, CancellationToken cancellationToken = default)
{ {
await WriteAsync(data, offset, count, cancellationToken); await WriteAsync(data, offset, count, cancellationToken);
if (flush) if (flush)
......
...@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal class ProxyInfo internal class ProxyInfo
{ {
public ProxyInfo(bool? autoDetect, string autoConfigUrl, int? proxyEnable, string proxyServer, internal ProxyInfo(bool? autoDetect, string autoConfigUrl, int? proxyEnable, string proxyServer,
string proxyOverride) string proxyOverride)
{ {
AutoDetect = autoDetect; AutoDetect = autoDetect;
...@@ -51,23 +51,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -51,23 +51,23 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
public bool? AutoDetect { get; } internal bool? AutoDetect { get; }
public string AutoConfigUrl { get; } internal string AutoConfigUrl { get; }
public int? ProxyEnable { get; } internal int? ProxyEnable { get; }
public string ProxyServer { get; } internal string ProxyServer { get; }
public string ProxyOverride { get; } internal string ProxyOverride { get; }
public bool BypassLoopback { get; } internal bool BypassLoopback { get; }
public bool BypassOnLocal { get; } internal bool BypassOnLocal { get; }
public Dictionary<ProxyProtocolType, HttpSystemProxyValue> Proxies { get; } internal Dictionary<ProxyProtocolType, HttpSystemProxyValue> Proxies { get; }
public string[] BypassList { get; } internal string[] BypassList { get; }
private static string BypassStringEscape(string rawString) private static string BypassStringEscape(string rawString)
{ {
...@@ -131,7 +131,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -131,7 +131,7 @@ namespace Titanium.Web.Proxy.Helpers
return stringBuilder.ToString(); return stringBuilder.ToString();
} }
public static ProxyProtocolType? ParseProtocolType(string protocolTypeStr) internal static ProxyProtocolType? ParseProtocolType(string protocolTypeStr)
{ {
if (protocolTypeStr == null) if (protocolTypeStr == null)
{ {
...@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="proxyServerValues"></param> /// <param name="proxyServerValues"></param>
/// <returns></returns> /// <returns></returns>
public static List<HttpSystemProxyValue> GetSystemProxyValues(string proxyServerValues) internal static List<HttpSystemProxyValue> GetSystemProxyValues(string proxyServerValues)
{ {
var result = new List<HttpSystemProxyValue>(); var result = new List<HttpSystemProxyValue>();
......
...@@ -6,18 +6,18 @@ using System.Threading.Tasks; ...@@ -6,18 +6,18 @@ using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
public class Ref<T> internal class Ref<T>
{ {
public Ref() internal Ref()
{ {
} }
public Ref(T value) internal Ref(T value)
{ {
Value = value; Value = value;
} }
public T Value { get; set; } internal T Value { get; set; }
public override string ToString() public override string ToString()
{ {
......
...@@ -27,12 +27,12 @@ namespace Titanium.Web.Proxy.Http ...@@ -27,12 +27,12 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary> /// <summary>
/// Unique Request header collection /// Unique Request header collection.
/// </summary> /// </summary>
public ReadOnlyDictionary<string, HttpHeader> Headers { get; } public ReadOnlyDictionary<string, HttpHeader> Headers { get; }
/// <summary> /// <summary>
/// Non Unique headers /// Non Unique headers.
/// </summary> /// </summary>
public ReadOnlyDictionary<string, List<HttpHeader>> NonUniqueHeaders { get; } public ReadOnlyDictionary<string, List<HttpHeader>> NonUniqueHeaders { get; }
......
...@@ -15,12 +15,12 @@ namespace Titanium.Web.Proxy.Http ...@@ -15,12 +15,12 @@ namespace Titanium.Web.Proxy.Http
public class Request : RequestResponseBase public class Request : RequestResponseBase
{ {
/// <summary> /// <summary>
/// Request Method /// Request Method.
/// </summary> /// </summary>
public string Method { get; set; } public string Method { get; set; }
/// <summary> /// <summary>
/// Request HTTP Uri /// Request HTTP Uri.
/// </summary> /// </summary>
public Uri RequestUri { get; set; } public Uri RequestUri { get; set; }
...@@ -66,9 +66,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -66,9 +66,9 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary> /// <summary>
/// Http hostname header value if exists /// Http hostname header value if exists.
/// Note: Changing this does NOT change host in RequestUri /// Note: Changing this does NOT change host in RequestUri.
/// Users can set new RequestUri separately /// Users can set new RequestUri separately.
/// </summary> /// </summary>
public string Host public string Host
{ {
...@@ -88,15 +88,18 @@ namespace Titanium.Web.Proxy.Http ...@@ -88,15 +88,18 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// Does this request contain multipart/form-data?
/// </summary>
public bool IsMultipartFormData => ContentType?.StartsWith("multipart/form-data") == true; public bool IsMultipartFormData => ContentType?.StartsWith("multipart/form-data") == true;
/// <summary> /// <summary>
/// Request Url /// Request Url.
/// </summary> /// </summary>
public string Url => RequestUri.OriginalString; public string Url => RequestUri.OriginalString;
/// <summary> /// <summary>
/// Terminates the underlying Tcp Connection to client after current request /// Terminates the underlying Tcp Connection to client after current request.
/// </summary> /// </summary>
internal bool CancelRequest { get; set; } internal bool CancelRequest { get; set; }
...@@ -119,12 +122,12 @@ namespace Titanium.Web.Proxy.Http ...@@ -119,12 +122,12 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary> /// <summary>
/// Does server responsed positively for 100 continue request /// Did server responsed positively for 100 continue request?
/// </summary> /// </summary>
public bool Is100Continue { get; internal set; } public bool Is100Continue { get; internal set; }
/// <summary> /// <summary>
/// Server responsed negatively for the request for 100 continue /// Did server responsed negatively for the request for 100 continue?
/// </summary> /// </summary>
public bool ExpectationFailed { get; internal set; } public bool ExpectationFailed { get; internal set; }
......
...@@ -12,12 +12,12 @@ namespace Titanium.Web.Proxy.Http ...@@ -12,12 +12,12 @@ namespace Titanium.Web.Proxy.Http
public abstract class RequestResponseBase public abstract class RequestResponseBase
{ {
/// <summary> /// <summary>
/// Cached body content as byte array /// Cached body content as byte array.
/// </summary> /// </summary>
protected byte[] BodyInternal; protected byte[] BodyInternal;
/// <summary> /// <summary>
/// Cached body as string /// Cached body as string.
/// </summary> /// </summary>
private string bodyString; private string bodyString;
...@@ -27,22 +27,22 @@ namespace Titanium.Web.Proxy.Http ...@@ -27,22 +27,22 @@ namespace Titanium.Web.Proxy.Http
internal bool OriginalHasBody; internal bool OriginalHasBody;
/// <summary> /// <summary>
/// Keeps the body data after the session is finished /// Keeps the body data after the session is finished.
/// </summary> /// </summary>
public bool KeepBody { get; set; } public bool KeepBody { get; set; }
/// <summary> /// <summary>
/// Http Version /// Http Version.
/// </summary> /// </summary>
public Version HttpVersion { get; set; } = HttpHeader.VersionUnknown; public Version HttpVersion { get; set; } = HttpHeader.VersionUnknown;
/// <summary> /// <summary>
/// Collection of all headers /// Collection of all headers.
/// </summary> /// </summary>
public HeaderCollection Headers { get; } = new HeaderCollection(); public HeaderCollection Headers { get; } = new HeaderCollection();
/// <summary> /// <summary>
/// Length of the body /// Length of the body.
/// </summary> /// </summary>
public long ContentLength public long ContentLength
{ {
...@@ -77,17 +77,17 @@ namespace Titanium.Web.Proxy.Http ...@@ -77,17 +77,17 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary> /// <summary>
/// Content encoding for this request/response /// Content encoding for this request/response.
/// </summary> /// </summary>
public string ContentEncoding => Headers.GetHeaderValueOrNull(KnownHeaders.ContentEncoding)?.Trim(); public string ContentEncoding => Headers.GetHeaderValueOrNull(KnownHeaders.ContentEncoding)?.Trim();
/// <summary> /// <summary>
/// Encoding for this request/response /// Encoding for this request/response.
/// </summary> /// </summary>
public Encoding Encoding => HttpHelper.GetEncodingFromContentType(ContentType); public Encoding Encoding => HttpHelper.GetEncodingFromContentType(ContentType);
/// <summary> /// <summary>
/// Content-type of the request/response /// Content-type of the request/response.
/// </summary> /// </summary>
public string ContentType public string ContentType
{ {
...@@ -96,7 +96,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -96,7 +96,7 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary> /// <summary>
/// Is body send as chunked bytes /// Is body send as chunked bytes.
/// </summary> /// </summary>
public bool IsChunked public bool IsChunked
{ {
...@@ -119,6 +119,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -119,6 +119,9 @@ namespace Titanium.Web.Proxy.Http
} }
} }
/// <summary>
/// The header text.
/// </summary>
public abstract string HeaderText { get; } public abstract string HeaderText { get; }
/// <summary> /// <summary>
...@@ -148,7 +151,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -148,7 +151,7 @@ namespace Titanium.Web.Proxy.Http
public abstract bool HasBody { get; } public abstract bool HasBody { get; }
/// <summary> /// <summary>
/// Body as string /// Body as string.
/// Use the encoding specified to decode the byte[] data to string /// Use the encoding specified to decode the byte[] data to string
/// </summary> /// </summary>
[Browsable(false)] [Browsable(false)]
......
...@@ -7,17 +7,17 @@ using Titanium.Web.Proxy.Extensions; ...@@ -7,17 +7,17 @@ using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
{ {
/// <summary> /// <summary>
/// A proxy endpoint that the client is aware of /// A proxy endpoint that the client is aware of.
/// So client application know that it is communicating with a proxy server /// So client application know that it is communicating with a proxy server.
/// </summary> /// </summary>
public class ExplicitProxyEndPoint : ProxyEndPoint public class ExplicitProxyEndPoint : ProxyEndPoint
{ {
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
/// <param name="ipAddress"></param> /// <param name="ipAddress">Listening IP address.</param>
/// <param name="port"></param> /// <param name="port">Listening port.</param>
/// <param name="decryptSsl"></param> /// <param name="decryptSsl">Should we decrypt ssl?</param>
public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) : base(ipAddress, port, public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) : base(ipAddress, port,
decryptSsl) decryptSsl)
{ {
...@@ -33,16 +33,16 @@ namespace Titanium.Web.Proxy.Models ...@@ -33,16 +33,16 @@ namespace Titanium.Web.Proxy.Models
public X509Certificate2 GenericCertificate { get; set; } public X509Certificate2 GenericCertificate { get; set; }
/// <summary> /// <summary>
/// Intercept tunnel connect request /// Intercept tunnel connect request.
/// Valid only for explicit endpoints /// Valid only for explicit endpoints.
/// Set the <see cref="TunnelConnectSessionEventArgs.DecryptSsl" /> property to false if this HTTP connect request /// Set the <see cref="TunnelConnectSessionEventArgs.DecryptSsl" /> property to false if this HTTP connect request
/// should'nt be decrypted and instead be relayed /// should'nt be decrypted and instead be relayed.
/// </summary> /// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest; public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest;
/// <summary> /// <summary>
/// Intercept tunnel connect response /// Intercept tunnel connect response.
/// Valid only for explicit endpoints /// Valid only for explicit endpoints.
/// </summary> /// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectResponse; public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectResponse;
......
...@@ -4,7 +4,7 @@ using System.Net; ...@@ -4,7 +4,7 @@ using System.Net;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
{ {
/// <summary> /// <summary>
/// An upstream proxy this proxy uses if any /// An upstream proxy this proxy uses if any.
/// </summary> /// </summary>
public class ExternalProxy public class ExternalProxy
{ {
...@@ -69,6 +69,10 @@ namespace Titanium.Web.Proxy.Models ...@@ -69,6 +69,10 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public int Port { get; set; } public int Port { get; set; }
/// <summary>
/// returns data in Hostname:port format.
/// </summary>
/// <returns></returns>
public override string ToString() public override string ToString()
{ {
return $"{HostName}:{Port}"; return $"{HostName}:{Port}";
......
...@@ -22,12 +22,11 @@ namespace Titanium.Web.Proxy.Models ...@@ -22,12 +22,11 @@ namespace Titanium.Web.Proxy.Models
internal static readonly HttpHeader ProxyConnectionKeepAlive = new HttpHeader("Proxy-Connection", "keep-alive"); internal static readonly HttpHeader ProxyConnectionKeepAlive = new HttpHeader("Proxy-Connection", "keep-alive");
/// <summary> /// <summary>
/// Constructor. /// Initialize a new instance.
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name">Header name.</param>
/// <param name="value"></param> /// <param name="value">Header value.</param>
/// <exception cref="Exception"></exception>
public HttpHeader(string name, string value) public HttpHeader(string name, string value)
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
...@@ -50,7 +49,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -50,7 +49,7 @@ namespace Titanium.Web.Proxy.Models
public string Value { get; set; } public string Value { get; set; }
/// <summary> /// <summary>
/// Returns header as a valid header string /// Returns header as a valid header string.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public override string ToString() public override string ToString()
......
...@@ -6,17 +6,17 @@ using Titanium.Web.Proxy.Extensions; ...@@ -6,17 +6,17 @@ using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
{ {
/// <summary> /// <summary>
/// A proxy end point client is not aware of /// A proxy end point client is not aware of.
/// Usefull when requests are redirected to this proxy end point through port forwarding /// Useful when requests are redirected to this proxy end point through port forwarding via router.
/// </summary> /// </summary>
public class TransparentProxyEndPoint : ProxyEndPoint public class TransparentProxyEndPoint : ProxyEndPoint
{ {
/// <summary> /// <summary>
/// Constructor. /// Initialize a new instance.
/// </summary> /// </summary>
/// <param name="ipAddress"></param> /// <param name="ipAddress">Listening Ip address.</param>
/// <param name="port"></param> /// <param name="port">Listening port.</param>
/// <param name="decryptSsl"></param> /// <param name="decryptSsl">Should we decrypt ssl?</param>
public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) : base(ipAddress, port, public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) : base(ipAddress, port,
decryptSsl) decryptSsl)
{ {
...@@ -24,13 +24,13 @@ namespace Titanium.Web.Proxy.Models ...@@ -24,13 +24,13 @@ namespace Titanium.Web.Proxy.Models
} }
/// <summary> /// <summary>
/// Name of the Certificate need to be sent (same as the hostname we want to proxy) /// Name of the Certificate need to be sent (same as the hostname we want to proxy).
/// This is valid only when UseServerNameIndication is set to false /// This is valid only when UseServerNameIndication is set to false.
/// </summary> /// </summary>
public string GenericCertificateName { get; set; } public string GenericCertificateName { get; set; }
/// <summary> /// <summary>
/// Before Ssl authentication /// Before Ssl authentication this event is fired.
/// </summary> /// </summary>
public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate; public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate;
......
...@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth ...@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// NTLM process details below /// NTLM process details below
/// https://blogs.msdn.microsoft.com/chiranth/2013/09/20/ntlm-want-to-know-how-it-works/ /// https://blogs.msdn.microsoft.com/chiranth/2013/09/20/ntlm-want-to-know-how-it-works/
/// </summary> /// </summary>
public static class WinAuthHandler internal static class WinAuthHandler
{ {
/// <summary> /// <summary>
/// Get the initial client token for server /// Get the initial client token for server
...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth ...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// <param name="authScheme"></param> /// <param name="authScheme"></param>
/// <param name="requestId"></param> /// <param name="requestId"></param>
/// <returns></returns> /// <returns></returns>
public static string GetInitialAuthToken(string serverHostname, string authScheme, Guid requestId) internal static string GetInitialAuthToken(string serverHostname, string authScheme, Guid requestId)
{ {
var tokenBytes = WinAuthEndPoint.AcquireInitialSecurityToken(serverHostname, authScheme, requestId); var tokenBytes = WinAuthEndPoint.AcquireInitialSecurityToken(serverHostname, authScheme, requestId);
return string.Concat(" ", Convert.ToBase64String(tokenBytes)); return string.Concat(" ", Convert.ToBase64String(tokenBytes));
...@@ -32,7 +32,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth ...@@ -32,7 +32,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// <param name="serverToken"></param> /// <param name="serverToken"></param>
/// <param name="requestId"></param> /// <param name="requestId"></param>
/// <returns></returns> /// <returns></returns>
public static string GetFinalAuthToken(string serverHostname, string serverToken, Guid requestId) internal static string GetFinalAuthToken(string serverHostname, string serverToken, Guid requestId)
{ {
var tokenBytes = var tokenBytes =
WinAuthEndPoint.AcquireFinalSecurityToken(serverHostname, Convert.FromBase64String(serverToken), WinAuthEndPoint.AcquireFinalSecurityToken(serverHostname, Convert.FromBase64String(serverToken),
......
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.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>{EBF2EA46-EA00-4350-BE1D-D86AFD699DB3}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Titanium.Web.Proxy</RootNamespace>
<AssemblyName>Titanium.Web.Proxy</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</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>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Titanium.Web.Proxy.xml</DocumentationFile>
<LangVersion>latest</LangVersion>
</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="BouncyCastle.Crypto, Version=1.8.2.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
<HintPath>..\packages\Portable.BouncyCastle.1.8.2\lib\net40\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="StreamExtended, Version=1.0.147.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\packages\StreamExtended.1.0.147-beta\lib\net45\StreamExtended.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<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="CertificateHandler.cs" />
<Compile Include="Compression\CompressionFactory.cs" />
<Compile Include="Compression\DeflateCompression.cs" />
<Compile Include="Compression\GZipCompression.cs" />
<Compile Include="Compression\ICompression.cs" />
<Compile Include="Decompression\DecompressionFactory.cs" />
<Compile Include="Decompression\DeflateDecompression.cs" />
<Compile Include="Decompression\GZipDecompression.cs" />
<Compile Include="Decompression\IDecompression.cs" />
<Compile Include="EventArguments\AsyncEventHandler.cs" />
<Compile Include="EventArguments\BeforeSslAuthenticateEventArgs.cs" />
<Compile Include="EventArguments\CertificateSelectionEventArgs.cs" />
<Compile Include="EventArguments\CertificateValidationEventArgs.cs" />
<Compile Include="EventArguments\DataEventArgs.cs" />
<Compile Include="EventArguments\LimitedStream.cs" />
<Compile Include="EventArguments\MultipartRequestPartSentEventArgs.cs" />
<Compile Include="EventArguments\SessionEventArgs.cs" />
<Compile Include="EventArguments\SessionEventArgsBase.cs" />
<Compile Include="EventArguments\TransformationMode.cs" />
<Compile Include="EventArguments\TunnelConnectEventArgs.cs" />
<Compile Include="ExceptionHandler.cs" />
<Compile Include="Exceptions\BodyNotFoundException.cs" />
<Compile Include="Exceptions\ProxyAuthorizationException.cs" />
<Compile Include="Exceptions\ProxyException.cs" />
<Compile Include="Exceptions\ProxyHttpException.cs" />
<Compile Include="ExplicitClientHandler.cs" />
<Compile Include="Extensions\FuncExtensions.cs" />
<Compile Include="Extensions\SslExtensions.cs" />
<Compile Include="Extensions\StreamExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Extensions\TcpExtensions.cs" />
<Compile Include="Helpers\HttpHelper.cs" />
<Compile Include="Helpers\HttpRequestWriter.cs" />
<Compile Include="Helpers\HttpResponseWriter.cs" />
<Compile Include="Helpers\HttpWriter.cs" />
<Compile Include="Helpers\NativeMethods.SystemProxy.cs" />
<Compile Include="Helpers\NativeMethods.Tcp.cs" />
<Compile Include="Helpers\Network.cs" />
<Compile Include="Helpers\ProxyInfo.cs" />
<Compile Include="Helpers\Ref.cs" />
<Compile Include="Helpers\RunTime.cs" />
<Compile Include="Helpers\SystemProxy.cs" />
<Compile Include="Helpers\Tcp.cs" />
<Compile Include="Helpers\WinHttp\NativeMethods.WinHttp.cs" />
<Compile Include="Helpers\WinHttp\WinHttpHandle.cs" />
<Compile Include="Helpers\WinHttp\WinHttpWebProxyFinder.cs" />
<Compile Include="Http\ConnectRequest.cs" />
<Compile Include="Http\ConnectResponse.cs" />
<Compile Include="Http\HeaderCollection.cs" />
<Compile Include="Http\HeaderParser.cs" />
<Compile Include="Http\HttpWebClient.cs" />
<Compile Include="Http\KnownHeaders.cs" />
<Compile Include="Http\Request.cs" />
<Compile Include="Http\RequestResponseBase.cs" />
<Compile Include="Http\Response.cs" />
<Compile Include="Http\Responses\GenericResponse.cs" />
<Compile Include="Http\Responses\OkResponse.cs" />
<Compile Include="Http\Responses\RedirectResponse.cs" />
<Compile Include="Models\ExplicitProxyEndPoint.cs" />
<Compile Include="Models\ExternalProxy.cs" />
<Compile Include="Models\HttpHeader.cs" />
<Compile Include="Models\ProxyEndPoint.cs" />
<Compile Include="Models\TransparentProxyEndPoint.cs" />
<Compile Include="Network\CachedCertificate.cs" />
<Compile Include="Network\CertificateManager.cs" />
<Compile Include="Network\Certificate\BCCertificateMaker.cs" />
<Compile Include="Network\Certificate\ICertificateMaker.cs" />
<Compile Include="Network\Certificate\WinCertificateMaker.cs" />
<Compile Include="Network\DebugCustomBufferedStream.cs" />
<Compile Include="Network\ProxyClient.cs" />
<Compile Include="Network\Tcp\TcpConnection.cs" />
<Compile Include="Network\Tcp\TcpConnectionFactory.cs" />
<Compile Include="Network\WinAuth\Security\Common.cs" />
<Compile Include="Network\WinAuth\Security\LittleEndian.cs" />
<Compile Include="Network\WinAuth\Security\Message.cs" />
<Compile Include="Network\WinAuth\Security\State.cs" />
<Compile Include="Network\WinAuth\Security\WinAuthEndPoint.cs" />
<Compile Include="Network\WinAuth\WinAuthHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ProxyAuthorizationHandler.cs" />
<Compile Include="ProxyServer.cs" />
<Compile Include="RequestHandler.cs" />
<Compile Include="ResponseHandler.cs" />
<Compile Include="Shared\ProxyConstants.cs" />
<Compile Include="TransparentClientHandler.cs" />
<Compile Include="WinAuthHandler.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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
baseurl: /Titanium-Web-Proxy
...@@ -24,7 +24,7 @@ configuration: Release ...@@ -24,7 +24,7 @@ configuration: Release
# to run your custom scripts instead of automatic MSBuild # to run your custom scripts instead of automatic MSBuild
build_script: build_script:
- cmd: .\build.bat Package - cmd: build.bat Package
assembly_info: assembly_info:
patch: true patch: true
...@@ -39,7 +39,9 @@ test: on ...@@ -39,7 +39,9 @@ test: on
# skip building commits that add tags (such as release tag) # skip building commits that add tags (such as release tag)
skip_tags: true skip_tags: true
skip_commits:
author: buildbot121
#---------------------------------# #---------------------------------#
# artifacts configuration # # artifacts configuration #
#---------------------------------# #---------------------------------#
...@@ -50,14 +52,19 @@ nuget: ...@@ -50,14 +52,19 @@ nuget:
artifacts: artifacts:
- path: '**\Titanium.Web.Proxy.*.nupkg' - path: '**\Titanium.Web.Proxy.*.nupkg'
environment:
github_access_token:
secure: BGdKiI7FwHGkFt+/OmgZDkE1hzLqLrTxcc9c+joVqGyO4LvesHb1sR6hzisVwVPm
github_email:
secure: wvYod3JLufbIBkavRXlCP724wJkhqR2RRuLLaPnqfps=
nuget_access_token:
secure: ZbRmjOcp+TDllRV1wxqLZjdRV7hld388rXlWVJuGGiQleomP9Ku+Nsy3a75E7/9k
deploy: deploy:
- provider: GitHub - provider: GitHub
auth_token: auth_token: $(github_access_token)
secure: ItVm+50ASpDXx1w+FCe2NTpZxqCbjRWfugLjk/bqBIi00DvPnSGOV1rIQ5hnwBW3
on: on:
branch: /(stable|beta)/ branch: /(stable|beta)/
- provider: NuGet - provider: NuGet
api_key: api_key: $(nuget_access_token)
secure: ZbRmjOcp+TDllRV1wxqLZjdRV7hld388rXlWVJuGGiQleomP9Ku+Nsy3a75E7/9k
on: on:
branch: /(stable|beta)/ branch: /(stable|beta)/
@echo off @echo off
if '%1'=='/?' goto help powershell -NoProfile -ExecutionPolicy bypass -Command "%~dp0.build\setup.ps1 %*; if ($psake.build_success -eq $false) { exit 1 } else { exit 0 }"
if '%1'=='-help' goto help exit /B %errorlevel%
if '%1'=='-h' goto help \ No newline at end of file
powershell -NoProfile -ExecutionPolicy bypass -Command "%~dp0.build\bootstrap.ps1 %*; if ($psake.build_success -eq $false) { exit 1 } else { exit 0 }"
exit /B %errorlevel%
:help
powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0.build\bootstrap.ps1' -help"
\ No newline at end of file
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Delegate AsyncEventHandler&lt;TEventArgs&gt;
| Titanium Web Proxy </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Delegate AsyncEventHandler&lt;TEventArgs&gt;
| Titanium Web Proxy ">
<meta name="generator" content="docfx 2.35.2.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="">
<meta property="docfx:tocrel" content="toc.html">
<meta property="docfx:rel" content="../">
</head>
<body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div class="container body-content">
<div id="search-results">
<div class="search-list"></div>
<div class="sr-items">
<p><i class="glyphicon glyphicon-refresh index-loading"></i></p>
</div>
<ul id="pagination"></ul>
</div>
</div>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="Titanium.Web.Proxy.EventArguments.AsyncEventHandler`1">
<h1 id="Titanium_Web_Proxy_EventArguments_AsyncEventHandler_1" data-uid="Titanium.Web.Proxy.EventArguments.AsyncEventHandler`1" class="text-break">Delegate AsyncEventHandler&lt;TEventArgs&gt;
</h1>
<div class="markdown level0 summary"><p>A generic asynchronous event handler used by the proxy.</p>
</div>
<div class="markdown level0 conceptual"></div>
<h6><strong>Namespace</strong>: <a class="xref" href="Titanium.Web.Proxy.EventArguments.html">Titanium.Web.Proxy.EventArguments</a></h6>
<h6><strong>Assembly</strong>: Titanium.Web.Proxy.dll</h6>
<h5 id="Titanium_Web_Proxy_EventArguments_AsyncEventHandler_1_syntax">Syntax</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public delegate Task AsyncEventHandler&lt;in TEventArgs&gt;(object sender, TEventArgs e);</code></pre>
</div>
<h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object">Object</a></td>
<td><span class="parametername">sender</span></td>
<td><p>The proxy server instance.</p>
</td>
</tr>
<tr>
<td><span class="xref">TEventArgs</span></td>
<td><span class="parametername">e</span></td>
<td><p>The event arguments.</p>
</td>
</tr>
</tbody>
</table>
<h5 class="returns">Returns</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.threading.tasks.task">Task</a></td>
<td></td>
</tr>
</tbody>
</table>
<h5 class="typeParameters">Type Parameters</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="parametername">TEventArgs</span></td>
<td><p>Event argument type.</p>
</td>
</tr>
</tbody>
</table>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Class DataEventArgs
| Titanium Web Proxy </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Class DataEventArgs
| Titanium Web Proxy ">
<meta name="generator" content="docfx 2.35.2.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="">
<meta property="docfx:tocrel" content="toc.html">
<meta property="docfx:rel" content="../">
</head>
<body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div class="container body-content">
<div id="search-results">
<div class="search-list"></div>
<div class="sr-items">
<p><i class="glyphicon glyphicon-refresh index-loading"></i></p>
</div>
<ul id="pagination"></ul>
</div>
</div>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs">
<h1 id="Titanium_Web_Proxy_EventArguments_DataEventArgs" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs" class="text-break">Class DataEventArgs
</h1>
<div class="markdown level0 summary"><p>Wraps the data sent/received by a proxy server instance.</p>
</div>
<div class="markdown level0 conceptual"></div>
<div class="inheritance">
<h5>Inheritance</h5>
<div class="level0"><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object">Object</a></div>
<div class="level1"><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventargs">EventArgs</a></div>
<div class="level2"><span class="xref">DataEventArgs</span></div>
</div>
<div class="inheritedMembers">
<h5>Inherited Members</h5>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventargs.empty">EventArgs.Empty</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.tostring#System_Object_ToString">Object.ToString()</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.equals#System_Object_Equals_System_Object_">Object.Equals(Object)</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.equals#System_Object_Equals_System_Object_System_Object_">Object.Equals(Object, Object)</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.referenceequals#System_Object_ReferenceEquals_System_Object_System_Object_">Object.ReferenceEquals(Object, Object)</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.gethashcode#System_Object_GetHashCode">Object.GetHashCode()</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.gettype#System_Object_GetType">Object.GetType()</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.memberwiseclone#System_Object_MemberwiseClone">Object.MemberwiseClone()</a>
</div>
</div>
<h6><strong>Namespace</strong>: <a class="xref" href="Titanium.Web.Proxy.EventArguments.html">Titanium.Web.Proxy.EventArguments</a></h6>
<h6><strong>Assembly</strong>: Titanium.Web.Proxy.dll</h6>
<h5 id="Titanium_Web_Proxy_EventArguments_DataEventArgs_syntax">Syntax</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public class DataEventArgs : EventArgs</code></pre>
</div>
<h3 id="properties">Properties
</h3>
<a id="Titanium_Web_Proxy_EventArguments_DataEventArgs_Buffer_" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_DataEventArgs_Buffer" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer">Buffer</h4>
<div class="markdown level1 summary"><p>The buffer with data.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public byte[] Buffer { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="xref">System.Byte</span>[]</td>
<td></td>
</tr>
</tbody>
</table>
<a id="Titanium_Web_Proxy_EventArguments_DataEventArgs_Count_" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs.Count*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_DataEventArgs_Count" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs.Count">Count</h4>
<div class="markdown level1 summary"><p>Length from offset in buffer with valid data.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public int Count { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td></td>
</tr>
</tbody>
</table>
<a id="Titanium_Web_Proxy_EventArguments_DataEventArgs_Offset_" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_DataEventArgs_Offset" data-uid="Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset">Offset</h4>
<div class="markdown level1 summary"><p>Offset in buffer from which valid data begins.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public int Offset { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td></td>
</tr>
</tbody>
</table>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Class MultipartRequestPartSentEventArgs
| Titanium Web Proxy </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Class MultipartRequestPartSentEventArgs
| Titanium Web Proxy ">
<meta name="generator" content="docfx 2.35.2.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="">
<meta property="docfx:tocrel" content="toc.html">
<meta property="docfx:rel" content="../">
</head>
<body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div class="container body-content">
<div id="search-results">
<div class="search-list"></div>
<div class="sr-items">
<p><i class="glyphicon glyphicon-refresh index-loading"></i></p>
</div>
<ul id="pagination"></ul>
</div>
</div>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs">
<h1 id="Titanium_Web_Proxy_EventArguments_MultipartRequestPartSentEventArgs" data-uid="Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs" class="text-break">Class MultipartRequestPartSentEventArgs
</h1>
<div class="markdown level0 summary"><p>Class that wraps the multipart sent request arguments.</p>
</div>
<div class="markdown level0 conceptual"></div>
<div class="inheritance">
<h5>Inheritance</h5>
<div class="level0"><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object">Object</a></div>
<div class="level1"><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventargs">EventArgs</a></div>
<div class="level2"><span class="xref">MultipartRequestPartSentEventArgs</span></div>
</div>
<div class="inheritedMembers">
<h5>Inherited Members</h5>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventargs.empty">EventArgs.Empty</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.tostring#System_Object_ToString">Object.ToString()</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.equals#System_Object_Equals_System_Object_">Object.Equals(Object)</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.equals#System_Object_Equals_System_Object_System_Object_">Object.Equals(Object, Object)</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.referenceequals#System_Object_ReferenceEquals_System_Object_System_Object_">Object.ReferenceEquals(Object, Object)</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.gethashcode#System_Object_GetHashCode">Object.GetHashCode()</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.gettype#System_Object_GetType">Object.GetType()</a>
</div>
<div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.object.memberwiseclone#System_Object_MemberwiseClone">Object.MemberwiseClone()</a>
</div>
</div>
<h6><strong>Namespace</strong>: <a class="xref" href="Titanium.Web.Proxy.EventArguments.html">Titanium.Web.Proxy.EventArguments</a></h6>
<h6><strong>Assembly</strong>: Titanium.Web.Proxy.dll</h6>
<h5 id="Titanium_Web_Proxy_EventArguments_MultipartRequestPartSentEventArgs_syntax">Syntax</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public class MultipartRequestPartSentEventArgs : EventArgs</code></pre>
</div>
<h3 id="properties">Properties
</h3>
<a id="Titanium_Web_Proxy_EventArguments_MultipartRequestPartSentEventArgs_Boundary_" data-uid="Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.Boundary*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_MultipartRequestPartSentEventArgs_Boundary" data-uid="Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.Boundary">Boundary</h4>
<div class="markdown level1 summary"><p>Boundary.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string Boundary { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></td>
<td></td>
</tr>
</tbody>
</table>
<a id="Titanium_Web_Proxy_EventArguments_MultipartRequestPartSentEventArgs_Headers_" data-uid="Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.Headers*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_MultipartRequestPartSentEventArgs_Headers" data-uid="Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.Headers">Headers</h4>
<div class="markdown level1 summary"><p>The header collection.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public HeaderCollection Headers { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="Titanium.Web.Proxy.Http.HeaderCollection.html">HeaderCollection</a></td>
<td></td>
</tr>
</tbody>
</table>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Namespace Titanium.Web.Proxy.EventArguments
| Titanium Web Proxy </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Namespace Titanium.Web.Proxy.EventArguments
| Titanium Web Proxy ">
<meta name="generator" content="docfx 2.35.2.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="">
<meta property="docfx:tocrel" content="toc.html">
<meta property="docfx:rel" content="../">
</head>
<body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div class="container body-content">
<div id="search-results">
<div class="search-list"></div>
<div class="sr-items">
<p><i class="glyphicon glyphicon-refresh index-loading"></i></p>
</div>
<ul id="pagination"></ul>
</div>
</div>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="Titanium.Web.Proxy.EventArguments">
<h1 id="Titanium_Web_Proxy_EventArguments" data-uid="Titanium.Web.Proxy.EventArguments" class="text-break">Namespace Titanium.Web.Proxy.EventArguments
</h1>
<div class="markdown level0 summary"></div>
<div class="markdown level0 conceptual"></div>
<div class="markdown level0 remarks"></div>
<h3 id="classes">Classes
</h3>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.BeforeSslAuthenticateEventArgs.html">BeforeSslAuthenticateEventArgs</a></h4>
<section><p>This is used in transparent endpoint before authenticating client. </p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.html">CertificateSelectionEventArgs</a></h4>
<section><p>An argument passed on to user for client certificate selection during mutual SSL authentication.</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.CertificateValidationEventArgs.html">CertificateValidationEventArgs</a></h4>
<section><p>An argument passed on to the user for validating the server certificate
during SSL authentication.</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.DataEventArgs.html">DataEventArgs</a></h4>
<section><p>Wraps the data sent/received by a proxy server instance.</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html">MultipartRequestPartSentEventArgs</a></h4>
<section><p>Class that wraps the multipart sent request arguments.</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgs.html">SessionEventArgs</a></h4>
<section><p>Holds info related to a single proxy session (single request/response sequence).
A proxy session is bounded to a single connection from client.
A proxy session ends when client terminates connection to proxy
or when server terminates connection from proxy.</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html">SessionEventArgsBase</a></h4>
<section><p>Holds info related to a single proxy session (single request/response sequence).
A proxy session is bounded to a single connection from client.
A proxy session ends when client terminates connection to proxy
or when server terminates connection from proxy.</p>
</section>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html">TunnelConnectSessionEventArgs</a></h4>
<section><p>A class that wraps the state when a tunnel connect event happen for Explicit endpoints.</p>
</section>
<h3 id="delegates">Delegates
</h3>
<h4><a class="xref" href="Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html">AsyncEventHandler&lt;TEventArgs&gt;</a></h4>
<section><p>A generic asynchronous event handler used by the proxy.</p>
</section>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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