Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
T
Titanium-Web-Proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Titanium-Web-Proxy
Commits
f387486d
Commit
f387486d
authored
May 20, 2016
by
justcoding121
Committed by
justcoding121
May 20, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Asyncify fixes
parent
bf63cc40
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
239 additions
and
218 deletions
+239
-218
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+4
-4
README.md
README.md
+3
-6
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+23
-16
HttpWebRequestExtensions.cs
Titanium.Web.Proxy/Extensions/HttpWebRequestExtensions.cs
+2
-1
HttpWebResponseExtensions.cs
Titanium.Web.Proxy/Extensions/HttpWebResponseExtensions.cs
+24
-6
StreamExtensions.cs
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
+10
-6
CertificateManager.cs
Titanium.Web.Proxy/Helpers/CertificateManager.cs
+94
-68
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+12
-12
Response.cs
Titanium.Web.Proxy/Http/Response.cs
+3
-22
ProxyClient.cs
Titanium.Web.Proxy/Network/ProxyClient.cs
+1
-1
TcpConnectionManager.cs
Titanium.Web.Proxy/Network/TcpConnectionManager.cs
+21
-18
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+9
-6
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+12
-8
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+20
-43
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+1
-1
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
f387486d
...
@@ -12,9 +12,9 @@ namespace Titanium.Web.Proxy.Examples.Basic
...
@@ -12,9 +12,9 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
{
public
void
StartProxy
()
public
void
StartProxy
()
{
{
ProxyServer
.
BeforeRequest
+=
OnRequest
;
//
ProxyServer.BeforeRequest += OnRequest;
ProxyServer
.
BeforeResponse
+=
OnResponse
;
//
ProxyServer.BeforeResponse += OnResponse;
ProxyServer
.
ServerCertificateValidationCallback
+=
OnCertificateValidation
;
//
ProxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
//Exclude Https addresses you don't want to proxy
//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
//Usefull for clients that use certificate pinning
...
@@ -112,7 +112,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
...
@@ -112,7 +112,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
{
if
(
e
.
WebSession
.
Response
.
ResponseStatusCode
==
"200"
)
if
(
e
.
WebSession
.
Response
.
ResponseStatusCode
==
"200"
)
{
{
if
(
e
.
WebSession
.
Response
.
ContentType
.
Trim
().
ToLower
().
Contains
(
"text/html"
))
if
(
e
.
WebSession
.
Response
.
ContentType
!=
null
&&
e
.
WebSession
.
Response
.
ContentType
.
Trim
().
ToLower
().
Contains
(
"text/html"
))
{
{
byte
[]
bodyBytes
=
await
e
.
GetResponseBody
();
byte
[]
bodyBytes
=
await
e
.
GetResponseBody
();
await
e
.
SetResponseBody
(
bodyBytes
);
await
e
.
SetResponseBody
(
bodyBytes
);
...
...
README.md
View file @
f387486d
...
@@ -136,7 +136,7 @@ Sample request and response event handlers
...
@@ -136,7 +136,7 @@ Sample request and response event handlers
{
{
if
(
e
.
WebSession
.
Response
.
ResponseStatusCode
==
"200"
)
if
(
e
.
WebSession
.
Response
.
ResponseStatusCode
==
"200"
)
{
{
if
(
e
.
WebSession
.
Response
.
ContentType
.
Trim
().
ToLower
().
Contains
(
"text/html"
))
if
(
e
.
WebSession
.
Response
.
ContentType
!=
null
&&
e
.
WebSession
.
Response
.
ContentType
.
Trim
().
ToLower
().
Contains
(
"text/html"
))
{
{
byte
[]
bodyBytes
=
await
e
.
GetResponseBody
();
byte
[]
bodyBytes
=
await
e
.
GetResponseBody
();
await
e
.
SetResponseBody
(
bodyBytes
);
await
e
.
SetResponseBody
(
bodyBytes
);
...
@@ -148,11 +148,8 @@ Sample request and response event handlers
...
@@ -148,11 +148,8 @@ Sample request and response event handlers
}
}
}
}
/// <summary>
/// Allows overriding default certificate validation logic
/// Allows overriding default certificate validation logic
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public
async
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
public
async
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
{
//set IsValid to true/false based on Certificate Errors
//set IsValid to true/false based on Certificate Errors
...
...
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
f387486d
...
@@ -7,6 +7,7 @@ using Titanium.Web.Proxy.Http;
...
@@ -7,6 +7,7 @@ using Titanium.Web.Proxy.Http;
using
Titanium.Web.Proxy.Http.Responses
;
using
Titanium.Web.Proxy.Http.Responses
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Extensions
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Network
;
namespace
Titanium.Web.Proxy.EventArguments
namespace
Titanium.Web.Proxy.EventArguments
{
{
...
@@ -86,14 +87,17 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -86,14 +87,17 @@ namespace Titanium.Web.Proxy.EventArguments
await
this
.
Client
.
ClientStreamReader
.
CopyBytesToStream
(
requestBodyStream
,
WebSession
.
Request
.
ContentLength
).
ConfigureAwait
(
false
);
await
this
.
Client
.
ClientStreamReader
.
CopyBytesToStream
(
requestBodyStream
,
WebSession
.
Request
.
ContentLength
).
ConfigureAwait
(
false
);
}
}
else
if
(
WebSession
.
Request
.
HttpVersion
.
ToLower
().
Trim
().
Equals
(
"http/1.0"
))
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
requestBodyStream
,
long
.
MaxValue
).
ConfigureAwait
(
false
);
}
}
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
requestBodyStream
.
ToArray
()).
ConfigureAwait
(
false
);
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
requestBodyStream
.
ToArray
()).
ConfigureAwait
(
false
);
}
}
}
//Now set the flag to true
//Now set the flag to true
//So that next time we can deliver body from cache
//So that next time we can deliver body from cache
WebSession
.
Request
.
RequestBodyRead
=
true
;
WebSession
.
Request
.
RequestBodyRead
=
true
;
}
}
}
/// <summary>
/// <summary>
...
@@ -109,16 +113,18 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -109,16 +113,18 @@ namespace Titanium.Web.Proxy.EventArguments
//If chuncked the read chunk by chunk until we hit chunk end symbol
//If chuncked the read chunk by chunk until we hit chunk end symbol
if
(
WebSession
.
Response
.
IsChunked
)
if
(
WebSession
.
Response
.
IsChunked
)
{
{
await
WebSession
.
ProxyClient
.
Server
StreamReader
.
CopyBytesToStreamChunked
(
responseBodyStream
).
ConfigureAwait
(
false
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStreamChunked
(
responseBodyStream
).
ConfigureAwait
(
false
);
}
}
else
else
{
{
if
(
WebSession
.
Response
.
ContentLength
>
0
)
if
(
WebSession
.
Response
.
ContentLength
>
0
)
{
{
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await
WebSession
.
ProxyClient
.
Server
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
WebSession
.
Response
.
ContentLength
).
ConfigureAwait
(
false
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
WebSession
.
Response
.
ContentLength
).
ConfigureAwait
(
false
);
}
}
else
if
(
WebSession
.
Response
.
HttpVersion
.
ToLower
().
Trim
().
Equals
(
"http/1.0"
))
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
long
.
MaxValue
).
ConfigureAwait
(
false
);
}
}
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
()).
ConfigureAwait
(
false
);
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
()).
ConfigureAwait
(
false
);
...
@@ -173,7 +179,11 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -173,7 +179,11 @@ namespace Titanium.Web.Proxy.EventArguments
}
}
WebSession
.
Request
.
RequestBody
=
body
;
WebSession
.
Request
.
RequestBody
=
body
;
WebSession
.
Request
.
RequestBodyRead
=
true
;
if
(
WebSession
.
Request
.
IsChunked
==
false
)
WebSession
.
Request
.
ContentLength
=
body
.
Length
;
else
WebSession
.
Request
.
ContentLength
=
-
1
;
}
}
/// <summary>
/// <summary>
...
@@ -191,13 +201,8 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -191,13 +201,8 @@ namespace Titanium.Web.Proxy.EventArguments
await
ReadRequestBody
().
ConfigureAwait
(
false
);
await
ReadRequestBody
().
ConfigureAwait
(
false
);
}
}
WebSession
.
Request
.
RequestBody
=
WebSession
.
Request
.
Encoding
.
GetBytes
(
body
);
await
SetRequestBody
(
WebSession
.
Request
.
Encoding
.
GetBytes
(
body
));
//If there is a content length header update it
if
(!
WebSession
.
Request
.
IsChunked
)
WebSession
.
Request
.
ContentLength
=
body
.
Length
;
WebSession
.
Request
.
RequestBodyRead
=
true
;
}
}
/// <summary>
/// <summary>
...
@@ -245,9 +250,10 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -245,9 +250,10 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession
.
Response
.
ResponseBody
=
body
;
WebSession
.
Response
.
ResponseBody
=
body
;
//If there is a content length header update it
//If there is a content length header update it
if
(
!
WebSession
.
Response
.
IsChunked
)
if
(
WebSession
.
Response
.
IsChunked
==
false
)
WebSession
.
Response
.
ContentLength
=
body
.
Length
;
WebSession
.
Response
.
ContentLength
=
body
.
Length
;
else
WebSession
.
Response
.
ContentLength
=
-
1
;
}
}
/// <summary>
/// <summary>
...
@@ -266,8 +272,9 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -266,8 +272,9 @@ namespace Titanium.Web.Proxy.EventArguments
}
}
var
bodyBytes
=
WebSession
.
Response
.
Encoding
.
GetBytes
(
body
);
var
bodyBytes
=
WebSession
.
Response
.
Encoding
.
GetBytes
(
body
);
await
SetResponseBody
(
bodyBytes
).
ConfigureAwait
(
false
);
await
SetResponseBody
(
bodyBytes
).
ConfigureAwait
(
false
);
}
}
private
async
Task
<
byte
[
]>
GetDecompressedResponseBody
(
string
encodingType
,
byte
[]
responseBodyStream
)
private
async
Task
<
byte
[
]>
GetDecompressedResponseBody
(
string
encodingType
,
byte
[]
responseBodyStream
)
{
{
...
...
Titanium.Web.Proxy/Extensions/HttpWebRequestExtensions.cs
View file @
f387486d
...
@@ -15,7 +15,8 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -15,7 +15,8 @@ namespace Titanium.Web.Proxy.Extensions
try
try
{
{
//return default if not specified
//return default if not specified
if
(
request
.
ContentType
==
null
)
return
Encoding
.
GetEncoding
(
"ISO-8859-1"
);
if
(
request
.
ContentType
==
null
)
return
Encoding
.
GetEncoding
(
"ISO-8859-1"
);
//extract the encoding by finding the charset
//extract the encoding by finding the charset
var
contentTypes
=
request
.
ContentType
.
Split
(
Constants
.
SemiColonSplit
);
var
contentTypes
=
request
.
ContentType
.
Split
(
Constants
.
SemiColonSplit
);
...
...
Titanium.Web.Proxy/Extensions/HttpWebResponseExtensions.cs
View file @
f387486d
using
System.Text
;
using
System.Text
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Shared
;
namespace
Titanium.Web.Proxy.Extensions
namespace
Titanium.Web.Proxy.Extensions
{
{
public
static
class
HttpWebResponseExtensions
public
static
class
HttpWebResponseExtensions
{
{
public
static
Encoding
GetResponseEncoding
(
this
Response
response
)
public
static
Encoding
GetResponse
Character
Encoding
(
this
Response
response
)
{
{
if
(
string
.
IsNullOrEmpty
(
response
.
CharacterSet
))
return
Encoding
.
GetEncoding
(
"ISO-8859-1"
);
try
try
{
{
return
Encoding
.
GetEncoding
(
response
.
CharacterSet
.
Replace
(
@""""
,
string
.
Empty
));
//return default if not specified
if
(
response
.
ContentType
==
null
)
return
Encoding
.
GetEncoding
(
"ISO-8859-1"
);
//extract the encoding by finding the charset
var
contentTypes
=
response
.
ContentType
.
Split
(
Constants
.
SemiColonSplit
);
foreach
(
var
contentType
in
contentTypes
)
{
var
encodingSplit
=
contentType
.
Split
(
'='
);
if
(
encodingSplit
.
Length
==
2
&&
encodingSplit
[
0
].
ToLower
().
Trim
()
==
"charset"
)
{
return
Encoding
.
GetEncoding
(
encodingSplit
[
1
]);
}
}
}
}
catch
{
return
Encoding
.
GetEncoding
(
"ISO-8859-1"
);
}
catch
{
//parsing errors
// ignored
}
//return default if not specified
return
Encoding
.
GetEncoding
(
"ISO-8859-1"
);
}
}
}
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
View file @
f387486d
...
@@ -20,25 +20,29 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -20,25 +20,29 @@ namespace Titanium.Web.Proxy.Extensions
await
input
.
CopyToAsync
(
output
);
await
input
.
CopyToAsync
(
output
);
}
}
internal
static
async
Task
CopyBytesToStream
(
this
CustomBinaryReader
clientS
treamReader
,
Stream
stream
,
long
totalBytesToRead
)
internal
static
async
Task
CopyBytesToStream
(
this
CustomBinaryReader
s
treamReader
,
Stream
stream
,
long
totalBytesToRead
)
{
{
var
totalbytesRead
=
0
;
var
totalbytesRead
=
0
;
int
bytesToRead
;
long
bytesToRead
;
if
(
totalBytesToRead
<
Constants
.
BUFFER_SIZE
)
if
(
totalBytesToRead
<
Constants
.
BUFFER_SIZE
)
{
{
bytesToRead
=
(
int
)
totalBytesToRead
;
bytesToRead
=
totalBytesToRead
;
}
}
else
else
bytesToRead
=
Constants
.
BUFFER_SIZE
;
bytesToRead
=
Constants
.
BUFFER_SIZE
;
while
(
totalbytesRead
<
(
int
)
totalBytesToRead
)
while
(
totalbytesRead
<
totalBytesToRead
)
{
{
var
buffer
=
await
clientStreamReader
.
ReadBytesAsync
(
bytesToRead
);
var
buffer
=
await
streamReader
.
ReadBytesAsync
(
bytesToRead
);
if
(
buffer
.
Length
==
0
)
break
;
totalbytesRead
+=
buffer
.
Length
;
totalbytesRead
+=
buffer
.
Length
;
var
remainingBytes
=
(
int
)
totalBytesToRead
-
totalbytesRead
;
var
remainingBytes
=
totalBytesToRead
-
totalbytesRead
;
if
(
remainingBytes
<
bytesToRead
)
if
(
remainingBytes
<
bytesToRead
)
{
{
bytesToRead
=
remainingBytes
;
bytesToRead
=
remainingBytes
;
...
...
Titanium.Web.Proxy/Helpers/CertificateManager.cs
View file @
f387486d
...
@@ -4,15 +4,18 @@ using System.Diagnostics;
...
@@ -4,15 +4,18 @@ using System.Diagnostics;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Reflection
;
using
System.Reflection
;
using
System.Threading.Tasks
;
using
System.Threading
;
namespace
Titanium.Web.Proxy.Helpers
namespace
Titanium.Web.Proxy.Helpers
{
{
public
class
CertificateManager
:
IDisposable
public
class
CertificateManager
:
IDisposable
{
{
private
const
string
CertCreateFormat
=
private
const
string
CertCreateFormat
=
"-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 {5}"
;
"-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 {5}"
;
private
readonly
IDictionary
<
string
,
X509Certificate2
>
_certificateCache
;
private
readonly
IDictionary
<
string
,
X509Certificate2
>
_certificateCache
;
private
static
SemaphoreSlim
semaphoreLock
=
new
SemaphoreSlim
(
1
);
public
string
Issuer
{
get
;
private
set
;
}
public
string
Issuer
{
get
;
private
set
;
}
public
string
RootCertificateName
{
get
;
private
set
;
}
public
string
RootCertificateName
{
get
;
private
set
;
}
...
@@ -35,10 +38,10 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -35,10 +38,10 @@ namespace Titanium.Web.Proxy.Helpers
/// Attempts to move a self-signed certificate to the root store.
/// Attempts to move a self-signed certificate to the root store.
/// </summary>
/// </summary>
/// <returns>true if succeeded, else false</returns>
/// <returns>true if succeeded, else false</returns>
public
bool
CreateTrustedRootCertificate
()
public
async
Task
<
bool
>
CreateTrustedRootCertificate
()
{
{
X509Certificate2
rootCertificate
=
X509Certificate2
rootCertificate
=
CreateCertificate
(
RootStore
,
RootCertificateName
);
await
CreateCertificate
(
RootStore
,
RootCertificateName
);
return
rootCertificate
!=
null
;
return
rootCertificate
!=
null
;
}
}
...
@@ -46,9 +49,9 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -46,9 +49,9 @@ namespace Titanium.Web.Proxy.Helpers
/// Attempts to remove the self-signed certificate from the root store.
/// Attempts to remove the self-signed certificate from the root store.
/// </summary>
/// </summary>
/// <returns>true if succeeded, else false</returns>
/// <returns>true if succeeded, else false</returns>
public
bool
DestroyTrustedRootCertificate
()
public
async
Task
<
bool
>
DestroyTrustedRootCertificate
()
{
{
return
DestroyCertificate
(
RootStore
,
RootCertificateName
);
return
await
DestroyCertificate
(
RootStore
,
RootCertificateName
);
}
}
public
X509Certificate2Collection
FindCertificates
(
string
certificateSubject
)
public
X509Certificate2Collection
FindCertificates
(
string
certificateSubject
)
...
@@ -64,103 +67,126 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -64,103 +67,126 @@ namespace Titanium.Web.Proxy.Helpers
discoveredCertificates
:
null
;
discoveredCertificates
:
null
;
}
}
public
X509Certificate2
CreateCertificate
(
string
certificateName
)
public
async
Task
<
X509Certificate2
>
CreateCertificate
(
string
certificateName
)
{
{
return
CreateCertificate
(
MyStore
,
certificateName
);
return
await
CreateCertificate
(
MyStore
,
certificateName
);
}
}
protected
virtual
X509Certificate2
CreateCertificate
(
X509Store
store
,
string
certificateName
)
protected
async
virtual
Task
<
X509Certificate2
>
CreateCertificate
(
X509Store
store
,
string
certificateName
)
{
{
if
(
_certificateCache
.
ContainsKey
(
certificateName
))
if
(
_certificateCache
.
ContainsKey
(
certificateName
))
return
_certificateCache
[
certificateName
];
return
_certificateCache
[
certificateName
];
lock
(
store
)
await
semaphoreLock
.
WaitAsync
();
X509Certificate2
certificate
=
null
;
try
{
{
X509Certificate2
certificate
=
null
;
store
.
Open
(
OpenFlags
.
ReadWrite
);
try
string
certificateSubject
=
string
.
Format
(
"CN={0}, O={1}"
,
certificateName
,
Issuer
);
{
store
.
Open
(
OpenFlags
.
ReadWrite
);
string
certificateSubject
=
string
.
Format
(
"CN={0}, O={1}"
,
certificateName
,
Issuer
);
var
certificates
=
var
certificates
=
FindCertificates
(
store
,
certificateSubject
);
FindCertificates
(
store
,
certificateSubject
);
if
(
certificates
!=
null
)
if
(
certificates
!=
null
)
certificate
=
certificates
[
0
];
certificate
=
certificates
[
0
];
if
(
certificate
==
null
)
if
(
certificate
==
null
)
{
{
string
[]
args
=
new
[]
{
string
[]
args
=
new
[]
{
GetCertificateCreateArgs
(
store
,
certificateName
)
};
GetCertificateCreateArgs
(
store
,
certificateName
)
};
CreateCertificate
(
args
);
await
CreateCertificate
(
args
);
certificates
=
FindCertificates
(
store
,
certificateSubject
);
certificates
=
FindCertificates
(
store
,
certificateSubject
);
return
certificates
!=
null
?
return
certificates
!=
null
?
certificates
[
0
]
:
null
;
certificates
[
0
]
:
null
;
}
return
certificate
;
}
finally
{
store
.
Close
();
if
(
certificate
!=
null
&&
!
_certificateCache
.
ContainsKey
(
certificateName
))
_certificateCache
.
Add
(
certificateName
,
certificate
);
}
}
store
.
Close
();
if
(
certificate
!=
null
&&
!
_certificateCache
.
ContainsKey
(
certificateName
))
_certificateCache
.
Add
(
certificateName
,
certificate
);
return
certificate
;
}
finally
{
semaphoreLock
.
Release
();
}
}
}
}
protected
virtual
void
CreateCertificate
(
string
[]
args
)
protected
virtual
Task
<
int
>
CreateCertificate
(
string
[]
args
)
{
{
using
(
var
process
=
new
Process
())
{
string
file
=
Path
.
Combine
(
Path
.
GetDirectoryName
(
Assembly
.
GetExecutingAssembly
().
Location
),
"makecert.exe"
);
if
(!
File
.
Exists
(
file
))
// there is no non-generic TaskCompletionSource
throw
new
Exception
(
"Unable to locate 'makecert.exe'."
);
var
tcs
=
new
TaskCompletionSource
<
int
>();
var
process
=
new
Process
();
process
.
StartInfo
.
Verb
=
"runas"
;
string
file
=
Path
.
Combine
(
Path
.
GetDirectoryName
(
Assembly
.
GetExecutingAssembly
().
Location
),
"makecert.exe"
);
process
.
StartInfo
.
Arguments
=
args
!=
null
?
args
[
0
]
:
string
.
Empty
;
process
.
StartInfo
.
CreateNoWindow
=
true
;
process
.
StartInfo
.
UseShellExecute
=
false
;
process
.
StartInfo
.
FileName
=
file
;
process
.
Start
();
if
(!
File
.
Exists
(
file
))
process
.
WaitForExit
();
throw
new
Exception
(
"Unable to locate 'makecert.exe'."
);
process
.
StartInfo
.
Verb
=
"runas"
;
process
.
StartInfo
.
Arguments
=
args
!=
null
?
args
[
0
]
:
string
.
Empty
;
process
.
StartInfo
.
CreateNoWindow
=
true
;
process
.
StartInfo
.
UseShellExecute
=
false
;
process
.
StartInfo
.
FileName
=
file
;
process
.
EnableRaisingEvents
=
true
;
process
.
Exited
+=
(
sender
,
processArgs
)
=>
{
tcs
.
SetResult
(
process
.
ExitCode
);
process
.
Dispose
();
};
bool
started
=
process
.
Start
();
if
(!
started
)
{
//you may allow for the process to be re-used (started = false)
//but I'm not sure about the guarantees of the Exited event in such a case
throw
new
InvalidOperationException
(
"Could not start process: "
+
process
);
}
}
return
tcs
.
Task
;
}
}
public
bool
DestroyCertificate
(
string
certificateName
)
public
async
Task
<
bool
>
DestroyCertificate
(
string
certificateName
)
{
{
return
DestroyCertificate
(
MyStore
,
certificateName
);
return
await
DestroyCertificate
(
MyStore
,
certificateName
);
}
}
protected
virtual
bool
DestroyCertificate
(
X509Store
store
,
string
certificateName
)
protected
virtual
async
Task
<
bool
>
DestroyCertificate
(
X509Store
store
,
string
certificateName
)
{
{
lock
(
store
)
await
semaphoreLock
.
WaitAsync
();
X509Certificate2Collection
certificates
=
null
;
try
{
{
X509Certificate2Collection
certificates
=
null
;
store
.
Open
(
OpenFlags
.
ReadWrite
);
try
string
certificateSubject
=
string
.
Format
(
"CN={0}, O={1}"
,
certificateName
,
Issuer
);
{
store
.
Open
(
OpenFlags
.
ReadWrite
);
string
certificateSubject
=
string
.
Format
(
"CN={0}, O={1}"
,
certificateName
,
Issuer
);
certificates
=
FindCertificates
(
store
,
certificateSubject
);
if
(
certificates
!=
null
)
{
store
.
RemoveRange
(
certificates
);
certificates
=
FindCertificates
(
store
,
certificateSubject
);
certificates
=
FindCertificates
(
store
,
certificateSubject
);
if
(
certificates
!=
null
)
{
store
.
RemoveRange
(
certificates
);
certificates
=
FindCertificates
(
store
,
certificateSubject
);
}
return
certificates
==
null
;
}
}
finally
store
.
Close
();
if
(
certificates
==
null
&&
_certificateCache
.
ContainsKey
(
certificateName
))
{
{
store
.
Close
();
_certificateCache
.
Remove
(
certificateName
);
if
(
certificates
==
null
&&
_certificateCache
.
ContainsKey
(
certificateName
))
{
_certificateCache
.
Remove
(
certificateName
);
}
}
}
return
certificates
==
null
;
}
}
finally
{
semaphoreLock
.
Release
();
}
}
}
protected
virtual
string
GetCertificateCreateArgs
(
X509Store
store
,
string
certificateName
)
protected
virtual
string
GetCertificateCreateArgs
(
X509Store
store
,
string
certificateName
)
...
...
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
f387486d
...
@@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy.Http
{
{
public
class
HttpWebSession
public
class
HttpWebSession
{
{
internal
TcpConnection
ProxyClient
{
get
;
set
;
}
internal
TcpConnection
ServerConnection
{
get
;
set
;
}
public
Request
Request
{
get
;
set
;
}
public
Request
Request
{
get
;
set
;
}
public
Response
Response
{
get
;
set
;
}
public
Response
Response
{
get
;
set
;
}
...
@@ -27,7 +27,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -27,7 +27,7 @@ namespace Titanium.Web.Proxy.Http
internal
void
SetConnection
(
TcpConnection
Connection
)
internal
void
SetConnection
(
TcpConnection
Connection
)
{
{
Connection
.
LastAccess
=
DateTime
.
Now
;
Connection
.
LastAccess
=
DateTime
.
Now
;
ProxyClient
=
Connection
;
ServerConnection
=
Connection
;
}
}
internal
HttpWebSession
()
internal
HttpWebSession
()
...
@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy.Http
internal
async
Task
SendRequest
()
internal
async
Task
SendRequest
()
{
{
Stream
stream
=
ProxyClient
.
Stream
;
Stream
stream
=
ServerConnection
.
Stream
;
StringBuilder
requestLines
=
new
StringBuilder
();
StringBuilder
requestLines
=
new
StringBuilder
();
...
@@ -59,12 +59,12 @@ namespace Titanium.Web.Proxy.Http
...
@@ -59,12 +59,12 @@ namespace Titanium.Web.Proxy.Http
string
request
=
requestLines
.
ToString
();
string
request
=
requestLines
.
ToString
();
byte
[]
requestBytes
=
Encoding
.
ASCII
.
GetBytes
(
request
);
byte
[]
requestBytes
=
Encoding
.
ASCII
.
GetBytes
(
request
);
await
stream
.
WriteAsync
(
requestBytes
,
0
,
requestBytes
.
Length
);
await
stream
.
WriteAsync
(
requestBytes
,
0
,
requestBytes
.
Length
);
stream
.
Flush
();
await
stream
.
FlushAsync
();
if
(
ProxyServer
.
Enable100ContinueBehaviour
)
if
(
ProxyServer
.
Enable100ContinueBehaviour
)
if
(
this
.
Request
.
ExpectContinue
)
if
(
this
.
Request
.
ExpectContinue
)
{
{
var
httpResult
=
(
await
ProxyClient
.
Server
StreamReader
.
ReadLineAsync
()).
Split
(
Constants
.
SpaceSplit
,
3
);
var
httpResult
=
(
await
ServerConnection
.
StreamReader
.
ReadLineAsync
()).
Split
(
Constants
.
SpaceSplit
,
3
);
var
responseStatusCode
=
httpResult
[
1
].
Trim
();
var
responseStatusCode
=
httpResult
[
1
].
Trim
();
var
responseStatusDescription
=
httpResult
[
2
].
Trim
();
var
responseStatusDescription
=
httpResult
[
2
].
Trim
();
...
@@ -73,13 +73,13 @@ namespace Titanium.Web.Proxy.Http
...
@@ -73,13 +73,13 @@ namespace Titanium.Web.Proxy.Http
&&
responseStatusDescription
.
ToLower
().
Equals
(
"continue"
))
&&
responseStatusDescription
.
ToLower
().
Equals
(
"continue"
))
{
{
this
.
Request
.
Is100Continue
=
true
;
this
.
Request
.
Is100Continue
=
true
;
await
ProxyClient
.
Server
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
ServerConnection
.
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
}
}
else
if
(
responseStatusCode
.
Equals
(
"417"
)
else
if
(
responseStatusCode
.
Equals
(
"417"
)
&&
responseStatusDescription
.
ToLower
().
Equals
(
"expectation failed"
))
&&
responseStatusDescription
.
ToLower
().
Equals
(
"expectation failed"
))
{
{
this
.
Request
.
ExpectationFailed
=
true
;
this
.
Request
.
ExpectationFailed
=
true
;
await
ProxyClient
.
Server
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
ServerConnection
.
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
}
}
}
}
}
}
...
@@ -89,11 +89,11 @@ namespace Titanium.Web.Proxy.Http
...
@@ -89,11 +89,11 @@ namespace Titanium.Web.Proxy.Http
//return if this is already read
//return if this is already read
if
(
this
.
Response
.
ResponseStatusCode
!=
null
)
return
;
if
(
this
.
Response
.
ResponseStatusCode
!=
null
)
return
;
var
httpResult
=
(
await
ProxyClient
.
Server
StreamReader
.
ReadLineAsync
()).
Split
(
Constants
.
SpaceSplit
,
3
);
var
httpResult
=
(
await
ServerConnection
.
StreamReader
.
ReadLineAsync
()).
Split
(
Constants
.
SpaceSplit
,
3
);
if
(
string
.
IsNullOrEmpty
(
httpResult
[
0
]))
if
(
string
.
IsNullOrEmpty
(
httpResult
[
0
]))
{
{
await
ProxyClient
.
Server
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
ServerConnection
.
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
}
}
this
.
Response
.
HttpVersion
=
httpResult
[
0
].
Trim
();
this
.
Response
.
HttpVersion
=
httpResult
[
0
].
Trim
();
...
@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Http
{
{
this
.
Response
.
Is100Continue
=
true
;
this
.
Response
.
Is100Continue
=
true
;
this
.
Response
.
ResponseStatusCode
=
null
;
this
.
Response
.
ResponseStatusCode
=
null
;
await
ProxyClient
.
Server
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
ServerConnection
.
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
ReceiveResponse
();
await
ReceiveResponse
();
return
;
return
;
}
}
...
@@ -115,12 +115,12 @@ namespace Titanium.Web.Proxy.Http
...
@@ -115,12 +115,12 @@ namespace Titanium.Web.Proxy.Http
{
{
this
.
Response
.
ExpectationFailed
=
true
;
this
.
Response
.
ExpectationFailed
=
true
;
this
.
Response
.
ResponseStatusCode
=
null
;
this
.
Response
.
ResponseStatusCode
=
null
;
await
ProxyClient
.
Server
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
ServerConnection
.
StreamReader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
ReceiveResponse
();
await
ReceiveResponse
();
return
;
return
;
}
}
List
<
string
>
responseLines
=
await
ProxyClient
.
Server
StreamReader
.
ReadAllLinesAsync
().
ConfigureAwait
(
false
);
List
<
string
>
responseLines
=
await
ServerConnection
.
StreamReader
.
ReadAllLinesAsync
().
ConfigureAwait
(
false
);
for
(
int
index
=
0
;
index
<
responseLines
.
Count
;
++
index
)
for
(
int
index
=
0
;
index
<
responseLines
.
Count
;
++
index
)
{
{
...
...
Titanium.Web.Proxy/Http/Response.cs
View file @
f387486d
...
@@ -13,22 +13,9 @@ namespace Titanium.Web.Proxy.Http
...
@@ -13,22 +13,9 @@ namespace Titanium.Web.Proxy.Http
public
string
ResponseStatusCode
{
get
;
set
;
}
public
string
ResponseStatusCode
{
get
;
set
;
}
public
string
ResponseStatusDescription
{
get
;
set
;
}
public
string
ResponseStatusDescription
{
get
;
set
;
}
internal
Encoding
Encoding
{
get
{
return
this
.
GetResponseEncoding
();
}
}
internal
Encoding
Encoding
{
get
{
return
this
.
GetResponse
Character
Encoding
();
}
}
internal
string
CharacterSet
{
get
{
if
(
this
.
ContentType
.
Contains
(
";"
))
{
return
this
.
ContentType
.
Split
(
';'
)[
1
].
Substring
(
9
).
Trim
();
}
return
null
;
}
}
internal
string
ContentEncoding
internal
string
ContentEncoding
{
{
get
get
...
@@ -69,13 +56,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -69,13 +56,7 @@ namespace Titanium.Web.Proxy.Http
if
(
header
!=
null
)
if
(
header
!=
null
)
{
{
if
(
header
.
Value
.
Contains
(
";"
))
return
header
.
Value
;
{
return
header
.
Value
.
Split
(
';'
)[
0
].
Trim
();
}
else
return
header
.
Value
.
ToLower
().
Trim
();
}
}
return
null
;
return
null
;
...
...
Titanium.Web.Proxy/
EventArguments
/ProxyClient.cs
→
Titanium.Web.Proxy/
Network
/ProxyClient.cs
View file @
f387486d
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
using
System.Net.Sockets
;
using
System.Net.Sockets
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers
;
namespace
Titanium.Web.Proxy.
EventArguments
namespace
Titanium.Web.Proxy.
Network
{
{
/// <summary>
/// <summary>
/// This class wraps Tcp connection to Server
/// This class wraps Tcp connection to Server
...
...
Titanium.Web.Proxy/Network/TcpConnectionManager.cs
View file @
f387486d
...
@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Network
internal
Version
Version
{
get
;
set
;
}
internal
Version
Version
{
get
;
set
;
}
internal
TcpClient
TcpClient
{
get
;
set
;
}
internal
TcpClient
TcpClient
{
get
;
set
;
}
internal
CustomBinaryReader
S
erverS
treamReader
{
get
;
set
;
}
internal
CustomBinaryReader
StreamReader
{
get
;
set
;
}
internal
Stream
Stream
{
get
;
set
;
}
internal
Stream
Stream
{
get
;
set
;
}
internal
DateTime
LastAccess
{
get
;
set
;
}
internal
DateTime
LastAccess
{
get
;
set
;
}
...
@@ -88,21 +88,25 @@ namespace Titanium.Web.Proxy.Network
...
@@ -88,21 +88,25 @@ namespace Titanium.Web.Proxy.Network
client
=
new
TcpClient
(
ProxyServer
.
UpStreamHttpsProxy
.
HostName
,
ProxyServer
.
UpStreamHttpsProxy
.
Port
);
client
=
new
TcpClient
(
ProxyServer
.
UpStreamHttpsProxy
.
HostName
,
ProxyServer
.
UpStreamHttpsProxy
.
Port
);
stream
=
(
Stream
)
client
.
GetStream
();
stream
=
(
Stream
)
client
.
GetStream
();
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
Constants
.
BUFFER_SIZE
,
true
);
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
Constants
.
BUFFER_SIZE
,
true
))
{
writer
.
WriteLine
(
string
.
Format
(
"CONNECT {0}:{1} {2}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Port
,
sessionArgs
.
WebSession
.
Request
.
HttpVersion
));
await
writer
.
WriteLineAsync
(
string
.
Format
(
"CONNECT {0}:{1} {2}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Port
,
sessionArgs
.
WebSession
.
Request
.
HttpVersion
));
writer
.
WriteLine
(
string
.
Format
(
"Host: {0}:{1}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Port
));
await
writer
.
WriteLineAsync
(
string
.
Format
(
"Host: {0}:{1}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Port
));
writer
.
WriteLine
(
"Connection: Keep-Alive"
);
await
writer
.
WriteLineAsync
(
"Connection: Keep-Alive"
);
writer
.
WriteLine
();
await
writer
.
WriteLineAsync
();
writer
.
Flush
();
await
writer
.
FlushAsync
();
writer
.
Close
();
var
reader
=
new
CustomBinaryReader
(
stream
);
}
var
result
=
await
reader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
using
(
var
reader
=
new
CustomBinaryReader
(
stream
))
if
(!
result
.
ToLower
().
Contains
(
"200 connection established"
))
{
throw
new
Exception
(
"Upstream proxy failed to create a secure tunnel"
);
var
result
=
await
reader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
await
reader
.
ReadAllLinesAsync
().
ConfigureAwait
(
false
);
if
(!
result
.
ToLower
().
Contains
(
"200 connection established"
))
throw
new
Exception
(
"Upstream proxy failed to create a secure tunnel"
);
await
reader
.
ReadAllLinesAsync
().
ConfigureAwait
(
false
);
}
}
}
else
else
{
{
...
@@ -144,7 +148,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -144,7 +148,7 @@ namespace Titanium.Web.Proxy.Network
port
=
port
,
port
=
port
,
IsSecure
=
isSecure
,
IsSecure
=
isSecure
,
TcpClient
=
client
,
TcpClient
=
client
,
S
erverS
treamReader
=
new
CustomBinaryReader
(
stream
),
StreamReader
=
new
CustomBinaryReader
(
stream
),
Stream
=
stream
,
Stream
=
stream
,
Version
=
version
Version
=
version
};
};
...
@@ -178,6 +182,5 @@ namespace Titanium.Web.Proxy.Network
...
@@ -178,6 +182,5 @@ namespace Titanium.Web.Proxy.Network
}
}
}
}
}
}
Titanium.Web.Proxy/ProxyServer.cs
View file @
f387486d
...
@@ -154,7 +154,7 @@ namespace Titanium.Web.Proxy
...
@@ -154,7 +154,7 @@ namespace Titanium.Web.Proxy
CertManager
=
new
CertificateManager
(
RootCertificateIssuerName
,
CertManager
=
new
CertificateManager
(
RootCertificateIssuerName
,
RootCertificateName
);
RootCertificateName
);
certTrusted
=
CertManager
.
CreateTrustedRootCertificate
();
certTrusted
=
CertManager
.
CreateTrustedRootCertificate
()
.
Result
;
foreach
(
var
endPoint
in
ProxyEndPoints
)
foreach
(
var
endPoint
in
ProxyEndPoints
)
{
{
...
@@ -222,18 +222,21 @@ namespace Titanium.Web.Proxy
...
@@ -222,18 +222,21 @@ namespace Titanium.Web.Proxy
{
{
var
client
=
endPoint
.
listener
.
EndAcceptTcpClient
(
asyn
);
var
client
=
endPoint
.
listener
.
EndAcceptTcpClient
(
asyn
);
if
(
endPoint
.
GetType
()
==
typeof
(
TransparentProxyEndPoint
))
if
(
endPoint
.
GetType
()
==
typeof
(
TransparentProxyEndPoint
))
Task
.
Factory
.
StartNew
(()
=>
HandleClient
(
endPoint
as
TransparentProxyEndPoint
,
client
)
);
HandleClient
(
endPoint
as
TransparentProxyEndPoint
,
client
);
else
else
Task
.
Factory
.
StartNew
(()
=>
HandleClient
(
endPoint
as
ExplicitProxyEndPoint
,
client
)
);
HandleClient
(
endPoint
as
ExplicitProxyEndPoint
,
client
);
// Get the listener that handles the client request.
// Get the listener that handles the client request.
endPoint
.
listener
.
BeginAcceptTcpClient
(
OnAcceptConnection
,
endPoint
);
endPoint
.
listener
.
BeginAcceptTcpClient
(
OnAcceptConnection
,
endPoint
);
}
}
catch
catch
(
ObjectDisposedException
)
{
{
// ignored
// The listener was Stop()'d, disposing the underlying socket and
// triggering the completion of the callback. We're already exiting,
// so just return.
return
;
}
}
}
}
}
}
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
f387486d
...
@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy
...
@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy
await
WriteConnectResponse
(
clientStreamWriter
,
httpVersion
).
ConfigureAwait
(
false
);
await
WriteConnectResponse
(
clientStreamWriter
,
httpVersion
).
ConfigureAwait
(
false
);
var
certificate
=
CertManager
.
CreateCertificate
(
httpRemoteUri
.
Host
);
var
certificate
=
await
CertManager
.
CreateCertificate
(
httpRemoteUri
.
Host
);
SslStream
sslStream
=
null
;
SslStream
sslStream
=
null
;
...
@@ -139,7 +139,7 @@ namespace Titanium.Web.Proxy
...
@@ -139,7 +139,7 @@ namespace Titanium.Web.Proxy
// certificate = CertManager.CreateCertificate(hostName);
// certificate = CertManager.CreateCertificate(hostName);
//}
//}
//else
//else
certificate
=
CertManager
.
CreateCertificate
(
endPoint
.
GenericCertificateName
);
certificate
=
await
CertManager
.
CreateCertificate
(
endPoint
.
GenericCertificateName
);
try
try
{
{
...
@@ -281,13 +281,13 @@ namespace Titanium.Web.Proxy
...
@@ -281,13 +281,13 @@ namespace Titanium.Web.Proxy
{
{
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
Client
.
ClientStreamWriter
);
"Continue"
,
args
.
Client
.
ClientStreamWriter
);
a
rgs
.
Client
.
ClientStreamWriter
.
WriteLine
();
a
wait
args
.
Client
.
ClientStreamWriter
.
WriteLineAsync
();
}
}
else
if
(
args
.
WebSession
.
Request
.
ExpectationFailed
)
else
if
(
args
.
WebSession
.
Request
.
ExpectationFailed
)
{
{
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
Client
.
ClientStreamWriter
);
"Expectation Failed"
,
args
.
Client
.
ClientStreamWriter
);
args
.
Client
.
ClientStreamWriter
.
WriteLine
();
await
args
.
Client
.
ClientStreamWriter
.
WriteLineAsync
();
}
}
if
(!
args
.
WebSession
.
Request
.
ExpectContinue
)
if
(!
args
.
WebSession
.
Request
.
ExpectContinue
)
...
@@ -299,8 +299,14 @@ namespace Titanium.Web.Proxy
...
@@ -299,8 +299,14 @@ namespace Titanium.Web.Proxy
//If request was modified by user
//If request was modified by user
if
(
args
.
WebSession
.
Request
.
RequestBodyRead
)
if
(
args
.
WebSession
.
Request
.
RequestBodyRead
)
{
{
if
(
args
.
WebSession
.
Request
.
ContentEncoding
!=
null
)
{
args
.
WebSession
.
Request
.
RequestBody
=
await
GetCompressedResponseBody
(
args
.
WebSession
.
Request
.
ContentEncoding
,
args
.
WebSession
.
Request
.
RequestBody
);
}
args
.
WebSession
.
Request
.
ContentLength
=
args
.
WebSession
.
Request
.
RequestBody
.
Length
;
args
.
WebSession
.
Request
.
ContentLength
=
args
.
WebSession
.
Request
.
RequestBody
.
Length
;
var
newStream
=
args
.
WebSession
.
ProxyClient
.
Stream
;
var
newStream
=
args
.
WebSession
.
ServerConnection
.
Stream
;
await
newStream
.
WriteAsync
(
args
.
WebSession
.
Request
.
RequestBody
,
0
,
args
.
WebSession
.
Request
.
RequestBody
.
Length
).
ConfigureAwait
(
false
);
await
newStream
.
WriteAsync
(
args
.
WebSession
.
Request
.
RequestBody
,
0
,
args
.
WebSession
.
Request
.
RequestBody
.
Length
).
ConfigureAwait
(
false
);
}
}
else
else
...
@@ -392,7 +398,7 @@ namespace Titanium.Web.Proxy
...
@@ -392,7 +398,7 @@ namespace Titanium.Web.Proxy
private
static
async
Task
SendClientRequestBody
(
SessionEventArgs
args
)
private
static
async
Task
SendClientRequestBody
(
SessionEventArgs
args
)
{
{
// End the operation
// End the operation
var
postStream
=
args
.
WebSession
.
ProxyClient
.
Stream
;
var
postStream
=
args
.
WebSession
.
ServerConnection
.
Stream
;
if
(
args
.
WebSession
.
Request
.
ContentLength
>
0
)
if
(
args
.
WebSession
.
Request
.
ContentLength
>
0
)
{
{
...
@@ -466,8 +472,6 @@ namespace Titanium.Web.Proxy
...
@@ -466,8 +472,6 @@ namespace Titanium.Web.Proxy
if
(
sslPolicyErrors
==
SslPolicyErrors
.
None
)
if
(
sslPolicyErrors
==
SslPolicyErrors
.
None
)
return
true
;
return
true
;
Console
.
WriteLine
(
"Certificate error: {0}"
,
sslPolicyErrors
);
//By default
//By default
//do not allow this client to communicate with unauthenticated servers.
//do not allow this client to communicate with unauthenticated servers.
return
false
;
return
false
;
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
f387486d
...
@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy
...
@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy
try
try
{
{
if
(!
args
.
WebSession
.
Response
.
ResponseBodyRead
)
if
(!
args
.
WebSession
.
Response
.
ResponseBodyRead
)
args
.
WebSession
.
Response
.
ResponseStream
=
args
.
WebSession
.
ProxyClient
.
Stream
;
args
.
WebSession
.
Response
.
ResponseStream
=
args
.
WebSession
.
ServerConnection
.
Stream
;
if
(
BeforeResponse
!=
null
&&
!
args
.
WebSession
.
Response
.
ResponseLocked
)
if
(
BeforeResponse
!=
null
&&
!
args
.
WebSession
.
Response
.
ResponseLocked
)
...
@@ -46,13 +46,13 @@ namespace Titanium.Web.Proxy
...
@@ -46,13 +46,13 @@ namespace Titanium.Web.Proxy
{
{
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
Client
.
ClientStreamWriter
);
"Continue"
,
args
.
Client
.
ClientStreamWriter
);
a
rgs
.
Client
.
ClientStreamWriter
.
WriteLine
();
a
wait
args
.
Client
.
ClientStreamWriter
.
WriteLineAsync
();
}
}
else
if
(
args
.
WebSession
.
Response
.
ExpectationFailed
)
else
if
(
args
.
WebSession
.
Response
.
ExpectationFailed
)
{
{
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
Client
.
ClientStreamWriter
);
"Expectation Failed"
,
args
.
Client
.
ClientStreamWriter
);
a
rgs
.
Client
.
ClientStreamWriter
.
WriteLine
();
a
wait
args
.
Client
.
ClientStreamWriter
.
WriteLineAsync
();
}
}
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
args
.
WebSession
.
Response
.
ResponseStatusCode
,
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
args
.
WebSession
.
Response
.
ResponseStatusCode
,
...
@@ -68,19 +68,20 @@ namespace Titanium.Web.Proxy
...
@@ -68,19 +68,20 @@ namespace Titanium.Web.Proxy
args
.
WebSession
.
Response
.
ResponseBody
=
await
GetCompressedResponseBody
(
contentEncoding
,
args
.
WebSession
.
Response
.
ResponseBody
).
ConfigureAwait
(
false
);
args
.
WebSession
.
Response
.
ResponseBody
=
await
GetCompressedResponseBody
(
contentEncoding
,
args
.
WebSession
.
Response
.
ResponseBody
).
ConfigureAwait
(
false
);
}
}
await
WriteResponseHeaders
(
args
.
Client
.
ClientStreamWriter
,
args
.
WebSession
.
Response
.
ResponseHeaders
,
args
.
WebSession
.
Response
.
ResponseBody
.
Length
,
args
.
WebSession
.
Response
.
ContentLength
=
args
.
WebSession
.
Response
.
ResponseBody
.
Length
;
isChunked
).
ConfigureAwait
(
false
);
await
WriteResponseBody
(
args
.
Client
.
ClientStream
,
args
.
WebSession
.
Response
.
ResponseBody
,
isChunked
).
ConfigureAwait
(
false
);
await
WriteResponseHeaders
(
args
.
Client
.
ClientStreamWriter
,
args
.
WebSession
.
Response
.
ResponseHeaders
).
ConfigureAwait
(
false
);
await
WriteResponseBody
(
args
.
Client
.
ClientStream
,
args
.
WebSession
.
Response
.
ResponseBody
,
isChunked
).
ConfigureAwait
(
false
);
}
}
else
else
{
{
WriteResponseHeaders
(
args
.
Client
.
ClientStreamWriter
,
args
.
WebSession
.
Response
.
ResponseHeaders
);
await
WriteResponseHeaders
(
args
.
Client
.
ClientStreamWriter
,
args
.
WebSession
.
Response
.
ResponseHeaders
);
if
(
args
.
WebSession
.
Response
.
IsChunked
||
args
.
WebSession
.
Response
.
ContentLength
>
0
)
if
(
args
.
WebSession
.
Response
.
IsChunked
||
args
.
WebSession
.
Response
.
ContentLength
>
0
||
args
.
WebSession
.
Response
.
HttpVersion
.
ToLower
().
Trim
()
==
"http/1.0"
)
await
WriteResponseBody
(
args
.
WebSession
.
ProxyClient
.
Server
StreamReader
,
args
.
Client
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
).
ConfigureAwait
(
false
);
await
WriteResponseBody
(
args
.
WebSession
.
ServerConnection
.
StreamReader
,
args
.
Client
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
).
ConfigureAwait
(
false
);
}
}
a
rgs
.
Client
.
ClientStream
.
Flush
();
a
wait
args
.
Client
.
ClientStream
.
FlushAsync
();
}
}
catch
catch
...
@@ -104,10 +105,10 @@ namespace Titanium.Web.Proxy
...
@@ -104,10 +105,10 @@ namespace Titanium.Web.Proxy
private
static
void
WriteResponseStatus
(
string
version
,
string
code
,
string
description
,
private
static
void
WriteResponseStatus
(
string
version
,
string
code
,
string
description
,
StreamWriter
responseWriter
)
StreamWriter
responseWriter
)
{
{
responseWriter
.
WriteLine
(
string
.
Format
(
"{0} {1} {2}"
,
version
,
code
,
description
));
responseWriter
.
WriteLine
Async
(
string
.
Format
(
"{0} {1} {2}"
,
version
,
code
,
description
));
}
}
private
static
void
WriteResponseHeaders
(
StreamWriter
responseWriter
,
List
<
HttpHeader
>
headers
)
private
static
async
Task
WriteResponseHeaders
(
StreamWriter
responseWriter
,
List
<
HttpHeader
>
headers
)
{
{
if
(
headers
!=
null
)
if
(
headers
!=
null
)
{
{
...
@@ -115,12 +116,12 @@ namespace Titanium.Web.Proxy
...
@@ -115,12 +116,12 @@ namespace Titanium.Web.Proxy
foreach
(
var
header
in
headers
)
foreach
(
var
header
in
headers
)
{
{
responseWriter
.
WriteLine
(
header
.
ToString
());
await
responseWriter
.
WriteLineAsync
(
header
.
ToString
());
}
}
}
}
responseWriter
.
WriteLine
();
await
responseWriter
.
WriteLineAsync
();
responseWriter
.
Flush
();
await
responseWriter
.
FlushAsync
();
}
}
private
static
void
FixResponseProxyHeaders
(
List
<
HttpHeader
>
headers
)
private
static
void
FixResponseProxyHeaders
(
List
<
HttpHeader
>
headers
)
{
{
...
@@ -141,34 +142,6 @@ namespace Titanium.Web.Proxy
...
@@ -141,34 +142,6 @@ namespace Titanium.Web.Proxy
headers
.
RemoveAll
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
headers
.
RemoveAll
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
}
}
private
static
async
Task
WriteResponseHeaders
(
StreamWriter
responseWriter
,
List
<
HttpHeader
>
headers
,
int
length
,
bool
isChunked
)
{
FixResponseProxyHeaders
(
headers
);
if
(!
isChunked
)
{
if
(
headers
.
Any
(
x
=>
x
.
Name
.
ToLower
()
==
"content-length"
)
==
false
)
{
headers
.
Add
(
new
HttpHeader
(
"Content-Length"
,
length
.
ToString
()));
}
}
if
(
headers
!=
null
)
{
foreach
(
var
header
in
headers
)
{
if
(!
isChunked
&&
header
.
Name
.
ToLower
()
==
"content-length"
)
header
.
Value
=
length
.
ToString
();
await
responseWriter
.
WriteLineAsync
(
header
.
ToString
()).
ConfigureAwait
(
false
);
}
}
await
responseWriter
.
WriteLineAsync
().
ConfigureAwait
(
false
);
await
responseWriter
.
FlushAsync
().
ConfigureAwait
(
false
);
}
private
static
async
Task
WriteResponseBody
(
Stream
clientStream
,
byte
[]
data
,
bool
isChunked
)
private
static
async
Task
WriteResponseBody
(
Stream
clientStream
,
byte
[]
data
,
bool
isChunked
)
{
{
if
(!
isChunked
)
if
(!
isChunked
)
...
@@ -183,6 +156,10 @@ namespace Titanium.Web.Proxy
...
@@ -183,6 +156,10 @@ namespace Titanium.Web.Proxy
{
{
if
(!
isChunked
)
if
(!
isChunked
)
{
{
//http 1.0
if
(
ContentLength
==
-
1
)
ContentLength
=
long
.
MaxValue
;
int
bytesToRead
=
Constants
.
BUFFER_SIZE
;
int
bytesToRead
=
Constants
.
BUFFER_SIZE
;
if
(
ContentLength
<
Constants
.
BUFFER_SIZE
)
if
(
ContentLength
<
Constants
.
BUFFER_SIZE
)
...
...
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
f387486d
...
@@ -61,7 +61,7 @@
...
@@ -61,7 +61,7 @@
<Compile
Include=
"Decompression\IDecompression.cs"
/>
<Compile
Include=
"Decompression\IDecompression.cs"
/>
<Compile
Include=
"Decompression\ZlibDecompression.cs"
/>
<Compile
Include=
"Decompression\ZlibDecompression.cs"
/>
<Compile
Include=
"EventArguments\CertificateValidationEventArgs.cs"
/>
<Compile
Include=
"EventArguments\CertificateValidationEventArgs.cs"
/>
<Compile
Include=
"
EventArguments
\ProxyClient.cs"
/>
<Compile
Include=
"
Network
\ProxyClient.cs"
/>
<Compile
Include=
"Exceptions\BodyNotFoundException.cs"
/>
<Compile
Include=
"Exceptions\BodyNotFoundException.cs"
/>
<Compile
Include=
"Extensions\HttpWebResponseExtensions.cs"
/>
<Compile
Include=
"Extensions\HttpWebResponseExtensions.cs"
/>
<Compile
Include=
"Extensions\HttpWebRequestExtensions.cs"
/>
<Compile
Include=
"Extensions\HttpWebRequestExtensions.cs"
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment