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
55312330
Commit
55312330
authored
Oct 22, 2016
by
Hakan Arıcı
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* PAC/WAPD script handling implementation
* Various code refactorings
parent
a9d1011b
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
681 additions
and
659 deletions
+681
-659
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+447
-448
Tcp.cs
Titanium.Web.Proxy/Helpers/Tcp.cs
+192
-195
TcpConnection.cs
Titanium.Web.Proxy/Network/TcpConnection.cs
+1
-1
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/TcpConnectionFactory.cs
+5
-8
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+34
-1
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+2
-6
No files found.
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
55312330
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.IO
;
using
System.Text
;
using
System.Text
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.Decompression
;
using
Titanium.Web.Proxy.Decompression
;
using
Titanium.Web.Proxy.Http
;
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
;
using
Titanium.Web.Proxy.Network
;
using
System.Net
;
using
System.Net
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy.EventArguments
namespace
Titanium.Web.Proxy.EventArguments
{
{
/// <summary>
/// <summary>
/// Holds info related to a single proxy session (single request/response sequence)
/// Holds info related to a single proxy session (single request/response sequence)
/// A proxy session is bounded to a single connection from client
/// A proxy session is bounded to a single connection from client
/// A proxy session ends when client terminates connection to proxy
/// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy
/// or when server terminates connection from proxy
/// </summary>
/// </summary>
public
class
SessionEventArgs
:
EventArgs
,
IDisposable
public
class
SessionEventArgs
:
EventArgs
,
IDisposable
{
{
/// <summary>
/// <summary>
/// Size of Buffers used by this object
/// Size of Buffers used by this object
/// </summary>
/// </summary>
private
readonly
int
bufferSize
;
private
readonly
int
bufferSize
;
/// <summary>
/// <summary>
/// Holds a reference to proxy response handler method
/// Holds a reference to proxy response handler method
/// </summary>
/// </summary>
private
readonly
Func
<
SessionEventArgs
,
Task
>
httpResponseHandler
;
private
readonly
Func
<
SessionEventArgs
,
Task
>
httpResponseHandler
;
/// <summary>
/// <summary>
/// Holds a reference to client
/// Holds a reference to client
/// </summary>
/// </summary>
internal
ProxyClient
ProxyClient
{
get
;
set
;
}
internal
ProxyClient
ProxyClient
{
get
;
set
;
}
//Should we send a rerequest
//Should we send a rerequest
public
bool
ReRequest
public
bool
ReRequest
{
{
get
;
get
;
set
;
set
;
}
}
/// <summary>
/// <summary>
/// Does this session uses SSL
/// Does this session uses SSL
/// </summary>
/// </summary>
public
bool
IsHttps
=>
WebSession
.
Request
.
RequestUri
.
Scheme
==
Uri
.
UriSchemeHttps
;
public
bool
IsHttps
=>
WebSession
.
Request
.
RequestUri
.
Scheme
==
Uri
.
UriSchemeHttps
;
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
ProxyClient
.
TcpClient
.
Client
.
RemoteEndPoint
;
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
ProxyClient
.
TcpClient
.
Client
.
RemoteEndPoint
;
/// <summary>
/// <summary>
/// A web session corresponding to a single request/response sequence
/// A web session corresponding to a single request/response sequence
/// within a proxy connection
/// within a proxy connection
/// </summary>
/// </summary>
public
HttpWebClient
WebSession
{
get
;
set
;
}
public
HttpWebClient
WebSession
{
get
;
set
;
}
public
ExternalProxy
CustomUpStreamHttpProxyUsed
{
get
;
set
;
}
public
ExternalProxy
CustomUpStreamHttpProxyUsed
{
get
;
set
;
}
public
ExternalProxy
CustomUpStreamHttpsProxyUsed
{
get
;
set
;
}
public
ExternalProxy
CustomUpStreamHttpsProxyUsed
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Constructor to initialize the proxy
/// Constructor to initialize the proxy
/// </summary>
/// </summary>
internal
SessionEventArgs
(
int
bufferSize
,
Func
<
SessionEventArgs
,
Task
>
httpResponseHandler
)
internal
SessionEventArgs
(
int
bufferSize
,
Func
<
SessionEventArgs
,
Task
>
httpResponseHandler
)
{
{
this
.
bufferSize
=
bufferSize
;
this
.
bufferSize
=
bufferSize
;
this
.
httpResponseHandler
=
httpResponseHandler
;
this
.
httpResponseHandler
=
httpResponseHandler
;
ProxyClient
=
new
ProxyClient
();
ProxyClient
=
new
ProxyClient
();
WebSession
=
new
HttpWebClient
();
WebSession
=
new
HttpWebClient
();
}
}
/// <summary>
/// <summary>
/// Read request body content as bytes[] for current session
/// Read request body content as bytes[] for current session
/// </summary>
/// </summary>
private
async
Task
ReadRequestBody
()
private
async
Task
ReadRequestBody
()
{
{
//GET request don't have a request body to read
//GET request don't have a request body to read
if
((
WebSession
.
Request
.
Method
.
ToUpper
()
!=
"POST"
&&
WebSession
.
Request
.
Method
.
ToUpper
()
!=
"PUT"
))
if
((
WebSession
.
Request
.
Method
.
ToUpper
()
!=
"POST"
&&
WebSession
.
Request
.
Method
.
ToUpper
()
!=
"PUT"
))
{
{
throw
new
BodyNotFoundException
(
"Request don't have a body."
+
throw
new
BodyNotFoundException
(
"Request don't have a body."
+
"Please verify that this request is a Http POST/PUT and request "
+
"Please verify that this request is a Http POST/PUT and request "
+
"content length is greater than zero before accessing the body."
);
"content length is greater than zero before accessing the body."
);
}
}
//Caching check
//Caching check
if
(
WebSession
.
Request
.
RequestBody
==
null
)
if
(
WebSession
.
Request
.
RequestBody
==
null
)
{
{
//If chunked then its easy just read the whole body with the content length mentioned in the request header
//If chunked then its easy just read the whole body with the content length mentioned in the request header
using
(
var
requestBodyStream
=
new
MemoryStream
())
using
(
var
requestBodyStream
=
new
MemoryStream
())
{
{
//For chunked request we need to read data as they arrive, until we reach a chunk end symbol
//For chunked request we need to read data as they arrive, until we reach a chunk end symbol
if
(
WebSession
.
Request
.
IsChunked
)
if
(
WebSession
.
Request
.
IsChunked
)
{
{
await
this
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStreamChunked
(
bufferSize
,
requestBodyStream
);
await
this
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStreamChunked
(
bufferSize
,
requestBodyStream
);
}
}
else
else
{
{
//If not chunked then its easy just read the whole body with the content length mentioned in the request header
//If not chunked then its easy just read the whole body with the content length mentioned in the request header
if
(
WebSession
.
Request
.
ContentLength
>
0
)
if
(
WebSession
.
Request
.
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
this
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStream
(
bufferSize
,
requestBodyStream
,
await
this
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStream
(
bufferSize
,
requestBodyStream
,
WebSession
.
Request
.
ContentLength
);
WebSession
.
Request
.
ContentLength
);
}
}
else
if
(
WebSession
.
Request
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Request
.
HttpVersion
.
Minor
==
0
)
else
if
(
WebSession
.
Request
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Request
.
HttpVersion
.
Minor
==
0
)
{
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
requestBodyStream
,
long
.
MaxValue
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
requestBodyStream
,
long
.
MaxValue
);
}
}
}
}
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
requestBodyStream
.
ToArray
());
requestBodyStream
.
ToArray
());
}
}
//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>
/// Read response body as byte[] for current response
/// Read response body as byte[] for current response
/// </summary>
/// </summary>
private
async
Task
ReadResponseBody
()
private
async
Task
ReadResponseBody
()
{
{
//If not already read (not cached yet)
//If not already read (not cached yet)
if
(
WebSession
.
Response
.
ResponseBody
==
null
)
if
(
WebSession
.
Response
.
ResponseBody
==
null
)
{
{
using
(
var
responseBodyStream
=
new
MemoryStream
())
using
(
var
responseBodyStream
=
new
MemoryStream
())
{
{
//If chuncked the read chunk by chunk until we hit chunk end symbol
//If chuncked the read chunk by chunk until we hit chunk end symbol
if
(
WebSession
.
Response
.
IsChunked
)
if
(
WebSession
.
Response
.
IsChunked
)
{
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStreamChunked
(
bufferSize
,
responseBodyStream
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStreamChunked
(
bufferSize
,
responseBodyStream
);
}
}
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
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
WebSession
.
Response
.
ContentLength
);
WebSession
.
Response
.
ContentLength
);
}
}
else
if
((
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
||
WebSession
.
Response
.
ContentLength
==
-
1
)
else
if
((
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
||
WebSession
.
Response
.
ContentLength
==
-
1
)
{
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
long
.
MaxValue
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
long
.
MaxValue
);
}
}
}
}
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
());
responseBodyStream
.
ToArray
());
}
}
//set this to true for caching
//set this to true for caching
WebSession
.
Response
.
ResponseBodyRead
=
true
;
WebSession
.
Response
.
ResponseBodyRead
=
true
;
}
}
}
}
/// <summary>
/// <summary>
/// Gets the request body as bytes
/// Gets the request body as bytes
/// </summary>
/// </summary>
/// <returns></returns>
/// <returns></returns>
public
async
Task
<
byte
[
]>
GetRequestBody
()
public
async
Task
<
byte
[
]>
GetRequestBody
()
{
{
if
(!
WebSession
.
Request
.
RequestBodyRead
)
if
(!
WebSession
.
Request
.
RequestBodyRead
)
{
{
if
(
WebSession
.
Request
.
RequestLocked
)
if
(
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
}
}
await
ReadRequestBody
();
await
ReadRequestBody
();
}
}
return
WebSession
.
Request
.
RequestBody
;
return
WebSession
.
Request
.
RequestBody
;
}
}
/// <summary>
/// <summary>
/// Gets the request body as string
/// Gets the request body as string
/// </summary>
/// </summary>
/// <returns></returns>
/// <returns></returns>
public
async
Task
<
string
>
GetRequestBodyAsString
()
public
async
Task
<
string
>
GetRequestBodyAsString
()
{
{
if
(!
WebSession
.
Request
.
RequestBodyRead
)
if
(!
WebSession
.
Request
.
RequestBodyRead
)
{
{
if
(
WebSession
.
Request
.
RequestLocked
)
if
(
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
}
}
await
ReadRequestBody
();
await
ReadRequestBody
();
}
}
//Use the encoding specified in request to decode the byte[] data to string
//Use the encoding specified in request to decode the byte[] data to string
return
WebSession
.
Request
.
RequestBodyString
??
(
WebSession
.
Request
.
RequestBodyString
=
WebSession
.
Request
.
Encoding
.
GetString
(
WebSession
.
Request
.
RequestBody
));
return
WebSession
.
Request
.
RequestBodyString
??
(
WebSession
.
Request
.
RequestBodyString
=
WebSession
.
Request
.
Encoding
.
GetString
(
WebSession
.
Request
.
RequestBody
));
}
}
/// <summary>
/// <summary>
/// Sets the request body
/// Sets the request body
/// </summary>
/// </summary>
/// <param name="body"></param>
/// <param name="body"></param>
public
async
Task
SetRequestBody
(
byte
[]
body
)
public
async
Task
SetRequestBody
(
byte
[]
body
)
{
{
if
(
WebSession
.
Request
.
RequestLocked
)
if
(
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
}
}
//syphon out the request body from client before setting the new body
//syphon out the request body from client before setting the new body
if
(!
WebSession
.
Request
.
RequestBodyRead
)
if
(!
WebSession
.
Request
.
RequestBodyRead
)
{
{
await
ReadRequestBody
();
await
ReadRequestBody
();
}
}
WebSession
.
Request
.
RequestBody
=
body
;
WebSession
.
Request
.
RequestBody
=
body
;
if
(
WebSession
.
Request
.
IsChunked
==
false
)
if
(
WebSession
.
Request
.
IsChunked
==
false
)
{
{
WebSession
.
Request
.
ContentLength
=
body
.
Length
;
WebSession
.
Request
.
ContentLength
=
body
.
Length
;
}
}
else
else
{
{
WebSession
.
Request
.
ContentLength
=
-
1
;
WebSession
.
Request
.
ContentLength
=
-
1
;
}
}
}
}
/// <summary>
/// <summary>
/// Sets the body with the specified string
/// Sets the body with the specified string
/// </summary>
/// </summary>
/// <param name="body"></param>
/// <param name="body"></param>
public
async
Task
SetRequestBodyString
(
string
body
)
public
async
Task
SetRequestBodyString
(
string
body
)
{
{
if
(
WebSession
.
Request
.
RequestLocked
)
if
(
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
}
}
//syphon out the request body from client before setting the new body
//syphon out the request body from client before setting the new body
if
(!
WebSession
.
Request
.
RequestBodyRead
)
if
(!
WebSession
.
Request
.
RequestBodyRead
)
{
{
await
ReadRequestBody
();
await
ReadRequestBody
();
}
}
await
SetRequestBody
(
WebSession
.
Request
.
Encoding
.
GetBytes
(
body
));
await
SetRequestBody
(
WebSession
.
Request
.
Encoding
.
GetBytes
(
body
));
}
}
/// <summary>
/// <summary>
/// Gets the response body as byte array
/// Gets the response body as byte array
/// </summary>
/// </summary>
/// <returns></returns>
/// <returns></returns>
public
async
Task
<
byte
[
]>
GetResponseBody
()
public
async
Task
<
byte
[
]>
GetResponseBody
()
{
{
if
(!
WebSession
.
Request
.
RequestLocked
)
if
(!
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
}
}
await
ReadResponseBody
();
await
ReadResponseBody
();
return
WebSession
.
Response
.
ResponseBody
;
return
WebSession
.
Response
.
ResponseBody
;
}
}
/// <summary>
/// <summary>
/// Gets the response body as string
/// Gets the response body as string
/// </summary>
/// </summary>
/// <returns></returns>
/// <returns></returns>
public
async
Task
<
string
>
GetResponseBodyAsString
()
public
async
Task
<
string
>
GetResponseBodyAsString
()
{
{
if
(!
WebSession
.
Request
.
RequestLocked
)
if
(!
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
}
}
await
GetResponseBody
();
await
GetResponseBody
();
return
WebSession
.
Response
.
ResponseBodyString
??
return
WebSession
.
Response
.
ResponseBodyString
??
(
WebSession
.
Response
.
ResponseBodyString
=
WebSession
.
Response
.
Encoding
.
GetString
(
WebSession
.
Response
.
ResponseBody
));
(
WebSession
.
Response
.
ResponseBodyString
=
WebSession
.
Response
.
Encoding
.
GetString
(
WebSession
.
Response
.
ResponseBody
));
}
}
/// <summary>
/// <summary>
/// Set the response body bytes
/// Set the response body bytes
/// </summary>
/// </summary>
/// <param name="body"></param>
/// <param name="body"></param>
public
async
Task
SetResponseBody
(
byte
[]
body
)
public
async
Task
SetResponseBody
(
byte
[]
body
)
{
{
if
(!
WebSession
.
Request
.
RequestLocked
)
if
(!
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
}
}
//syphon out the response body from server before setting the new body
//syphon out the response body from server before setting the new body
if
(
WebSession
.
Response
.
ResponseBody
==
null
)
if
(
WebSession
.
Response
.
ResponseBody
==
null
)
{
{
await
GetResponseBody
();
await
GetResponseBody
();
}
}
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
==
false
)
if
(
WebSession
.
Response
.
IsChunked
==
false
)
{
{
WebSession
.
Response
.
ContentLength
=
body
.
Length
;
WebSession
.
Response
.
ContentLength
=
body
.
Length
;
}
}
else
else
{
{
WebSession
.
Response
.
ContentLength
=
-
1
;
WebSession
.
Response
.
ContentLength
=
-
1
;
}
}
}
}
/// <summary>
/// <summary>
/// Replace the response body with the specified string
/// Replace the response body with the specified string
/// </summary>
/// </summary>
/// <param name="body"></param>
/// <param name="body"></param>
public
async
Task
SetResponseBodyString
(
string
body
)
public
async
Task
SetResponseBodyString
(
string
body
)
{
{
if
(!
WebSession
.
Request
.
RequestLocked
)
if
(!
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
}
}
//syphon out the response body from server before setting the new body
//syphon out the response body from server before setting the new body
if
(
WebSession
.
Response
.
ResponseBody
==
null
)
if
(
WebSession
.
Response
.
ResponseBody
==
null
)
{
{
await
GetResponseBody
();
await
GetResponseBody
();
}
}
var
bodyBytes
=
WebSession
.
Response
.
Encoding
.
GetBytes
(
body
);
var
bodyBytes
=
WebSession
.
Response
.
Encoding
.
GetBytes
(
body
);
await
SetResponseBody
(
bodyBytes
);
await
SetResponseBody
(
bodyBytes
);
}
}
private
async
Task
<
byte
[
]>
GetDecompressedResponseBody
(
string
encodingType
,
byte
[]
responseBodyStream
)
private
async
Task
<
byte
[
]>
GetDecompressedResponseBody
(
string
encodingType
,
byte
[]
responseBodyStream
)
{
{
var
decompressionFactory
=
new
DecompressionFactory
();
var
decompressionFactory
=
new
DecompressionFactory
();
var
decompressor
=
decompressionFactory
.
Create
(
encodingType
);
var
decompressor
=
decompressionFactory
.
Create
(
encodingType
);
return
await
decompressor
.
Decompress
(
responseBodyStream
,
bufferSize
);
return
await
decompressor
.
Decompress
(
responseBodyStream
,
bufferSize
);
}
}
/// <summary>
/// <summary>
/// Before request is made to server
/// Before request is made to server
/// Respond with the specified HTML string to client
/// Respond with the specified HTML string to client
/// and ignore the request
/// and ignore the request
/// </summary>
/// </summary>
/// <param name="html"></param>
/// <param name="html"></param>
public
async
Task
Ok
(
string
html
)
public
async
Task
Ok
(
string
html
)
{
{
await
Ok
(
html
,
null
);
await
Ok
(
html
,
null
);
}
}
/// <summary>
/// <summary>
/// Before request is made to server
/// Before request is made to server
/// Respond with the specified HTML string to client
/// Respond with the specified HTML string to client
/// and ignore the request
/// and ignore the request
/// </summary>
/// </summary>
/// <param name="html"></param>
/// <param name="html"></param>
/// <param name="headers"></param>
/// <param name="headers"></param>
public
async
Task
Ok
(
string
html
,
Dictionary
<
string
,
HttpHeader
>
headers
)
public
async
Task
Ok
(
string
html
,
Dictionary
<
string
,
HttpHeader
>
headers
)
{
{
if
(
WebSession
.
Request
.
RequestLocked
)
if
(
WebSession
.
Request
.
RequestLocked
)
{
{
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
}
}
if
(
html
==
null
)
if
(
html
==
null
)
{
{
html
=
string
.
Empty
;
html
=
string
.
Empty
;
}
}
var
result
=
Encoding
.
Default
.
GetBytes
(
html
);
var
result
=
Encoding
.
Default
.
GetBytes
(
html
);
await
Ok
(
result
,
headers
);
await
Ok
(
result
,
headers
);
}
}
/// <summary>
/// <summary>
/// Before request is made to server
/// Before request is made to server
/// Respond with the specified byte[] to client
/// Respond with the specified byte[] to client
/// and ignore the request
/// and ignore the request
/// </summary>
/// </summary>
/// <param name="result"></param>
/// <param name="result"></param>
public
async
Task
Ok
(
byte
[]
result
)
public
async
Task
Ok
(
byte
[]
result
)
{
{
await
Ok
(
result
,
null
);
await
Ok
(
result
,
null
);
}
}
/// <summary>
/// <summary>
/// Before request is made to server
/// Before request is made to server
/// Respond with the specified byte[] to client
/// Respond with the specified byte[] to client
/// and ignore the request
/// and ignore the request
/// </summary>
/// </summary>
/// <param name="result"></param>
/// <param name="result"></param>
/// <param name="headers"></param>
/// <param name="headers"></param>
public
async
Task
Ok
(
byte
[]
result
,
Dictionary
<
string
,
HttpHeader
>
headers
)
public
async
Task
Ok
(
byte
[]
result
,
Dictionary
<
string
,
HttpHeader
>
headers
)
{
{
var
response
=
new
OkResponse
();
var
response
=
new
OkResponse
();
if
(
headers
!=
null
&&
headers
.
Count
>
0
)
if
(
headers
!=
null
&&
headers
.
Count
>
0
)
{
{
response
.
ResponseHeaders
=
headers
;
response
.
ResponseHeaders
=
headers
;
}
}
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
ResponseBody
=
result
;
response
.
ResponseBody
=
result
;
await
Respond
(
response
);
await
Respond
(
response
);
WebSession
.
Request
.
CancelRequest
=
true
;
WebSession
.
Request
.
CancelRequest
=
true
;
}
}
public
async
Task
Redirect
(
string
url
)
public
async
Task
Redirect
(
string
url
)
{
{
var
response
=
new
RedirectResponse
();
var
response
=
new
RedirectResponse
();
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
ResponseHeaders
.
Add
(
"Location"
,
new
Models
.
HttpHeader
(
"Location"
,
url
));
response
.
ResponseHeaders
.
Add
(
"Location"
,
new
Models
.
HttpHeader
(
"Location"
,
url
));
response
.
ResponseBody
=
Encoding
.
ASCII
.
GetBytes
(
string
.
Empty
);
response
.
ResponseBody
=
Encoding
.
ASCII
.
GetBytes
(
string
.
Empty
);
await
Respond
(
response
);
await
Respond
(
response
);
WebSession
.
Request
.
CancelRequest
=
true
;
WebSession
.
Request
.
CancelRequest
=
true
;
}
}
/// a generic responder method
/// a generic responder method
public
async
Task
Respond
(
Response
response
)
public
async
Task
Respond
(
Response
response
)
{
{
WebSession
.
Request
.
RequestLocked
=
true
;
WebSession
.
Request
.
RequestLocked
=
true
;
response
.
ResponseLocked
=
true
;
response
.
ResponseLocked
=
true
;
response
.
ResponseBodyRead
=
true
;
response
.
ResponseBodyRead
=
true
;
WebSession
.
Response
=
response
;
WebSession
.
Response
=
response
;
await
httpResponseHandler
(
this
);
await
httpResponseHandler
(
this
);
}
}
/// <summary>
/// <summary>
/// implement any cleanup here
/// implement any cleanup here
/// </summary>
/// </summary>
public
void
Dispose
()
public
void
Dispose
()
{
{
}
}
}
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Helpers/Tcp.cs
View file @
55312330
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.IO
;
using
System.Linq
;
using
System.Linq
;
using
System.Net.NetworkInformation
;
using
System.Net.NetworkInformation
;
using
System.Net.Security
;
using
System.Net.Security
;
using
System.Runtime.InteropServices
;
using
System.Runtime.InteropServices
;
using
System.Security.Authentication
;
using
System.Security.Authentication
;
using
System.Text
;
using
System.Text
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Tcp
;
using
Titanium.Web.Proxy.Tcp
;
namespace
Titanium.Web.Proxy.Helpers
namespace
Titanium.Web.Proxy.Helpers
{
{
internal
enum
IpVersion
internal
enum
IpVersion
{
{
Ipv4
=
1
,
Ipv4
=
1
,
Ipv6
=
2
,
Ipv6
=
2
,
}
}
internal
partial
class
NativeMethods
internal
partial
class
NativeMethods
{
{
internal
const
int
AfInet
=
2
;
internal
const
int
AfInet
=
2
;
internal
const
int
AfInet6
=
23
;
internal
const
int
AfInet6
=
23
;
internal
enum
TcpTableType
internal
enum
TcpTableType
{
{
BasicListener
,
BasicListener
,
BasicConnections
,
BasicConnections
,
BasicAll
,
BasicAll
,
OwnerPidListener
,
OwnerPidListener
,
OwnerPidConnections
,
OwnerPidConnections
,
OwnerPidAll
,
OwnerPidAll
,
OwnerModuleListener
,
OwnerModuleListener
,
OwnerModuleConnections
,
OwnerModuleConnections
,
OwnerModuleAll
,
OwnerModuleAll
,
}
}
/// <summary>
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/>
/// </summary>
/// </summary>
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
internal
struct
TcpTable
internal
struct
TcpTable
{
{
public
uint
length
;
public
uint
length
;
public
TcpRow
row
;
public
TcpRow
row
;
}
}
/// <summary>
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary>
/// </summary>
[
StructLayout
(
LayoutKind
.
Sequential
)]
[
StructLayout
(
LayoutKind
.
Sequential
)]
internal
struct
TcpRow
internal
struct
TcpRow
{
{
public
TcpState
state
;
public
TcpState
state
;
public
uint
localAddr
;
public
uint
localAddr
;
public
byte
localPort1
;
public
byte
localPort1
;
public
byte
localPort2
;
public
byte
localPort2
;
public
byte
localPort3
;
public
byte
localPort3
;
public
byte
localPort4
;
public
byte
localPort4
;
public
uint
remoteAddr
;
public
uint
remoteAddr
;
public
byte
remotePort1
;
public
byte
remotePort1
;
public
byte
remotePort2
;
public
byte
remotePort2
;
public
byte
remotePort3
;
public
byte
remotePort3
;
public
byte
remotePort4
;
public
byte
remotePort4
;
public
int
owningPid
;
public
int
owningPid
;
}
}
/// <summary>
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/>
/// </summary>
/// </summary>
[
DllImport
(
"iphlpapi.dll"
,
SetLastError
=
true
)]
[
DllImport
(
"iphlpapi.dll"
,
SetLastError
=
true
)]
internal
static
extern
uint
GetExtendedTcpTable
(
IntPtr
tcpTable
,
ref
int
size
,
bool
sort
,
int
ipVersion
,
int
tableClass
,
int
reserved
);
internal
static
extern
uint
GetExtendedTcpTable
(
IntPtr
tcpTable
,
ref
int
size
,
bool
sort
,
int
ipVersion
,
int
tableClass
,
int
reserved
);
}
}
internal
class
TcpHelper
internal
class
TcpHelper
{
{
/// <summary>
/// <summary>
/// Gets the extended TCP table.
/// Gets the extended TCP table.
/// </summary>
/// </summary>
/// <returns>Collection of <see cref="TcpRow"/>.</returns>
/// <returns>Collection of <see cref="TcpRow"/>.</returns>
internal
static
TcpTable
GetExtendedTcpTable
(
IpVersion
ipVersion
)
internal
static
TcpTable
GetExtendedTcpTable
(
IpVersion
ipVersion
)
{
{
List
<
TcpRow
>
tcpRows
=
new
List
<
TcpRow
>();
List
<
TcpRow
>
tcpRows
=
new
List
<
TcpRow
>();
IntPtr
tcpTable
=
IntPtr
.
Zero
;
IntPtr
tcpTable
=
IntPtr
.
Zero
;
int
tcpTableLength
=
0
;
int
tcpTableLength
=
0
;
var
ipVersionValue
=
ipVersion
==
IpVersion
.
Ipv4
?
NativeMethods
.
AfInet
:
NativeMethods
.
AfInet6
;
var
ipVersionValue
=
ipVersion
==
IpVersion
.
Ipv4
?
NativeMethods
.
AfInet
:
NativeMethods
.
AfInet6
;
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
false
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
!=
0
)
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
false
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
!=
0
)
{
{
try
try
{
{
tcpTable
=
Marshal
.
AllocHGlobal
(
tcpTableLength
);
tcpTable
=
Marshal
.
AllocHGlobal
(
tcpTableLength
);
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
true
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
==
0
)
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
true
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
==
0
)
{
{
NativeMethods
.
TcpTable
table
=
(
NativeMethods
.
TcpTable
)
Marshal
.
PtrToStructure
(
tcpTable
,
typeof
(
NativeMethods
.
TcpTable
));
NativeMethods
.
TcpTable
table
=
(
NativeMethods
.
TcpTable
)
Marshal
.
PtrToStructure
(
tcpTable
,
typeof
(
NativeMethods
.
TcpTable
));
IntPtr
rowPtr
=
(
IntPtr
)((
long
)
tcpTable
+
Marshal
.
SizeOf
(
table
.
length
));
IntPtr
rowPtr
=
(
IntPtr
)((
long
)
tcpTable
+
Marshal
.
SizeOf
(
table
.
length
));
for
(
int
i
=
0
;
i
<
table
.
length
;
++
i
)
for
(
int
i
=
0
;
i
<
table
.
length
;
++
i
)
{
{
tcpRows
.
Add
(
new
TcpRow
((
NativeMethods
.
TcpRow
)
Marshal
.
PtrToStructure
(
rowPtr
,
typeof
(
NativeMethods
.
TcpRow
))));
tcpRows
.
Add
(
new
TcpRow
((
NativeMethods
.
TcpRow
)
Marshal
.
PtrToStructure
(
rowPtr
,
typeof
(
NativeMethods
.
TcpRow
))));
rowPtr
=
(
IntPtr
)((
long
)
rowPtr
+
Marshal
.
SizeOf
(
typeof
(
NativeMethods
.
TcpRow
)));
rowPtr
=
(
IntPtr
)((
long
)
rowPtr
+
Marshal
.
SizeOf
(
typeof
(
NativeMethods
.
TcpRow
)));
}
}
}
}
}
}
finally
finally
{
{
if
(
tcpTable
!=
IntPtr
.
Zero
)
if
(
tcpTable
!=
IntPtr
.
Zero
)
{
{
Marshal
.
FreeHGlobal
(
tcpTable
);
Marshal
.
FreeHGlobal
(
tcpTable
);
}
}
}
}
}
}
return
new
TcpTable
(
tcpRows
);
return
new
TcpTable
(
tcpRows
);
}
}
/// <summary>
/// <summary>
/// relays the input clientStream to the server at the specified host name & port with the given httpCmd & headers as prefix
/// relays the input clientStream to the server at the specified host name & port with the given httpCmd & headers as prefix
/// Usefull for websocket requests
/// Usefull for websocket requests
/// </summary>
/// </summary>
/// <param name="bufferSize"></param>
/// <param name="bufferSize"></param>
/// <param name="connectionTimeOutSeconds"></param>
/// <param name="connectionTimeOutSeconds"></param>
/// <param name="remoteHostName"></param>
/// <param name="remoteHostName"></param>
/// <param name="httpCmd"></param>
/// <param name="httpCmd"></param>
/// <param name="httpVersion"></param>
/// <param name="httpVersion"></param>
/// <param name="requestHeaders"></param>
/// <param name="requestHeaders"></param>
/// <param name="isHttps"></param>
/// <param name="isHttps"></param>
/// <param name="remotePort"></param>
/// <param name="remotePort"></param>
/// <param name="supportedProtocols"></param>
/// <param name="supportedProtocols"></param>
/// <param name="remoteCertificateValidationCallback"></param>
/// <param name="remoteCertificateValidationCallback"></param>
/// <param name="localCertificateSelectionCallback"></param>
/// <param name="localCertificateSelectionCallback"></param>
/// <param name="clientStream"></param>
/// <param name="clientStream"></param>
/// <param name="tcpConnectionFactory"></param>
/// <param name="tcpConnectionFactory"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
async
Task
SendRaw
(
int
bufferSize
,
int
connectionTimeOutSeconds
,
internal
static
async
Task
SendRaw
(
int
bufferSize
,
int
connectionTimeOutSeconds
,
string
remoteHostName
,
int
remotePort
,
string
httpCmd
,
Version
httpVersion
,
Dictionary
<
string
,
HttpHeader
>
requestHeaders
,
string
remoteHostName
,
int
remotePort
,
string
httpCmd
,
Version
httpVersion
,
Dictionary
<
string
,
HttpHeader
>
requestHeaders
,
bool
isHttps
,
SslProtocols
supportedProtocols
,
bool
isHttps
,
SslProtocols
supportedProtocols
,
RemoteCertificateValidationCallback
remoteCertificateValidationCallback
,
LocalCertificateSelectionCallback
localCertificateSelectionCallback
,
RemoteCertificateValidationCallback
remoteCertificateValidationCallback
,
LocalCertificateSelectionCallback
localCertificateSelectionCallback
,
Stream
clientStream
,
TcpConnectionFactory
tcpConnectionFactory
)
Stream
clientStream
,
TcpConnectionFactory
tcpConnectionFactory
)
{
{
//prepare the prefix content
//prepare the prefix content
StringBuilder
sb
=
null
;
StringBuilder
sb
=
null
;
if
(
httpCmd
!=
null
||
requestHeaders
!=
null
)
if
(
httpCmd
!=
null
||
requestHeaders
!=
null
)
{
{
sb
=
new
StringBuilder
();
sb
=
new
StringBuilder
();
if
(
httpCmd
!=
null
)
if
(
httpCmd
!=
null
)
{
{
sb
.
Append
(
httpCmd
);
sb
.
Append
(
httpCmd
);
sb
.
Append
(
Environment
.
NewLine
);
sb
.
Append
(
Environment
.
NewLine
);
}
}
if
(
requestHeaders
!=
null
)
if
(
requestHeaders
!=
null
)
{
{
foreach
(
var
header
in
requestHeaders
.
Select
(
t
=>
t
.
Value
.
ToString
()))
foreach
(
var
header
in
requestHeaders
.
Select
(
t
=>
t
.
Value
.
ToString
()))
{
{
sb
.
Append
(
header
);
sb
.
Append
(
header
);
sb
.
Append
(
Environment
.
NewLine
);
sb
.
Append
(
Environment
.
NewLine
);
}
}
}
}
sb
.
Append
(
Environment
.
NewLine
);
sb
.
Append
(
Environment
.
NewLine
);
}
}
var
tcpConnection
=
await
tcpConnectionFactory
.
CreateClient
(
bufferSize
,
connectionTimeOutSeconds
,
var
tcpConnection
=
await
tcpConnectionFactory
.
CreateClient
(
bufferSize
,
connectionTimeOutSeconds
,
remoteHostName
,
remotePort
,
remoteHostName
,
remotePort
,
httpVersion
,
isHttps
,
httpVersion
,
isHttps
,
supportedProtocols
,
remoteCertificateValidationCallback
,
localCertificateSelectionCallback
,
supportedProtocols
,
remoteCertificateValidationCallback
,
localCertificateSelectionCallback
,
null
,
null
,
clientStream
);
null
,
null
,
clientStream
);
try
try
{
{
Stream
tunnelStream
=
tcpConnection
.
Stream
;
Stream
tunnelStream
=
tcpConnection
.
Stream
;
Task
sendRelay
;
//Now async relay all server=>client & client=>server data
var
sendRelay
=
clientStream
.
CopyToAsync
(
sb
?.
ToString
()
??
string
.
Empty
,
tunnelStream
);
//Now async relay all server=>client & client=>server data
sendRelay
=
clientStream
.
CopyToAsync
(
sb
?.
ToString
()
??
string
.
Empty
,
tunnelStream
);
var
receiveRelay
=
tunnelStream
.
CopyToAsync
(
string
.
Empty
,
clientStream
);
await
Task
.
WhenAll
(
sendRelay
,
receiveRelay
);
var
receiveRelay
=
tunnelStream
.
CopyToAsync
(
string
.
Empty
,
clientStream
);
}
finally
await
Task
.
WhenAll
(
sendRelay
,
receiveRelay
);
{
}
tcpConnection
.
Dispose
();
finally
}
{
}
tcpConnection
.
Dispose
();
}
}
}
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Network/TcpConnection.cs
View file @
55312330
...
@@ -16,7 +16,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -16,7 +16,7 @@ namespace Titanium.Web.Proxy.Network
internal
ExternalProxy
UpStreamHttpsProxy
{
get
;
set
;
}
internal
ExternalProxy
UpStreamHttpsProxy
{
get
;
set
;
}
internal
string
HostName
{
get
;
set
;
}
internal
string
HostName
{
get
;
set
;
}
internal
int
p
ort
{
get
;
set
;
}
internal
int
P
ort
{
get
;
set
;
}
internal
bool
IsHttps
{
get
;
set
;
}
internal
bool
IsHttps
{
get
;
set
;
}
...
...
Titanium.Web.Proxy/Network/TcpConnectionFactory.cs
View file @
55312330
...
@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network
SslStream
sslStream
=
null
;
SslStream
sslStream
=
null
;
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections
if
(
externalHttpsProxy
!=
null
)
if
(
externalHttpsProxy
!=
null
&&
externalHttpsProxy
.
HostName
!=
remoteHostName
)
{
{
client
=
new
TcpClient
(
externalHttpsProxy
.
HostName
,
externalHttpsProxy
.
Port
);
client
=
new
TcpClient
(
externalHttpsProxy
.
HostName
,
externalHttpsProxy
.
Port
);
stream
=
client
.
GetStream
();
stream
=
client
.
GetStream
();
...
@@ -100,17 +100,14 @@ namespace Titanium.Web.Proxy.Network
...
@@ -100,17 +100,14 @@ namespace Titanium.Web.Proxy.Network
}
}
catch
catch
{
{
if
(
sslStream
!=
null
)
sslStream
?.
Dispose
();
{
sslStream
.
Dispose
();
}
throw
;
throw
;
}
}
}
}
else
else
{
{
if
(
externalHttpProxy
!=
null
)
if
(
externalHttpProxy
!=
null
&&
externalHttpProxy
.
HostName
!=
remoteHostName
)
{
{
client
=
new
TcpClient
(
externalHttpProxy
.
HostName
,
externalHttpProxy
.
Port
);
client
=
new
TcpClient
(
externalHttpProxy
.
HostName
,
externalHttpProxy
.
Port
);
stream
=
client
.
GetStream
();
stream
=
client
.
GetStream
();
...
@@ -133,7 +130,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -133,7 +130,7 @@ namespace Titanium.Web.Proxy.Network
UpStreamHttpProxy
=
externalHttpProxy
,
UpStreamHttpProxy
=
externalHttpProxy
,
UpStreamHttpsProxy
=
externalHttpsProxy
,
UpStreamHttpsProxy
=
externalHttpsProxy
,
HostName
=
remoteHostName
,
HostName
=
remoteHostName
,
p
ort
=
remotePort
,
P
ort
=
remotePort
,
IsHttps
=
isHttps
,
IsHttps
=
isHttps
,
TcpClient
=
client
,
TcpClient
=
client
,
StreamReader
=
new
CustomBinaryReader
(
stream
),
StreamReader
=
new
CustomBinaryReader
(
stream
),
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
55312330
...
@@ -186,6 +186,11 @@ namespace Titanium.Web.Proxy
...
@@ -186,6 +186,11 @@ namespace Titanium.Web.Proxy
/// </summary>
/// </summary>
public
bool
ProxyRunning
=>
proxyRunning
;
public
bool
ProxyRunning
=>
proxyRunning
;
/// <summary>
/// Gets or sets a value indicating whether requests will be chained to upstream gateway.
/// </summary>
public
bool
ForwardToUpstreamGateway
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Constructor
/// Constructor
/// </summary>
/// </summary>
...
@@ -348,6 +353,12 @@ namespace Titanium.Web.Proxy
...
@@ -348,6 +353,12 @@ namespace Titanium.Web.Proxy
certificateCacheManager
.
TrustRootCertificate
();
certificateCacheManager
.
TrustRootCertificate
();
}
}
if
(
ForwardToUpstreamGateway
&&
GetCustomUpStreamHttpProxyFunc
==
null
&&
GetCustomUpStreamHttpsProxyFunc
==
null
)
{
GetCustomUpStreamHttpProxyFunc
=
GetSystemUpStreamProxy
;
GetCustomUpStreamHttpsProxyFunc
=
GetSystemUpStreamProxy
;
}
foreach
(
var
endPoint
in
ProxyEndPoints
)
foreach
(
var
endPoint
in
ProxyEndPoints
)
{
{
Listen
(
endPoint
);
Listen
(
endPoint
);
...
@@ -358,7 +369,29 @@ namespace Titanium.Web.Proxy
...
@@ -358,7 +369,29 @@ namespace Titanium.Web.Proxy
proxyRunning
=
true
;
proxyRunning
=
true
;
}
}
/// <summary>
/// <summary>
/// Gets the system up stream proxy.
/// </summary>
/// <param name="sessionEventArgs">The <see cref="SessionEventArgs"/> instance containing the event data.</param>
/// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns>
private
Task
<
ExternalProxy
>
GetSystemUpStreamProxy
(
SessionEventArgs
sessionEventArgs
)
{
// Use built-in WebProxy class to handle PAC/WAPD scripts.
var
systemProxyResolver
=
new
WebProxy
();
var
systemProxyUri
=
systemProxyResolver
.
GetProxy
(
sessionEventArgs
.
WebSession
.
Request
.
RequestUri
);
// TODO: Apply authorization
var
systemProxy
=
new
ExternalProxy
{
HostName
=
systemProxyUri
.
Host
,
Port
=
systemProxyUri
.
Port
};
return
Task
.
FromResult
(
systemProxy
);
}
/// <summary>
/// Stop this proxy server
/// Stop this proxy server
/// </summary>
/// </summary>
public
void
Stop
()
public
void
Stop
()
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
55312330
...
@@ -165,7 +165,6 @@ namespace Titanium.Web.Proxy
...
@@ -165,7 +165,6 @@ namespace Titanium.Web.Proxy
//write back successfull CONNECT response
//write back successfull CONNECT response
await
WriteConnectResponse
(
clientStreamWriter
,
version
);
await
WriteConnectResponse
(
clientStreamWriter
,
version
);
await
TcpHelper
.
SendRaw
(
BUFFER_SIZE
,
ConnectionTimeOutSeconds
,
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
await
TcpHelper
.
SendRaw
(
BUFFER_SIZE
,
ConnectionTimeOutSeconds
,
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
httpCmd
,
version
,
null
,
httpCmd
,
version
,
null
,
false
,
SupportedSslProtocols
,
false
,
SupportedSslProtocols
,
...
@@ -274,10 +273,8 @@ namespace Titanium.Web.Proxy
...
@@ -274,10 +273,8 @@ namespace Titanium.Web.Proxy
customUpStreamHttpProxy
??
UpStreamHttpProxy
,
customUpStreamHttpsProxy
??
UpStreamHttpsProxy
,
args
.
ProxyClient
.
ClientStream
);
customUpStreamHttpProxy
??
UpStreamHttpProxy
,
customUpStreamHttpsProxy
??
UpStreamHttpsProxy
,
args
.
ProxyClient
.
ClientStream
);
}
}
args
.
WebSession
.
Request
.
RequestLocked
=
true
;
args
.
WebSession
.
Request
.
RequestLocked
=
true
;
//If request was cancelled by user then dispose the client
//If request was cancelled by user then dispose the client
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
{
{
...
@@ -362,10 +359,10 @@ namespace Titanium.Web.Proxy
...
@@ -362,10 +359,10 @@ namespace Titanium.Web.Proxy
return
;
return
;
}
}
if
(
CloseConnection
&&
connection
!=
null
)
if
(
CloseConnection
)
{
{
//dispose
//dispose
connection
.
Dispose
();
connection
?
.
Dispose
();
}
}
}
}
...
@@ -472,7 +469,6 @@ namespace Titanium.Web.Proxy
...
@@ -472,7 +469,6 @@ namespace Titanium.Web.Proxy
break
;
break
;
}
}
PrepareRequestHeaders
(
args
.
WebSession
.
Request
.
RequestHeaders
,
args
.
WebSession
);
PrepareRequestHeaders
(
args
.
WebSession
.
Request
.
RequestHeaders
,
args
.
WebSession
);
args
.
WebSession
.
Request
.
Host
=
args
.
WebSession
.
Request
.
RequestUri
.
Authority
;
args
.
WebSession
.
Request
.
Host
=
args
.
WebSession
.
Request
.
RequestUri
.
Authority
;
...
...
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