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)"
$SolutionRoot = (Split-Path -parent $Here)
$ProjectName = "Titanium.Web.Proxy"
$GitHubProjectName = "Titanium-Web-Proxy"
$GitHubUserName = "justcoding121"
$SolutionFile = "$SolutionRoot\$ProjectName.sln"
## This comes from the build server iteration
if(!$BuildNumber) { $BuildNumber = $env:APPVEYOR_BUILD_NUMBER }
if(!$BuildNumber) { $BuildNumber = "1"}
if(!$BuildNumber) { $BuildNumber = "0"}
## The build configuration, i.e. Debug/Release
if(!$Configuration) { $Configuration = $env:Configuration }
if(!$Configuration) { $Configuration = "Release" }
if(!$Version) { $Version = $env:APPVEYOR_BUILD_VERSION }
if(!$Version) { $Version = "1.0.$BuildNumber" }
if(!$Version) { $Version = "0.0.$BuildNumber" }
if(!$Branch) { $Branch = $env:APPVEYOR_REPO_BRANCH }
if(!$Branch) { $Branch = "local" }
if($Branch -eq "beta" ) { $Version = "$Version-beta" }
Import-Module "$Here\Common" -DisableNameChecking
$NuGet = Join-Path $SolutionRoot ".nuget\nuget.exe"
$MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe"
$MSBuild -replace ' ', '` '
FormatTaskName (("-"*25) + "[{0}]" + ("-"*25))
Task default -depends Clean, Build, Package
Task Build -depends Restore-Packages{
exec { . $MSBuild $SolutionFile /t:Build /v:normal /p:Configuration=$Configuration /t:restore }
}
Task Package -depends Build {
exec { . $NuGet pack "$SolutionRoot\Titanium.Web.Proxy\Titanium.Web.Proxy.nuspec" -Properties Configuration=$Configuration -OutputDirectory "$SolutionRoot" -Version "$Version" }
}
#default task
Task default -depends Clean, Build, Document, Package
Task Clean -depends Install-BuildTools {
#cleans obj, b
Task Clean {
Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { Remove-Item $_.fullname -Force -Recurse }
exec { . $MSBuild $SolutionFile /t:Clean /v:quiet }
}
Task Restore-Packages {
exec { . dotnet restore "$SolutionRoot\Titanium.Web.Proxy.sln" }
}
Task Install-MSBuild {
#install build tools
Task Install-BuildTools -depends Clean {
if(!(Test-Path $MSBuild))
{
cinst microsoft-build-tools -y
}
}
Task Install-BuildTools -depends Install-MSBuild
\ No newline at end of file
#restore nuget packages
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}" ]
}
}
###
### Common Profile functions for all users
###
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$SolutionRoot = Split-Path -Parent $ScriptPath
$ToolsPath = Join-Path -Path $SolutionRoot -ChildPath "lib"
Export-ModuleMember -Variable @('ScriptPath', 'SolutionRoot', 'ToolsPath')
param (
[string]$Action="default",
[hashtable]$properties=@{},
[switch]$Help
)
function Install-Chocolatey()
{
......@@ -20,6 +11,7 @@ function Install-Chocolatey()
Write-Output "Chocolatey Not Found, Installing..."
iex ((new-object net.webclient).DownloadString('http://chocolatey.org/install.ps1'))
}
$env:Path += ";${env:ChocolateyInstall}"
}
function Install-Psake()
......@@ -30,4 +22,60 @@ function Install-Psake()
}
}
Export-ModuleMember -Function *-*
\ No newline at end of file
function Install-Git()
{
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/
# Visual Studio 6 workspace options file
*.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#
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**
![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**
![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
......

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
private static readonly ICompression gzip = new GZipCompression();
private static readonly ICompression deflate = new DeflateCompression();
public static ICompression GetCompression(string type)
internal static ICompression GetCompression(string type)
{
switch (type)
{
......
......@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Decompression
private static readonly IDecompression deflate = new DeflateDecompression();
public static IDecompression Create(string type)
internal static IDecompression Create(string type)
{
switch (type)
{
......
......@@ -2,5 +2,12 @@
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);
}
......@@ -3,6 +3,9 @@ using System.Threading;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// This is used in transparent endpoint before authenticating client.
/// </summary>
public class BeforeSslAuthenticateEventArgs : EventArgs
{
internal readonly CancellationTokenSource TaskCancellationSource;
......@@ -12,10 +15,21 @@ namespace Titanium.Web.Proxy.EventArguments
TaskCancellationSource = taskCancellationSource;
}
/// <summary>
/// The server name indication hostname if available. Otherwise the generic certificate hostname of TransparentEndPoint.
/// </summary>
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;
/// <summary>
/// Terminate the request abruptly by closing client/server connections.
/// </summary>
public void TerminateSession()
{
TaskCancellationSource.Cancel();
......
......@@ -4,37 +4,37 @@ using System.Security.Cryptography.X509Certificates;
namespace Titanium.Web.Proxy.EventArguments
{
/// <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>
public class CertificateSelectionEventArgs : EventArgs
{
/// <summary>
/// Sender object.
/// The proxy server instance.
/// </summary>
public object Sender { get; internal set; }
/// <summary>
/// Target host.
/// The remote hostname to which we are authenticating against.
/// </summary>
public string TargetHost { get; internal set; }
/// <summary>
/// Local certificates.
/// Local certificates in store with matching issuers requested by TargetHost website.
/// </summary>
public X509CertificateCollection LocalCertificates { get; internal set; }
/// <summary>
/// Remote certificate.
/// Certificate of the remote server.
/// </summary>
public X509Certificate RemoteCertificate { get; internal set; }
/// <summary>
/// Acceptable issuers.
/// Acceptable issuers as listed by remoted server.
/// </summary>
public string[] AcceptableIssuers { get; internal set; }
/// <summary>
/// Client Certificate.
/// Client Certificate we selected. Set this value to override.
/// </summary>
public X509Certificate ClientCertificate { get; set; }
}
......
......@@ -5,17 +5,18 @@ using System.Security.Cryptography.X509Certificates;
namespace Titanium.Web.Proxy.EventArguments
{
/// <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>
public class CertificateValidationEventArgs : EventArgs
{
/// <summary>
/// Certificate
/// Server certificate.
/// </summary>
public X509Certificate Certificate { get; internal set; }
/// <summary>
/// Certificate chain
/// Certificate chain.
/// </summary>
public X509Chain Chain { get; internal set; }
......@@ -25,7 +26,7 @@ namespace Titanium.Web.Proxy.EventArguments
public SslPolicyErrors SslPolicyErrors { get; internal set; }
/// <summary>
/// is a valid certificate?
/// Is the given server certificate valid?
/// </summary>
public bool IsValid { get; set; }
}
......
......@@ -2,6 +2,9 @@ using System;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// Wraps the data sent/received by a proxy server instance.
/// </summary>
public class DataEventArgs : EventArgs
{
internal DataEventArgs(byte[] buffer, int offset, int count)
......@@ -11,10 +14,19 @@ namespace Titanium.Web.Proxy.EventArguments
Count = count;
}
/// <summary>
/// The buffer with data.
/// </summary>
public byte[] Buffer { get; }
/// <summary>
/// Offset in buffer from which valid data begins.
/// </summary>
public int Offset { get; }
/// <summary>
/// Length from offset in buffer with valid data.
/// </summary>
public int Count { get; }
}
}
......@@ -54,7 +54,7 @@ namespace Titanium.Web.Proxy.EventArguments
readChunkTrail = true;
string chunkHead = baseReader.ReadLineAsync().Result;
int idx = chunkHead.IndexOf(";");
int idx = chunkHead.IndexOf(";", StringComparison.Ordinal);
if (idx >= 0)
{
chunkHead = chunkHead.Substring(0, idx);
......@@ -68,7 +68,7 @@ namespace Titanium.Web.Proxy.EventArguments
bytesRemaining = -1;
//chunk trail
string s = baseReader.ReadLineAsync().Result;
baseReader.ReadLineAsync().Wait();
}
}
......
......@@ -3,16 +3,25 @@ using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// Class that wraps the multipart sent request arguments.
/// </summary>
public class MultipartRequestPartSentEventArgs : EventArgs
{
public MultipartRequestPartSentEventArgs(string boundary, HeaderCollection headers)
internal MultipartRequestPartSentEventArgs(string boundary, HeaderCollection headers)
{
Boundary = boundary;
Headers = headers;
}
/// <summary>
/// Boundary.
/// </summary>
public string Boundary { get; }
/// <summary>
/// The header collection.
/// </summary>
public HeaderCollection Headers { get; }
}
}
......@@ -15,10 +15,10 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// Holds info related to a single proxy session (single request/response sequence)
/// A proxy session is bounded to a single connection from client
/// 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
/// or when server terminates connection from proxy.
/// </summary>
public class SessionEventArgs : SessionEventArgsBase
{
......@@ -47,7 +47,7 @@ namespace Titanium.Web.Proxy.EventArguments
private bool hasMulipartEventSubscribers => MultipartRequestPartSent != null;
/// <summary>
/// Should we send the request again
/// Should we send the request again ?
/// </summary>
public bool ReRequest
{
......@@ -346,9 +346,10 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Gets the request body as bytes
/// Gets the request body as bytes.
/// </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)
{
if (!WebSession.Request.IsBodyRead)
......@@ -360,9 +361,10 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Gets the request body as string
/// Gets the request body as string.
/// </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)
{
if (!WebSession.Request.IsBodyRead)
......@@ -374,9 +376,9 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Sets the request body
/// Sets the request body.
/// </summary>
/// <param name="body"></param>
/// <param name="body">The request body bytes.</param>
public void SetRequestBody(byte[] body)
{
var request = WebSession.Request;
......@@ -389,9 +391,9 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Sets the body with the specified string
/// Sets the body with the specified string.
/// </summary>
/// <param name="body"></param>
/// <param name="body">The request body string to set.</param>
public void SetRequestBodyString(string body)
{
if (WebSession.Request.Locked)
......@@ -402,10 +404,12 @@ namespace Titanium.Web.Proxy.EventArguments
SetRequestBody(WebSession.Request.Encoding.GetBytes(body));
}
/// <summary>
/// Gets the response body as byte array
/// Gets the response body as bytes.
/// </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)
{
if (!WebSession.Response.IsBodyRead)
......@@ -417,9 +421,10 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Gets the response body as string
/// Gets the response body as string.
/// </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)
{
if (!WebSession.Response.IsBodyRead)
......@@ -431,9 +436,9 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Set the response body bytes
/// Set the response body bytes.
/// </summary>
/// <param name="body"></param>
/// <param name="body">The body bytes to set.</param>
public void SetResponseBody(byte[] body)
{
if (!WebSession.Request.Locked)
......@@ -446,9 +451,9 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Replace the response body with the specified string
/// Replace the response body with the specified string.
/// </summary>
/// <param name="body"></param>
/// <param name="body">The body string to set.</param>
public void SetResponseBodyString(string body)
{
if (!WebSession.Request.Locked)
......@@ -462,12 +467,11 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Before request is made to server
/// Respond with the specified HTML string to client
/// and ignore the request
/// Before request is made to server respond with the specified HTML string to client
/// and ignore the request.
/// </summary>
/// <param name="html"></param>
/// <param name="headers"></param>
/// <param name="html">HTML content to sent.</param>
/// <param name="headers">HTTP response headers.</param>
public void Ok(string html, Dictionary<string, HttpHeader> headers = null)
{
var response = new OkResponse();
......@@ -483,12 +487,11 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Before request is made to server
/// Respond with the specified byte[] to client
/// and ignore the request
/// Before request is made to server respond with the specified byte[] to client
/// and ignore the request.
/// </summary>
/// <param name="result"></param>
/// <param name="headers"></param>
/// <param name="result">The html content bytes.</param>
/// <param name="headers">The HTTP headers.</param>
public void Ok(byte[] result, Dictionary<string, HttpHeader> headers = null)
{
var response = new OkResponse();
......@@ -501,13 +504,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// Before request is made to server 
/// Respond with the specified HTML string to client
/// and the specified status
/// and ignore the request 
/// respond with the specified HTML string and the specified status to client.
/// And then ignore the request. 
/// </summary>
/// <param name="html"></param>
/// <param name="status"></param>
/// <param name="headers"></param>
/// <param name="html">The html content.</param>
/// <param name="status">The HTTP status code.</param>
/// <param name="headers">The HTTP headers.</param>
/// <returns></returns>
public void GenericResponse(string html, HttpStatusCode status, Dictionary<string, HttpHeader> headers = null)
{
......@@ -520,14 +522,12 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Before request is made to server
/// Respond with the specified byte[] to client
/// and the specified status
/// and ignore the request
/// Before request is made to server respond with the specified byte[],
/// the specified status to client. And then ignore the request.
/// </summary>
/// <param name="result"></param>
/// <param name="status"></param>
/// <param name="headers"></param>
/// <param name="result">The bytes to sent.</param>
/// <param name="status">The HTTP status code.</param>
/// <param name="headers">The HTTP headers.</param>
/// <returns></returns>
public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary<string, HttpHeader> headers)
{
......@@ -540,9 +540,9 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Redirect to URL.
/// Redirect to provided URL.
/// </summary>
/// <param name="url"></param>
/// <param name="url">The URL to redirect.</param>
/// <returns></returns>
public void Redirect(string url)
{
......@@ -554,7 +554,10 @@ namespace Titanium.Web.Proxy.EventArguments
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)
{
if (WebSession.Request.Locked)
......@@ -579,13 +582,16 @@ namespace Titanium.Web.Proxy.EventArguments
}
}
/// <summary>
/// Terminate the connection to server.
/// </summary>
public void TerminateServerConnection()
{
WebSession.Response.TerminateResponse = true;
}
/// <summary>
/// implement any cleanup here
/// Implement any cleanup here
/// </summary>
public override void Dispose()
{
......
......@@ -9,10 +9,10 @@ using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// Holds info related to a single proxy session (single request/response sequence)
/// A proxy session is bounded to a single connection from client
/// 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
/// or when server terminates connection from proxy.
/// </summary>
public abstract class SessionEventArgsBase : EventArgs, IDisposable
{
......@@ -73,13 +73,13 @@ namespace Titanium.Web.Proxy.EventArguments
internal ProxyClient ProxyClient { get; }
/// <summary>
/// Returns a unique Id for this request/response session
/// same as RequestId of WebSession
/// Returns a unique Id for this request/response session which is
/// same as the RequestId of WebSession.
/// </summary>
public Guid Id => WebSession.RequestId;
/// <summary>
/// Does this session uses SSL
/// Does this session uses SSL?
/// </summary>
public bool IsHttps => WebSession.Request.IsHttps;
......@@ -90,7 +90,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// A web session corresponding to a single request/response sequence
/// within a proxy connection
/// within a proxy connection.
/// </summary>
public HttpWebClient WebSession { get; }
......@@ -99,14 +99,23 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public ExternalProxy CustomUpStreamProxyUsed { get; internal set; }
/// <summary>
/// Local endpoint via which we make the request.
/// </summary>
public ProxyEndPoint LocalEndPoint { get; }
/// <summary>
/// Is this a transparent endpoint?
/// </summary>
public bool IsTransparent => LocalEndPoint is TransparentProxyEndPoint;
/// <summary>
/// The last exception that happened.
/// </summary>
public Exception Exception { get; internal set; }
/// <summary>
/// implement any cleanup here
/// Implements cleanup here.
/// </summary>
public virtual void Dispose()
{
......@@ -119,8 +128,14 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.FinishSession();
}
/// <summary>
/// Fired when data is sent within this session to server/client.
/// </summary>
public event EventHandler<DataEventArgs> DataSent;
/// <summary>
/// Fired when data is received within this session from client/server.
/// </summary>
public event EventHandler<DataEventArgs> DataReceived;
internal void OnDataSent(byte[] buffer, int offset, int count)
......@@ -148,7 +163,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
/// <summary>
/// Terminates the session abruptly by terminating client/server connections
/// Terminates the session abruptly by terminating client/server connections.
/// </summary>
public void TerminateSession()
{
......
......@@ -5,6 +5,9 @@ using Titanium.Web.Proxy.Models;
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
{
private bool? isHttpsConnect;
......@@ -16,13 +19,20 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.ConnectRequest = connectRequest;
}
/// <summary>
/// Should we decrypt the Ssl or relay it to server?
/// Default is true.
/// </summary>
public bool DecryptSsl { get; set; } = true;
/// <summary>
/// Denies the connect request with a Forbidden status
/// When set to true it denies the connect request with a Forbidden status.
/// </summary>
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
{
get => isHttpsConnect ?? throw new Exception("The value of this property is known in the BeforeTunnectConnectResponse event");
......
......@@ -2,5 +2,9 @@ using System;
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);
}
namespace Titanium.Web.Proxy.Exceptions
{
/// <summary>
/// An expception thrown when body is unexpectedly empty
/// An exception thrown when body is unexpectedly empty.
/// </summary>
public class BodyNotFoundException : ProxyException
{
......
......@@ -6,14 +6,14 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Exceptions
{
/// <summary>
/// Proxy authorization exception
/// Proxy authorization exception.
/// </summary>
public class ProxyAuthorizationException : ProxyException
{
/// <summary>
/// Instantiate new instance
/// Instantiate new instance.
/// </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="innerException">Inner exception associated to upstream proxy authorization</param>
/// <param name="headers">Http's headers associated</param>
......@@ -24,10 +24,13 @@ namespace Titanium.Web.Proxy.Exceptions
Headers = headers;
}
/// <summary>
/// The current session within which this error happened.
/// </summary>
public SessionEventArgsBase Session { get; }
/// <summary>
/// Headers associated with the authorization exception
/// Headers associated with the authorization exception.
/// </summary>
public IEnumerable<HttpHeader> Headers { get; }
}
......
......@@ -3,7 +3,7 @@
namespace Titanium.Web.Proxy.Exceptions
{
/// <summary>
/// Base class exception associated with this proxy implementation
/// Base class exception associated with this proxy server.
/// </summary>
public abstract class ProxyException : Exception
{
......
......@@ -4,7 +4,7 @@ using Titanium.Web.Proxy.EventArguments;
namespace Titanium.Web.Proxy.Exceptions
{
/// <summary>
/// Proxy HTTP exception
/// Proxy HTTP exception.
/// </summary>
public class ProxyHttpException : ProxyException
{
......@@ -21,10 +21,10 @@ namespace Titanium.Web.Proxy.Exceptions
}
/// <summary>
/// Gets session info associated to the exception
/// Gets session info associated to the exception.
/// </summary>
/// <remarks>
/// This object should not be edited
/// This object properties should not be edited.
/// </remarks>
public SessionEventArgs SessionEventArgs { get; }
}
......
......@@ -6,14 +6,14 @@ namespace Titanium.Web.Proxy.Extensions
{
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)
{
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
{
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 &&
clientHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension))
......@@ -27,7 +27,7 @@ namespace Titanium.Web.Proxy.Extensions
}
#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))
{
......@@ -55,17 +55,17 @@ namespace Titanium.Web.Proxy.Extensions
return null;
}
#else
public static List<SslApplicationProtocol> GetAlpn(this ClientHelloInfo clientHelloInfo)
internal static List<SslApplicationProtocol> GetAlpn(this ClientHelloInfo clientHelloInfo)
{
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);
}
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);
}
......@@ -73,49 +73,49 @@ namespace Titanium.Web.Proxy.Extensions
}
#if !NETCOREAPP2_1
public enum SslApplicationProtocol
internal enum SslApplicationProtocol
{
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
}
......@@ -7,18 +7,18 @@ namespace Titanium.Web.Proxy.Helpers
{
internal sealed class HttpRequestWriter : HttpWriter
{
public HttpRequestWriter(Stream stream, int bufferSize) : base(stream, bufferSize)
internal HttpRequestWriter(Stream stream, int bufferSize) : base(stream, bufferSize)
{
}
/// <summary>
/// Writes the request.
/// </summary>
/// <param name="request"></param>
/// <param name="flush"></param>
/// <param name="cancellationToken"></param>
/// <param name="request">The request object.</param>
/// <param name="flush">Should we flush after write?</param>
/// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns></returns>
public async Task WriteRequestAsync(Request request, bool flush = true,
internal async Task WriteRequestAsync(Request request, bool flush = true,
CancellationToken cancellationToken = default)
{
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.OriginalUrl, request.HttpVersion),
......
......@@ -8,18 +8,18 @@ namespace Titanium.Web.Proxy.Helpers
{
internal sealed class HttpResponseWriter : HttpWriter
{
public HttpResponseWriter(Stream stream, int bufferSize) : base(stream, bufferSize)
internal HttpResponseWriter(Stream stream, int bufferSize) : base(stream, bufferSize)
{
}
/// <summary>
/// Writes the response.
/// </summary>
/// <param name="response"></param>
/// <param name="flush"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task WriteResponseAsync(Response response, bool flush = true,
/// <param name="response">The response object.</param>
/// <param name="flush">Should we flush after write?</param>
/// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The Task.</returns>
internal async Task WriteResponseAsync(Response response, bool flush = true,
CancellationToken cancellationToken = default)
{
await WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription,
......@@ -30,12 +30,12 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// Write response status
/// </summary>
/// <param name="version"></param>
/// <param name="code"></param>
/// <param name="description"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task WriteResponseStatusAsync(Version version, int code, string description, CancellationToken cancellationToken)
/// <param name="version">The Http version.</param>
/// <param name="code">The HTTP status code.</param>
/// <param name="description">The HTTP status description.</param>
/// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The Task.</returns>
internal Task WriteResponseStatusAsync(Version version, int code, string description, CancellationToken cancellationToken)
{
return WriteLineAsync(Response.CreateResponseLine(version, code, description), cancellationToken);
}
......
......@@ -27,14 +27,19 @@ namespace Titanium.Web.Proxy.Helpers
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);
}
public Task WriteAsync(string value, CancellationToken cancellationToken = default)
internal Task WriteAsync(string value, CancellationToken cancellationToken = default)
{
return WriteAsyncInternal(value, false, cancellationToken);
}
......@@ -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);
}
......@@ -93,7 +98,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="flush"></param>
/// <param name="cancellationToken"></param>
/// <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)
{
......@@ -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);
if (flush)
......@@ -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);
if (flush)
......
......@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Helpers
{
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)
{
AutoDetect = autoDetect;
......@@ -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)
{
......@@ -131,7 +131,7 @@ namespace Titanium.Web.Proxy.Helpers
return stringBuilder.ToString();
}
public static ProxyProtocolType? ParseProtocolType(string protocolTypeStr)
internal static ProxyProtocolType? ParseProtocolType(string protocolTypeStr)
{
if (protocolTypeStr == null)
{
......@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// <param name="proxyServerValues"></param>
/// <returns></returns>
public static List<HttpSystemProxyValue> GetSystemProxyValues(string proxyServerValues)
internal static List<HttpSystemProxyValue> GetSystemProxyValues(string proxyServerValues)
{
var result = new List<HttpSystemProxyValue>();
......
......@@ -6,18 +6,18 @@ using System.Threading.Tasks;
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;
}
public T Value { get; set; }
internal T Value { get; set; }
public override string ToString()
{
......
......@@ -27,12 +27,12 @@ namespace Titanium.Web.Proxy.Http
}
/// <summary>
/// Unique Request header collection
/// Unique Request header collection.
/// </summary>
public ReadOnlyDictionary<string, HttpHeader> Headers { get; }
/// <summary>
/// Non Unique headers
/// Non Unique headers.
/// </summary>
public ReadOnlyDictionary<string, List<HttpHeader>> NonUniqueHeaders { get; }
......
......@@ -15,12 +15,12 @@ namespace Titanium.Web.Proxy.Http
public class Request : RequestResponseBase
{
/// <summary>
/// Request Method
/// Request Method.
/// </summary>
public string Method { get; set; }
/// <summary>
/// Request HTTP Uri
/// Request HTTP Uri.
/// </summary>
public Uri RequestUri { get; set; }
......@@ -66,9 +66,9 @@ namespace Titanium.Web.Proxy.Http
}
/// <summary>
/// Http hostname header value if exists
/// Note: Changing this does NOT change host in RequestUri
/// Users can set new RequestUri separately
/// Http hostname header value if exists.
/// Note: Changing this does NOT change host in RequestUri.
/// Users can set new RequestUri separately.
/// </summary>
public string Host
{
......@@ -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;
/// <summary>
/// Request Url
/// Request Url.
/// </summary>
public string Url => RequestUri.OriginalString;
/// <summary>
/// Terminates the underlying Tcp Connection to client after current request
/// Terminates the underlying Tcp Connection to client after current request.
/// </summary>
internal bool CancelRequest { get; set; }
......@@ -119,12 +122,12 @@ namespace Titanium.Web.Proxy.Http
}
/// <summary>
/// Does server responsed positively for 100 continue request
/// Did server responsed positively for 100 continue request?
/// </summary>
public bool Is100Continue { get; internal set; }
/// <summary>
/// Server responsed negatively for the request for 100 continue
/// Did server responsed negatively for the request for 100 continue?
/// </summary>
public bool ExpectationFailed { get; internal set; }
......
......@@ -12,12 +12,12 @@ namespace Titanium.Web.Proxy.Http
public abstract class RequestResponseBase
{
/// <summary>
/// Cached body content as byte array
/// Cached body content as byte array.
/// </summary>
protected byte[] BodyInternal;
/// <summary>
/// Cached body as string
/// Cached body as string.
/// </summary>
private string bodyString;
......@@ -27,22 +27,22 @@ namespace Titanium.Web.Proxy.Http
internal bool OriginalHasBody;
/// <summary>
/// Keeps the body data after the session is finished
/// Keeps the body data after the session is finished.
/// </summary>
public bool KeepBody { get; set; }
/// <summary>
/// Http Version
/// Http Version.
/// </summary>
public Version HttpVersion { get; set; } = HttpHeader.VersionUnknown;
/// <summary>
/// Collection of all headers
/// Collection of all headers.
/// </summary>
public HeaderCollection Headers { get; } = new HeaderCollection();
/// <summary>
/// Length of the body
/// Length of the body.
/// </summary>
public long ContentLength
{
......@@ -77,17 +77,17 @@ namespace Titanium.Web.Proxy.Http
}
/// <summary>
/// Content encoding for this request/response
/// Content encoding for this request/response.
/// </summary>
public string ContentEncoding => Headers.GetHeaderValueOrNull(KnownHeaders.ContentEncoding)?.Trim();
/// <summary>
/// Encoding for this request/response
/// Encoding for this request/response.
/// </summary>
public Encoding Encoding => HttpHelper.GetEncodingFromContentType(ContentType);
/// <summary>
/// Content-type of the request/response
/// Content-type of the request/response.
/// </summary>
public string ContentType
{
......@@ -96,7 +96,7 @@ namespace Titanium.Web.Proxy.Http
}
/// <summary>
/// Is body send as chunked bytes
/// Is body send as chunked bytes.
/// </summary>
public bool IsChunked
{
......@@ -119,6 +119,9 @@ namespace Titanium.Web.Proxy.Http
}
}
/// <summary>
/// The header text.
/// </summary>
public abstract string HeaderText { get; }
/// <summary>
......@@ -148,7 +151,7 @@ namespace Titanium.Web.Proxy.Http
public abstract bool HasBody { get; }
/// <summary>
/// Body as string
/// Body as string.
/// Use the encoding specified to decode the byte[] data to string
/// </summary>
[Browsable(false)]
......
......@@ -7,17 +7,17 @@ using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy.Models
{
/// <summary>
/// A proxy endpoint that the client is aware of
/// So client application know that it is communicating with a proxy server
/// A proxy endpoint that the client is aware of.
/// So client application know that it is communicating with a proxy server.
/// </summary>
public class ExplicitProxyEndPoint : ProxyEndPoint
{
/// <summary>
/// Constructor.
/// Constructor.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="decryptSsl"></param>
/// <param name="ipAddress">Listening IP address.</param>
/// <param name="port">Listening port.</param>
/// <param name="decryptSsl">Should we decrypt ssl?</param>
public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) : base(ipAddress, port,
decryptSsl)
{
......@@ -33,16 +33,16 @@ namespace Titanium.Web.Proxy.Models
public X509Certificate2 GenericCertificate { get; set; }
/// <summary>
/// Intercept tunnel connect request
/// Valid only for explicit endpoints
/// Intercept tunnel connect request.
/// Valid only for explicit endpoints.
/// 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>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest;
/// <summary>
/// Intercept tunnel connect response
/// Valid only for explicit endpoints
/// Intercept tunnel connect response.
/// Valid only for explicit endpoints.
/// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectResponse;
......
......@@ -4,7 +4,7 @@ using System.Net;
namespace Titanium.Web.Proxy.Models
{
/// <summary>
/// An upstream proxy this proxy uses if any
/// An upstream proxy this proxy uses if any.
/// </summary>
public class ExternalProxy
{
......@@ -69,6 +69,10 @@ namespace Titanium.Web.Proxy.Models
/// </summary>
public int Port { get; set; }
/// <summary>
/// returns data in Hostname:port format.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"{HostName}:{Port}";
......
......@@ -22,12 +22,11 @@ namespace Titanium.Web.Proxy.Models
internal static readonly HttpHeader ProxyConnectionKeepAlive = new HttpHeader("Proxy-Connection", "keep-alive");
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <exception cref="Exception"></exception>
/// <summary>
/// Initialize a new instance.
/// </summary>
/// <param name="name">Header name.</param>
/// <param name="value">Header value.</param>
public HttpHeader(string name, string value)
{
if (string.IsNullOrEmpty(name))
......@@ -50,7 +49,7 @@ namespace Titanium.Web.Proxy.Models
public string Value { get; set; }
/// <summary>
/// Returns header as a valid header string
/// Returns header as a valid header string.
/// </summary>
/// <returns></returns>
public override string ToString()
......
......@@ -6,17 +6,17 @@ using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy.Models
{
/// <summary>
/// A proxy end point client is not aware of
/// Usefull when requests are redirected to this proxy end point through port forwarding
/// A proxy end point client is not aware of.
/// Useful when requests are redirected to this proxy end point through port forwarding via router.
/// </summary>
public class TransparentProxyEndPoint : ProxyEndPoint
{
/// <summary>
/// Constructor.
/// Initialize a new instance.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="decryptSsl"></param>
/// <param name="ipAddress">Listening Ip address.</param>
/// <param name="port">Listening port.</param>
/// <param name="decryptSsl">Should we decrypt ssl?</param>
public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) : base(ipAddress, port,
decryptSsl)
{
......@@ -24,13 +24,13 @@ namespace Titanium.Web.Proxy.Models
}
/// <summary>
/// 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
/// 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.
/// </summary>
public string GenericCertificateName { get; set; }
/// <summary>
/// Before Ssl authentication
/// Before Ssl authentication this event is fired.
/// </summary>
public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate;
......
......@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// NTLM process details below
/// https://blogs.msdn.microsoft.com/chiranth/2013/09/20/ntlm-want-to-know-how-it-works/
/// </summary>
public static class WinAuthHandler
internal static class WinAuthHandler
{
/// <summary>
/// Get the initial client token for server
......@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// <param name="authScheme"></param>
/// <param name="requestId"></param>
/// <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);
return string.Concat(" ", Convert.ToBase64String(tokenBytes));
......@@ -32,7 +32,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// <param name="serverToken"></param>
/// <param name="requestId"></param>
/// <returns></returns>
public static string GetFinalAuthToken(string serverHostname, string serverToken, Guid requestId)
internal static string GetFinalAuthToken(string serverHostname, string serverToken, Guid requestId)
{
var tokenBytes =
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
# to run your custom scripts instead of automatic MSBuild
build_script:
- cmd: .\build.bat Package
- cmd: build.bat Package
assembly_info:
patch: true
......@@ -39,7 +39,9 @@ test: on
# skip building commits that add tags (such as release tag)
skip_tags: true
skip_commits:
author: buildbot121
#---------------------------------#
# artifacts configuration #
#---------------------------------#
......@@ -50,14 +52,19 @@ nuget:
artifacts:
- 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:
- provider: GitHub
auth_token:
secure: ItVm+50ASpDXx1w+FCe2NTpZxqCbjRWfugLjk/bqBIi00DvPnSGOV1rIQ5hnwBW3
auth_token: $(github_access_token)
on:
branch: /(stable|beta)/
- provider: NuGet
api_key:
secure: ZbRmjOcp+TDllRV1wxqLZjdRV7hld388rXlWVJuGGiQleomP9Ku+Nsy3a75E7/9k
api_key: $(nuget_access_token)
on:
branch: /(stable|beta)/
@echo off
if '%1'=='/?' goto help
if '%1'=='-help' goto help
if '%1'=='-h' goto help
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
powershell -NoProfile -ExecutionPolicy bypass -Command "%~dp0.build\setup.ps1 %*; if ($psake.build_success -eq $false) { exit 1 } else { exit 0 }"
exit /B %errorlevel%
\ 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