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
a7cab15f
Commit
a7cab15f
authored
Nov 20, 2018
by
justcoding121
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#519 handle change in hostname on ReRequest
parent
8311e6b5
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
207 additions
and
167 deletions
+207
-167
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+3
-3
MainWindow.xaml.cs
examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
+13
-13
SessionEventArgs.cs
src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+41
-41
SessionEventArgsBase.cs
...Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
+15
-11
TunnelConnectEventArgs.cs
...tanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs
+1
-1
ExplicitClientHandler.cs
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
+8
-8
HttpWebClient.cs
src/Titanium.Web.Proxy/Http/HttpWebClient.cs
+17
-17
ProxyClient.cs
src/Titanium.Web.Proxy/Network/ProxyClient.cs
+1
-1
TcpConnectionFactory.cs
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+7
-7
ProxyAuthorizationHandler.cs
src/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
+8
-8
ProxyServer.cs
src/Titanium.Web.Proxy/ProxyServer.cs
+1
-1
RequestHandler.cs
src/Titanium.Web.Proxy/RequestHandler.cs
+73
-38
ResponseHandler.cs
src/Titanium.Web.Proxy/ResponseHandler.cs
+8
-7
WebSocketHandler.cs
src/Titanium.Web.Proxy/WebSocketHandler.cs
+1
-1
WinAuthHandler.cs
src/Titanium.Web.Proxy/WinAuthHandler.cs
+8
-8
InterceptionTests.cs
.../Titanium.Web.Proxy.IntegrationTests/InterceptionTests.cs
+2
-2
No files found.
examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
a7cab15f
...
...
@@ -118,7 +118,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
private
async
Task
OnBeforeTunnelConnectRequest
(
object
sender
,
TunnelConnectSessionEventArgs
e
)
{
string
hostname
=
e
.
WebSession
.
Request
.
RequestUri
.
Host
;
string
hostname
=
e
.
HttpClient
.
Request
.
RequestUri
.
Host
;
await
WriteToConsole
(
"Tunnel to: "
+
hostname
);
if
(
hostname
.
Contains
(
"dropbox.com"
))
...
...
@@ -139,7 +139,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
private
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
await
WriteToConsole
(
"Active Client Connections:"
+
((
ProxyServer
)
sender
).
ClientConnectionCount
);
await
WriteToConsole
(
e
.
WebSession
.
Request
.
Url
);
await
WriteToConsole
(
e
.
HttpClient
.
Request
.
Url
);
// store it in the UserData property
// It can be a simple integer, Guid, or any type
...
...
@@ -191,7 +191,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
await
WriteToConsole
(
"Active Server Connections:"
+
((
ProxyServer
)
sender
).
ServerConnectionCount
);
string
ext
=
System
.
IO
.
Path
.
GetExtension
(
e
.
WebSession
.
Request
.
RequestUri
.
AbsolutePath
);
string
ext
=
System
.
IO
.
Path
.
GetExtension
(
e
.
HttpClient
.
Request
.
RequestUri
.
AbsolutePath
);
//access user data set in request to do something with it
//var userData = e.WebSession.UserData as CustomUserData;
...
...
examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
View file @
a7cab15f
...
...
@@ -122,7 +122,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private
async
Task
ProxyServer_BeforeTunnelConnectRequest
(
object
sender
,
TunnelConnectSessionEventArgs
e
)
{
string
hostname
=
e
.
WebSession
.
Request
.
RequestUri
.
Host
;
string
hostname
=
e
.
HttpClient
.
Request
.
RequestUri
.
Host
;
if
(
hostname
.
EndsWith
(
"webex.com"
))
{
e
.
DecryptSsl
=
false
;
...
...
@@ -135,7 +135,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
await
Dispatcher
.
InvokeAsync
(()
=>
{
if
(
sessionDictionary
.
TryGetValue
(
e
.
WebSession
,
out
var
item
))
if
(
sessionDictionary
.
TryGetValue
(
e
.
HttpClient
,
out
var
item
))
{
item
.
Update
();
}
...
...
@@ -147,9 +147,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
SessionListItem
item
=
null
;
await
Dispatcher
.
InvokeAsync
(()
=>
{
item
=
AddSession
(
e
);
});
if
(
e
.
WebSession
.
Request
.
HasBody
)
if
(
e
.
HttpClient
.
Request
.
HasBody
)
{
e
.
WebSession
.
Request
.
KeepBody
=
true
;
e
.
HttpClient
.
Request
.
KeepBody
=
true
;
await
e
.
GetRequestBody
();
}
}
...
...
@@ -159,7 +159,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
SessionListItem
item
=
null
;
await
Dispatcher
.
InvokeAsync
(()
=>
{
if
(
sessionDictionary
.
TryGetValue
(
e
.
WebSession
,
out
item
))
if
(
sessionDictionary
.
TryGetValue
(
e
.
HttpClient
,
out
item
))
{
item
.
Update
();
}
...
...
@@ -167,9 +167,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
if
(
item
!=
null
)
{
if
(
e
.
WebSession
.
Response
.
HasBody
)
if
(
e
.
HttpClient
.
Response
.
HasBody
)
{
e
.
WebSession
.
Response
.
KeepBody
=
true
;
e
.
HttpClient
.
Response
.
KeepBody
=
true
;
await
e
.
GetResponseBody
();
await
Dispatcher
.
InvokeAsync
(()
=>
{
item
.
Update
();
});
...
...
@@ -181,7 +181,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
await
Dispatcher
.
InvokeAsync
(()
=>
{
if
(
sessionDictionary
.
TryGetValue
(
e
.
WebSession
,
out
var
item
))
if
(
sessionDictionary
.
TryGetValue
(
e
.
HttpClient
,
out
var
item
))
{
item
.
Exception
=
e
.
Exception
;
}
...
...
@@ -192,7 +192,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
var
item
=
CreateSessionListItem
(
e
);
Sessions
.
Add
(
item
);
sessionDictionary
.
Add
(
e
.
WebSession
,
item
);
sessionDictionary
.
Add
(
e
.
HttpClient
,
item
);
return
item
;
}
...
...
@@ -203,16 +203,16 @@ namespace Titanium.Web.Proxy.Examples.Wpf
var
item
=
new
SessionListItem
{
Number
=
lastSessionNumber
,
WebSession
=
e
.
WebSession
,
WebSession
=
e
.
HttpClient
,
IsTunnelConnect
=
isTunnelConnect
};
if
(
isTunnelConnect
||
e
.
WebSession
.
Request
.
UpgradeToWebSocket
)
if
(
isTunnelConnect
||
e
.
HttpClient
.
Request
.
UpgradeToWebSocket
)
{
e
.
DataReceived
+=
(
sender
,
args
)
=>
{
var
session
=
(
SessionEventArgs
)
sender
;
if
(
sessionDictionary
.
TryGetValue
(
session
.
WebSession
,
out
var
li
))
if
(
sessionDictionary
.
TryGetValue
(
session
.
HttpClient
,
out
var
li
))
{
li
.
ReceivedDataCount
+=
args
.
Count
;
}
...
...
@@ -221,7 +221,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
e
.
DataSent
+=
(
sender
,
args
)
=>
{
var
session
=
(
SessionEventArgs
)
sender
;
if
(
sessionDictionary
.
TryGetValue
(
session
.
WebSession
,
out
var
li
))
if
(
sessionDictionary
.
TryGetValue
(
session
.
HttpClient
,
out
var
li
))
{
li
.
SentDataCount
+=
args
.
Count
;
}
...
...
src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
a7cab15f
...
...
@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy.EventArguments
get
=>
reRequest
;
set
{
if
(
WebSession
.
Response
.
StatusCode
==
0
)
if
(
HttpClient
.
Response
.
StatusCode
==
0
)
{
throw
new
Exception
(
"Response status code is empty. Cannot request again a request "
+
"which was never send to server."
);
}
...
...
@@ -69,12 +69,12 @@ namespace Titanium.Web.Proxy.EventArguments
private
ICustomStreamReader
getStreamReader
(
bool
isRequest
)
{
return
isRequest
?
ProxyClient
.
ClientStream
:
WebSession
.
Server
Connection
.
Stream
;
return
isRequest
?
ProxyClient
.
ClientStream
:
HttpClient
.
Connection
.
Stream
;
}
private
HttpWriter
getStreamWriter
(
bool
isRequest
)
{
return
isRequest
?
(
HttpWriter
)
ProxyClient
.
ClientStreamWriter
:
WebSession
.
Server
Connection
.
StreamWriter
;
return
isRequest
?
(
HttpWriter
)
ProxyClient
.
ClientStreamWriter
:
HttpClient
.
Connection
.
StreamWriter
;
}
/// <summary>
...
...
@@ -82,9 +82,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
private
async
Task
readRequestBodyAsync
(
CancellationToken
cancellationToken
)
{
WebSession
.
Request
.
EnsureBodyAvailable
(
false
);
HttpClient
.
Request
.
EnsureBodyAvailable
(
false
);
var
request
=
WebSession
.
Request
;
var
request
=
HttpClient
.
Request
;
// If not already read (not cached yet)
if
(!
request
.
IsBodyRead
)
...
...
@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
// syphon out the response body from server
await
SyphonOutBodyAsync
(
false
,
cancellationToken
);
WebSession
.
Response
=
new
Response
();
HttpClient
.
Response
=
new
Response
();
}
internal
void
OnMultipartRequestPartSent
(
string
boundary
,
HeaderCollection
headers
)
...
...
@@ -126,12 +126,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
private
async
Task
readResponseBodyAsync
(
CancellationToken
cancellationToken
)
{
if
(!
WebSession
.
Request
.
Locked
)
if
(!
HttpClient
.
Request
.
Locked
)
{
throw
new
Exception
(
"You cannot read the response body before request is made to server."
);
}
var
response
=
WebSession
.
Response
;
var
response
=
HttpClient
.
Response
;
if
(!
response
.
HasBody
)
{
return
;
...
...
@@ -178,7 +178,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns></returns>
internal
async
Task
SyphonOutBodyAsync
(
bool
isRequest
,
CancellationToken
cancellationToken
)
{
var
requestResponse
=
isRequest
?
(
RequestResponseBase
)
WebSession
.
Request
:
WebSession
.
Response
;
var
requestResponse
=
isRequest
?
(
RequestResponseBase
)
HttpClient
.
Request
:
HttpClient
.
Response
;
if
(
requestResponse
.
IsBodyRead
||
!
requestResponse
.
OriginalHasBody
)
{
return
;
...
...
@@ -197,7 +197,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns></returns>
internal
async
Task
CopyRequestBodyAsync
(
HttpWriter
writer
,
TransformationMode
transformation
,
CancellationToken
cancellationToken
)
{
var
request
=
WebSession
.
Request
;
var
request
=
HttpClient
.
Request
;
long
contentLength
=
request
.
ContentLength
;
...
...
@@ -243,7 +243,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
var
stream
=
getStreamReader
(
isRequest
);
var
requestResponse
=
isRequest
?
(
RequestResponseBase
)
WebSession
.
Request
:
WebSession
.
Response
;
var
requestResponse
=
isRequest
?
(
RequestResponseBase
)
HttpClient
.
Request
:
HttpClient
.
Response
;
bool
isChunked
=
useOriginalHeaderValues
?
requestResponse
.
OriginalIsChunked
:
requestResponse
.
IsChunked
;
long
contentLength
=
useOriginalHeaderValues
?
requestResponse
.
OriginalContentLength
:
requestResponse
.
ContentLength
;
...
...
@@ -351,12 +351,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The body as bytes.</returns>
public
async
Task
<
byte
[
]>
GetRequestBody
(
CancellationToken
cancellationToken
=
default
)
{
if
(!
WebSession
.
Request
.
IsBodyRead
)
if
(!
HttpClient
.
Request
.
IsBodyRead
)
{
await
readRequestBodyAsync
(
cancellationToken
);
}
return
WebSession
.
Request
.
Body
;
return
HttpClient
.
Request
.
Body
;
}
/// <summary>
...
...
@@ -366,12 +366,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The body as string.</returns>
public
async
Task
<
string
>
GetRequestBodyAsString
(
CancellationToken
cancellationToken
=
default
)
{
if
(!
WebSession
.
Request
.
IsBodyRead
)
if
(!
HttpClient
.
Request
.
IsBodyRead
)
{
await
readRequestBodyAsync
(
cancellationToken
);
}
return
WebSession
.
Request
.
BodyString
;
return
HttpClient
.
Request
.
BodyString
;
}
/// <summary>
...
...
@@ -380,7 +380,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The request body bytes.</param>
public
void
SetRequestBody
(
byte
[]
body
)
{
var
request
=
WebSession
.
Request
;
var
request
=
HttpClient
.
Request
;
if
(
request
.
Locked
)
{
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
...
...
@@ -395,12 +395,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The request body string to set.</param>
public
void
SetRequestBodyString
(
string
body
)
{
if
(
WebSession
.
Request
.
Locked
)
if
(
HttpClient
.
Request
.
Locked
)
{
throw
new
Exception
(
"You cannot call this function after request is made to server."
);
}
SetRequestBody
(
WebSession
.
Request
.
Encoding
.
GetBytes
(
body
));
SetRequestBody
(
HttpClient
.
Request
.
Encoding
.
GetBytes
(
body
));
}
...
...
@@ -411,12 +411,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The resulting bytes.</returns>
public
async
Task
<
byte
[
]>
GetResponseBody
(
CancellationToken
cancellationToken
=
default
)
{
if
(!
WebSession
.
Response
.
IsBodyRead
)
if
(!
HttpClient
.
Response
.
IsBodyRead
)
{
await
readResponseBodyAsync
(
cancellationToken
);
}
return
WebSession
.
Response
.
Body
;
return
HttpClient
.
Response
.
Body
;
}
/// <summary>
...
...
@@ -426,12 +426,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <returns>The string body.</returns>
public
async
Task
<
string
>
GetResponseBodyAsString
(
CancellationToken
cancellationToken
=
default
)
{
if
(!
WebSession
.
Response
.
IsBodyRead
)
if
(!
HttpClient
.
Response
.
IsBodyRead
)
{
await
readResponseBodyAsync
(
cancellationToken
);
}
return
WebSession
.
Response
.
BodyString
;
return
HttpClient
.
Response
.
BodyString
;
}
/// <summary>
...
...
@@ -440,12 +440,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The body bytes to set.</param>
public
void
SetResponseBody
(
byte
[]
body
)
{
if
(!
WebSession
.
Request
.
Locked
)
if
(!
HttpClient
.
Request
.
Locked
)
{
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
}
var
response
=
WebSession
.
Response
;
var
response
=
HttpClient
.
Response
;
response
.
Body
=
body
;
}
...
...
@@ -455,12 +455,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="body">The body string to set.</param>
public
void
SetResponseBodyString
(
string
body
)
{
if
(!
WebSession
.
Request
.
Locked
)
if
(!
HttpClient
.
Request
.
Locked
)
{
throw
new
Exception
(
"You cannot call this function before request is made to server."
);
}
var
bodyBytes
=
WebSession
.
Response
.
Encoding
.
GetBytes
(
body
);
var
bodyBytes
=
HttpClient
.
Response
.
Encoding
.
GetBytes
(
body
);
SetResponseBody
(
bodyBytes
);
}
...
...
@@ -481,7 +481,7 @@ namespace Titanium.Web.Proxy.EventArguments
response
.
Headers
.
AddHeaders
(
headers
);
}
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
HttpVersion
=
HttpClient
.
Request
.
HttpVersion
;
response
.
Body
=
response
.
Encoding
.
GetBytes
(
html
??
string
.
Empty
);
Respond
(
response
,
closeServerConnection
);
...
...
@@ -499,7 +499,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
var
response
=
new
OkResponse
();
response
.
Headers
.
AddHeaders
(
headers
);
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
HttpVersion
=
HttpClient
.
Request
.
HttpVersion
;
response
.
Body
=
result
;
Respond
(
response
,
closeServerConnection
);
...
...
@@ -518,7 +518,7 @@ namespace Titanium.Web.Proxy.EventArguments
Dictionary
<
string
,
HttpHeader
>
headers
=
null
,
bool
closeServerConnection
=
false
)
{
var
response
=
new
GenericResponse
(
status
);
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
HttpVersion
=
HttpClient
.
Request
.
HttpVersion
;
response
.
Headers
.
AddHeaders
(
headers
);
response
.
Body
=
response
.
Encoding
.
GetBytes
(
html
??
string
.
Empty
);
...
...
@@ -537,7 +537,7 @@ namespace Titanium.Web.Proxy.EventArguments
Dictionary
<
string
,
HttpHeader
>
headers
,
bool
closeServerConnection
=
false
)
{
var
response
=
new
GenericResponse
(
status
);
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
HttpVersion
=
HttpClient
.
Request
.
HttpVersion
;
response
.
Headers
.
AddHeaders
(
headers
);
response
.
Body
=
result
;
...
...
@@ -552,7 +552,7 @@ namespace Titanium.Web.Proxy.EventArguments
public
void
Redirect
(
string
url
,
bool
closeServerConnection
=
false
)
{
var
response
=
new
RedirectResponse
();
response
.
HttpVersion
=
WebSession
.
Request
.
HttpVersion
;
response
.
HttpVersion
=
HttpClient
.
Request
.
HttpVersion
;
response
.
Headers
.
AddHeader
(
KnownHeaders
.
Location
,
url
);
response
.
Body
=
emptyData
;
...
...
@@ -567,10 +567,10 @@ namespace Titanium.Web.Proxy.EventArguments
public
void
Respond
(
Response
response
,
bool
closeServerConnection
=
false
)
{
//request already send/ready to be sent.
if
(
WebSession
.
Request
.
Locked
)
if
(
HttpClient
.
Request
.
Locked
)
{
//response already received from server and ready to be sent to client.
if
(
WebSession
.
Response
.
Locked
)
if
(
HttpClient
.
Response
.
Locked
)
{
throw
new
Exception
(
"You cannot call this function after response is sent to the client."
);
}
...
...
@@ -583,21 +583,21 @@ namespace Titanium.Web.Proxy.EventArguments
TerminateServerConnection
();
}
response
.
SetOriginalHeaders
(
WebSession
.
Response
);
response
.
SetOriginalHeaders
(
HttpClient
.
Response
);
//response already received from server but not yet ready to sent to client.
WebSession
.
Response
=
response
;
WebSession
.
Response
.
Locked
=
true
;
HttpClient
.
Response
=
response
;
HttpClient
.
Response
.
Locked
=
true
;
}
//request not yet sent/not yet ready to be sent.
else
{
WebSession
.
Request
.
Locked
=
true
;
WebSession
.
Request
.
CancelRequest
=
true
;
HttpClient
.
Request
.
Locked
=
true
;
HttpClient
.
Request
.
CancelRequest
=
true
;
//set new response.
WebSession
.
Response
=
response
;
WebSession
.
Response
.
Locked
=
true
;
HttpClient
.
Response
=
response
;
HttpClient
.
Response
.
Locked
=
true
;
}
}
...
...
@@ -607,7 +607,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public
void
TerminateServerConnection
()
{
WebSession
.
CloseServerConnection
=
true
;
HttpClient
.
CloseServerConnection
=
true
;
}
/// <summary>
...
...
src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
View file @
a7cab15f
...
...
@@ -8,6 +8,7 @@ using Titanium.Web.Proxy.Helpers;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network.Tcp
;
namespace
Titanium.Web.Proxy.EventArguments
{
...
...
@@ -19,8 +20,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public
abstract
class
SessionEventArgsBase
:
EventArgs
,
IDisposable
{
internal
readonly
CancellationTokenSource
CancellationTokenSource
;
internal
TcpServerConnection
ServerConnection
=>
HttpClient
.
Connection
;
internal
TcpClientConnection
ClientConnection
=>
ProxyClient
.
Connection
;
protected
readonly
int
bufferSize
;
protected
readonly
IBufferPool
bufferPool
;
...
...
@@ -50,10 +52,10 @@ namespace Titanium.Web.Proxy.EventArguments
CancellationTokenSource
=
cancellationTokenSource
;
ProxyClient
=
new
ProxyClient
();
WebSession
=
new
HttpWebClient
(
request
);
HttpClient
=
new
HttpWebClient
(
request
);
LocalEndPoint
=
endPoint
;
WebSession
.
ProcessId
=
new
Lazy
<
int
>(()
=>
HttpClient
.
ProcessId
=
new
Lazy
<
int
>(()
=>
{
if
(
RunTime
.
IsWindows
)
{
...
...
@@ -85,25 +87,27 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public
object
UserData
{
get
=>
WebSession
.
UserData
;
set
=>
WebSession
.
UserData
=
value
;
get
=>
HttpClient
.
UserData
;
set
=>
HttpClient
.
UserData
=
value
;
}
/// <summary>
/// Does this session uses SSL?
/// </summary>
public
bool
IsHttps
=>
WebSession
.
Request
.
IsHttps
;
public
bool
IsHttps
=>
HttpClient
.
Request
.
IsHttps
;
/// <summary>
/// Client End Point.
/// </summary>
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
ProxyClient
.
C
lientC
onnection
.
RemoteEndPoint
;
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
ProxyClient
.
Connection
.
RemoteEndPoint
;
/// <summary>
/// A web session corresponding to a single request/response sequence
/// within a proxy connection.
/// The web client used to communicate with server for this session.
/// </summary>
public
HttpWebClient
WebSession
{
get
;
}
public
HttpWebClient
HttpClient
{
get
;
}
[
Obsolete
(
"Use HttpClient instead."
)]
public
HttpWebClient
WebSession
=>
HttpClient
;
/// <summary>
/// Are we using a custom upstream HTTP(S) proxy?
...
...
@@ -136,7 +140,7 @@ namespace Titanium.Web.Proxy.EventArguments
DataReceived
=
null
;
Exception
=
null
;
WebSession
.
FinishSession
();
HttpClient
.
FinishSession
();
}
/// <summary>
...
...
src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs
View file @
a7cab15f
...
...
@@ -16,7 +16,7 @@ namespace Titanium.Web.Proxy.EventArguments
CancellationTokenSource
cancellationTokenSource
)
:
base
(
server
,
endPoint
,
cancellationTokenSource
,
connectRequest
)
{
WebSession
.
ConnectRequest
=
connectRequest
;
HttpClient
.
ConnectRequest
=
connectRequest
;
}
/// <summary>
...
...
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
View file @
a7cab15f
...
...
@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy
connectArgs
=
new
TunnelConnectSessionEventArgs
(
this
,
endPoint
,
connectRequest
,
cancellationTokenSource
);
connectArgs
.
ProxyClient
.
C
lientC
onnection
=
clientConnection
;
connectArgs
.
ProxyClient
.
Connection
=
clientConnection
;
connectArgs
.
ProxyClient
.
ClientStream
=
clientStream
;
await
endPoint
.
InvokeBeforeTunnelConnectRequest
(
this
,
connectArgs
,
ExceptionFunc
);
...
...
@@ -83,9 +83,9 @@ namespace Titanium.Web.Proxy
if
(
connectArgs
.
DenyConnect
)
{
if
(
connectArgs
.
WebSession
.
Response
.
StatusCode
==
0
)
if
(
connectArgs
.
HttpClient
.
Response
.
StatusCode
==
0
)
{
connectArgs
.
WebSession
.
Response
=
new
Response
connectArgs
.
HttpClient
.
Response
=
new
Response
{
HttpVersion
=
HttpHeader
.
Version11
,
StatusCode
=
(
int
)
HttpStatusCode
.
Forbidden
,
...
...
@@ -94,7 +94,7 @@ namespace Titanium.Web.Proxy
}
// send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
,
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
HttpClient
.
Response
,
cancellationToken
:
cancellationToken
);
return
;
}
...
...
@@ -104,7 +104,7 @@ namespace Titanium.Web.Proxy
await
endPoint
.
InvokeBeforeTunnectConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
);
// send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
,
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
HttpClient
.
Response
,
cancellationToken
:
cancellationToken
);
return
;
}
...
...
@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy
// Set ContentLength explicitly to properly handle HTTP 1.0
response
.
ContentLength
=
0
;
response
.
Headers
.
FixProxyHeaders
();
connectArgs
.
WebSession
.
Response
=
response
;
connectArgs
.
HttpClient
.
Response
=
response
;
await
clientStreamWriter
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
...
...
@@ -252,7 +252,7 @@ namespace Titanium.Web.Proxy
}
var
serverHelloInfo
=
await
SslTools
.
PeekServerHello
(
connection
.
Stream
,
BufferPool
,
cancellationToken
);
((
ConnectResponse
)
connectArgs
.
WebSession
.
Response
).
ServerHelloInfo
=
serverHelloInfo
;
((
ConnectResponse
)
connectArgs
.
HttpClient
.
Response
).
ServerHelloInfo
=
serverHelloInfo
;
}
await
TcpHelper
.
SendRaw
(
clientStream
,
connection
.
Stream
,
BufferPool
,
BufferSize
,
...
...
@@ -321,7 +321,7 @@ namespace Titanium.Web.Proxy
calledRequestHandler
=
true
;
// Now create the request
await
handleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
clientStreamWriter
,
cancellationTokenSource
,
connectHostname
,
connectArgs
?.
WebSession
.
ConnectRequest
,
prefetchConnectionTask
);
cancellationTokenSource
,
connectHostname
,
connectArgs
?.
HttpClient
.
ConnectRequest
,
prefetchConnectionTask
);
}
catch
(
ProxyException
e
)
{
...
...
src/Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
a7cab15f
...
...
@@ -17,16 +17,16 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
public
class
HttpWebClient
{
internal
HttpWebClient
(
Request
request
=
null
,
Response
response
=
null
)
internal
HttpWebClient
(
Request
request
)
{
Request
=
request
??
new
Request
();
Response
=
response
??
new
Response
();
Response
=
new
Response
();
}
/// <summary>
/// Connection to server
/// </summary>
internal
TcpServerConnection
Server
Connection
{
get
;
set
;
}
internal
TcpServerConnection
Connection
{
get
;
set
;
}
/// <summary>
/// Should we close the server connection at the end of this HTTP request/response session.
...
...
@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Http
internal
void
SetConnection
(
TcpServerConnection
serverConnection
)
{
serverConnection
.
LastAccess
=
DateTime
.
Now
;
Server
Connection
=
serverConnection
;
Connection
=
serverConnection
;
}
/// <summary>
...
...
@@ -91,11 +91,11 @@ namespace Titanium.Web.Proxy.Http
internal
async
Task
SendRequest
(
bool
enable100ContinueBehaviour
,
bool
isTransparent
,
CancellationToken
cancellationToken
)
{
var
upstreamProxy
=
Server
Connection
.
UpStreamProxy
;
var
upstreamProxy
=
Connection
.
UpStreamProxy
;
bool
useUpstreamProxy
=
upstreamProxy
!=
null
&&
Server
Connection
.
IsHttps
==
false
;
bool
useUpstreamProxy
=
upstreamProxy
!=
null
&&
Connection
.
IsHttps
==
false
;
var
writer
=
Server
Connection
.
StreamWriter
;
var
writer
=
Connection
.
StreamWriter
;
// prepare the request & headers
await
writer
.
WriteLineAsync
(
Request
.
CreateRequestLine
(
Request
.
Method
,
...
...
@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Http
// Send Authentication to Upstream proxy if needed
if
(!
isTransparent
&&
upstreamProxy
!=
null
&&
Server
Connection
.
IsHttps
==
false
&&
Connection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
upstreamProxy
.
UserName
)
&&
upstreamProxy
.
Password
!=
null
)
{
...
...
@@ -134,7 +134,7 @@ namespace Titanium.Web.Proxy.Http
string
httpStatus
;
try
{
httpStatus
=
await
Server
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
httpStatus
=
await
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
if
(
httpStatus
==
null
)
{
throw
new
ServerConnectionException
(
"Server connection was closed."
);
...
...
@@ -153,13 +153,13 @@ namespace Titanium.Web.Proxy.Http
&&
responseStatusDescription
.
EqualsIgnoreCase
(
"continue"
))
{
Request
.
Is100Continue
=
true
;
await
Server
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
await
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
}
else
if
(
responseStatusCode
==
(
int
)
HttpStatusCode
.
ExpectationFailed
&&
responseStatusDescription
.
EqualsIgnoreCase
(
"expectation failed"
))
{
Request
.
ExpectationFailed
=
true
;
await
Server
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
await
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
}
}
}
...
...
@@ -180,7 +180,7 @@ namespace Titanium.Web.Proxy.Http
string
httpStatus
;
try
{
httpStatus
=
await
Server
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
httpStatus
=
await
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
if
(
httpStatus
==
null
)
{
throw
new
ServerConnectionException
(
"Server connection was closed."
);
...
...
@@ -193,7 +193,7 @@ namespace Titanium.Web.Proxy.Http
if
(
httpStatus
==
string
.
Empty
)
{
httpStatus
=
await
Server
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
httpStatus
=
await
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
}
Response
.
ParseResponseLine
(
httpStatus
,
out
var
version
,
out
int
statusCode
,
out
string
statusDescription
);
...
...
@@ -209,7 +209,7 @@ namespace Titanium.Web.Proxy.Http
// Read the next line after 100-continue
Response
.
Is100Continue
=
true
;
Response
.
StatusCode
=
0
;
await
Server
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
await
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
// now receive response
await
ReceiveResponse
(
cancellationToken
);
...
...
@@ -222,7 +222,7 @@ namespace Titanium.Web.Proxy.Http
// read next line after expectation failed response
Response
.
ExpectationFailed
=
true
;
Response
.
StatusCode
=
0
;
await
Server
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
await
Connection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
// now receive response
await
ReceiveResponse
(
cancellationToken
);
...
...
@@ -230,7 +230,7 @@ namespace Titanium.Web.Proxy.Http
}
// Read the response headers in to unique and non-unique header collections
await
HeaderParser
.
ReadHeaders
(
Server
Connection
.
Stream
,
Response
.
Headers
,
cancellationToken
);
await
HeaderParser
.
ReadHeaders
(
Connection
.
Stream
,
Response
.
Headers
,
cancellationToken
);
}
/// <summary>
...
...
@@ -238,7 +238,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
internal
void
FinishSession
()
{
Server
Connection
=
null
;
Connection
=
null
;
ConnectRequest
?.
FinishSession
();
Request
?.
FinishSession
();
...
...
src/Titanium.Web.Proxy/Network/ProxyClient.cs
View file @
a7cab15f
...
...
@@ -12,7 +12,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// TcpClient connection used to communicate with client
/// </summary>
internal
TcpClientConnection
C
lientC
onnection
{
get
;
set
;
}
internal
TcpClientConnection
Connection
{
get
;
set
;
}
/// <summary>
/// Holds the stream to client
...
...
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
a7cab15f
...
...
@@ -98,10 +98,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
session
.
CustomUpStreamProxyUsed
=
customUpStreamProxy
;
return
GetConnectionCacheKey
(
session
.
WebSession
.
Request
.
RequestUri
.
Host
,
session
.
WebSession
.
Request
.
RequestUri
.
Port
,
session
.
HttpClient
.
Request
.
RequestUri
.
Host
,
session
.
HttpClient
.
Request
.
RequestUri
.
Port
,
isHttps
,
applicationProtocols
,
server
,
session
.
WebSession
.
UpStreamEndPoint
??
server
.
UpStreamEndPoint
,
server
,
session
.
HttpClient
.
UpStreamEndPoint
??
server
.
UpStreamEndPoint
,
customUpStreamProxy
??
(
isHttps
?
server
.
UpStreamHttpsProxy
:
server
.
UpStreamHttpProxy
));
}
...
...
@@ -148,11 +148,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
session
.
CustomUpStreamProxyUsed
=
customUpStreamProxy
;
return
await
GetServerConnection
(
session
.
WebSession
.
Request
.
RequestUri
.
Host
,
session
.
WebSession
.
Request
.
RequestUri
.
Port
,
session
.
WebSession
.
Request
.
HttpVersion
,
session
.
HttpClient
.
Request
.
RequestUri
.
Host
,
session
.
HttpClient
.
Request
.
RequestUri
.
Port
,
session
.
HttpClient
.
Request
.
HttpVersion
,
isHttps
,
applicationProtocols
,
isConnect
,
server
,
session
,
session
.
WebSession
.
UpStreamEndPoint
??
server
.
UpStreamEndPoint
,
server
,
session
,
session
.
HttpClient
.
UpStreamEndPoint
??
server
.
UpStreamEndPoint
,
customUpStreamProxy
??
(
isHttps
?
server
.
UpStreamHttpsProxy
:
server
.
UpStreamHttpProxy
),
noCache
,
cancellationToken
);
}
...
...
src/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
View file @
a7cab15f
...
...
@@ -26,14 +26,14 @@ namespace Titanium.Web.Proxy
return
true
;
}
var
httpHeaders
=
session
.
WebSession
.
Request
.
Headers
;
var
httpHeaders
=
session
.
HttpClient
.
Request
.
Headers
;
try
{
var
header
=
httpHeaders
.
GetFirstHeader
(
KnownHeaders
.
ProxyAuthorization
);
if
(
header
==
null
)
{
session
.
WebSession
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Required"
);
session
.
HttpClient
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Required"
);
return
false
;
}
...
...
@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy
if
(
headerValueParts
.
Length
!=
2
)
{
// Return not authorized
session
.
WebSession
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
HttpClient
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
return
false
;
}
...
...
@@ -57,7 +57,7 @@ namespace Titanium.Web.Proxy
if
(
result
.
Result
==
ProxyAuthenticationResult
.
ContinuationNeeded
)
{
session
.
WebSession
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
,
result
.
Continuation
);
session
.
HttpClient
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
,
result
.
Continuation
);
return
false
;
}
...
...
@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy
httpHeaders
));
// Return not authorized
session
.
WebSession
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
HttpClient
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
return
false
;
}
}
...
...
@@ -83,7 +83,7 @@ namespace Titanium.Web.Proxy
if
(!
headerValueParts
[
0
].
EqualsIgnoreCase
(
KnownHeaders
.
ProxyAuthorizationBasic
))
{
// Return not authorized
session
.
WebSession
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
HttpClient
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
return
false
;
}
...
...
@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy
if
(
colonIndex
==
-
1
)
{
// Return not authorized
session
.
WebSession
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
HttpClient
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
return
false
;
}
...
...
@@ -101,7 +101,7 @@ namespace Titanium.Web.Proxy
bool
authenticated
=
await
ProxyBasicAuthenticateFunc
(
session
,
username
,
password
);
if
(!
authenticated
)
{
session
.
WebSession
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
HttpClient
.
Response
=
createAuthentication407Response
(
"Proxy Authentication Invalid"
);
}
return
authenticated
;
...
...
src/Titanium.Web.Proxy/ProxyServer.cs
View file @
a7cab15f
...
...
@@ -679,7 +679,7 @@ namespace Titanium.Web.Proxy
/// <returns>The external proxy as task result.</returns>
private
Task
<
ExternalProxy
>
getSystemUpStreamProxy
(
SessionEventArgsBase
sessionEventArgs
)
{
var
proxy
=
systemProxyResolver
.
GetProxy
(
sessionEventArgs
.
WebSession
.
Request
.
RequestUri
);
var
proxy
=
systemProxyResolver
.
GetProxy
(
sessionEventArgs
.
HttpClient
.
Request
.
RequestUri
);
return
Task
.
FromResult
(
proxy
);
}
...
...
src/Titanium.Web.Proxy/RequestHandler.cs
View file @
a7cab15f
...
...
@@ -15,6 +15,7 @@ using Titanium.Web.Proxy.Extensions;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.Shared
;
...
...
@@ -71,8 +72,8 @@ namespace Titanium.Web.Proxy
var
args
=
new
SessionEventArgs
(
this
,
endPoint
,
cancellationTokenSource
)
{
ProxyClient
=
{
C
lientC
onnection
=
clientConnection
},
WebSession
=
{
ConnectRequest
=
connectRequest
}
ProxyClient
=
{
Connection
=
clientConnection
},
HttpClient
=
{
ConnectRequest
=
connectRequest
}
};
try
...
...
@@ -83,7 +84,7 @@ namespace Titanium.Web.Proxy
out
var
version
);
// Read the request headers in to unique and non-unique header collections
await
HeaderParser
.
ReadHeaders
(
clientStream
,
args
.
WebSession
.
Request
.
Headers
,
await
HeaderParser
.
ReadHeaders
(
clientStream
,
args
.
HttpClient
.
Request
.
Headers
,
cancellationToken
);
Uri
httpRemoteUri
;
...
...
@@ -100,7 +101,7 @@ namespace Titanium.Web.Proxy
}
else
{
string
host
=
args
.
WebSession
.
Request
.
Host
??
httpsConnectHostname
;
string
host
=
args
.
HttpClient
.
Request
.
Host
??
httpsConnectHostname
;
string
hostAndPath
=
host
;
if
(
httpUrl
.
StartsWith
(
"/"
))
{
...
...
@@ -119,7 +120,7 @@ namespace Titanium.Web.Proxy
}
}
var
request
=
args
.
WebSession
.
Request
;
var
request
=
args
.
HttpClient
.
Request
;
request
.
RequestUri
=
httpRemoteUri
;
request
.
OriginalUrl
=
httpUrl
;
...
...
@@ -136,7 +137,7 @@ namespace Titanium.Web.Proxy
await
invokeBeforeResponse
(
args
);
// send the response
await
clientStreamWriter
.
WriteResponseAsync
(
args
.
WebSession
.
Response
,
await
clientStreamWriter
.
WriteResponseAsync
(
args
.
HttpClient
.
Response
,
cancellationToken
:
cancellationToken
);
return
;
}
...
...
@@ -161,7 +162,7 @@ namespace Titanium.Web.Proxy
// If user requested interception do it
await
invokeBeforeRequest
(
args
);
var
response
=
args
.
WebSession
.
Response
;
var
response
=
args
.
HttpClient
.
Response
;
if
(
request
.
CancelRequest
)
{
...
...
@@ -197,49 +198,51 @@ namespace Titanium.Web.Proxy
connection
=
null
;
}
//a connection generator task with captured parameters via closure.
Func
<
Task
<
TcpServerConnection
>>
generator
=
()
=>
tcpConnectionFactory
.
GetServerConnection
(
this
,
args
,
isConnect
:
false
,
applicationProtocol
:
clientConnection
.
NegotiatedApplicationProtocol
,
noCache
:
false
,
cancellationToken
:
cancellationToken
);
//for connection pool, retry fails until cache is exhausted.
var
result
=
await
retryPolicy
<
ServerConnectionException
>().
ExecuteAsync
(
async
(
serverConnection
)
=>
RetryResult
result
;
if
(
request
.
UpgradeToWebSocket
)
{
args
.
TimeLine
[
"Connection Ready"
]
=
DateTime
.
Now
;
// if upgrading to websocket then relay the request without reading the contents
if
(
request
.
UpgradeToWebSocket
)
//a connection generator task with captured parameters via closure.
Func
<
Task
<
TcpServerConnection
>>
generator
=
()
=>
tcpConnectionFactory
.
GetServerConnection
(
this
,
args
,
isConnect
:
false
,
applicationProtocol
:
clientConnection
.
NegotiatedApplicationProtocol
,
noCache
:
false
,
cancellationToken
:
cancellationToken
);
//for connection pool, retry fails until cache is exhausted.
result
=
await
retryPolicy
<
ServerConnectionException
>().
ExecuteAsync
(
async
(
serverConnection
)
=>
{
args
.
TimeLine
[
"Connection Ready"
]
=
DateTime
.
Now
;
// if upgrading to websocket then relay the request without reading the contents
await
handleWebSocketUpgrade
(
httpCmd
,
args
,
request
,
response
,
clientStream
,
clientStreamWriter
,
serverConnection
,
cancellationTokenSource
,
cancellationToken
);
closeServerConnection
=
true
;
return
false
;
}
// construct the web request that we are going to issue on behalf of the client.
await
handleHttpSessionRequest
(
serverConnection
,
args
);
return
true
;
},
generator
,
connection
);
},
generator
,
connection
);
}
else
{
result
=
await
handleHttpSessionRequest
(
args
,
connection
,
clientConnection
.
NegotiatedApplicationProtocol
,
cancellationToken
);
}
//update connection to latest used
connection
=
result
.
LatestConnection
;
//throw if exception happened
if
(!
result
.
IsSuccess
)
if
(!
result
.
IsSuccess
)
{
throw
result
.
Exception
;
}
if
(!
result
.
Continue
)
if
(!
result
.
Continue
)
{
return
;
}
//user requested
if
(
args
.
WebSession
.
CloseServerConnection
)
if
(
args
.
HttpClient
.
CloseServerConnection
)
{
closeServerConnection
=
true
;
return
;
...
...
@@ -262,7 +265,7 @@ namespace Titanium.Web.Proxy
//between sessions without using it.
//Do not release authenticated connections for performance reasons.
//Otherwise it will keep authenticating per session.
if
(
EnableConnectionPool
&&
connection
!=
null
if
(
EnableConnectionPool
&&
connection
!=
null
&&
!
connection
.
IsWinAuthenticated
)
{
await
tcpConnectionFactory
.
Release
(
connection
);
...
...
@@ -297,6 +300,38 @@ namespace Titanium.Web.Proxy
}
}
private
async
Task
<
RetryResult
>
handleHttpSessionRequest
(
SessionEventArgs
args
,
TcpServerConnection
connection
,
SslApplicationProtocol
protocol
,
CancellationToken
cancellationToken
)
{
//host/scheme changed from ReRequest
if
(
args
.
ReRequest
&&
(
args
.
HttpClient
.
Request
.
IsHttps
!=
connection
.
IsHttps
||
args
.
HttpClient
.
Request
.
Host
!=
connection
.
HostName
))
{
connection
=
null
;
}
//a connection generator task with captured parameters via closure.
Func
<
Task
<
TcpServerConnection
>>
generator
=
()
=>
tcpConnectionFactory
.
GetServerConnection
(
this
,
args
,
isConnect
:
false
,
applicationProtocol
:
protocol
,
noCache
:
false
,
cancellationToken
:
cancellationToken
);
//for connection pool, retry fails until cache is exhausted.
return
await
retryPolicy
<
ServerConnectionException
>().
ExecuteAsync
(
async
(
serverConnection
)
=>
{
args
.
TimeLine
[
"Connection Ready"
]
=
DateTime
.
Now
;
// construct the web request that we are going to issue on behalf of the client.
await
handleHttpSessionRequest
(
serverConnection
,
args
);
return
true
;
},
generator
,
connection
);
}
/// <summary>
/// Handle a specific session (request/response sequence)
/// </summary>
...
...
@@ -306,7 +341,7 @@ namespace Titanium.Web.Proxy
private
async
Task
handleHttpSessionRequest
(
TcpServerConnection
serverConnection
,
SessionEventArgs
args
)
{
var
cancellationToken
=
args
.
CancellationTokenSource
.
Token
;
var
request
=
args
.
WebSession
.
Request
;
var
request
=
args
.
HttpClient
.
Request
;
request
.
Locked
=
true
;
var
body
=
request
.
CompressBodyAndUpdateContentLength
();
...
...
@@ -315,8 +350,8 @@ namespace Titanium.Web.Proxy
// and see if server would return 100 conitinue
if
(
request
.
ExpectContinue
)
{
args
.
WebSession
.
SetConnection
(
serverConnection
);
await
args
.
WebSession
.
SendRequest
(
Enable100ContinueBehaviour
,
args
.
IsTransparent
,
args
.
HttpClient
.
SetConnection
(
serverConnection
);
await
args
.
HttpClient
.
SendRequest
(
Enable100ContinueBehaviour
,
args
.
IsTransparent
,
cancellationToken
);
}
...
...
@@ -327,13 +362,13 @@ namespace Titanium.Web.Proxy
if
(
request
.
Is100Continue
)
{
await
clientStreamWriter
.
WriteResponseStatusAsync
(
args
.
WebSession
.
Response
.
HttpVersion
,
await
clientStreamWriter
.
WriteResponseStatusAsync
(
args
.
HttpClient
.
Response
.
HttpVersion
,
(
int
)
HttpStatusCode
.
Continue
,
"Continue"
,
cancellationToken
);
await
clientStreamWriter
.
WriteLineAsync
(
cancellationToken
);
}
else
if
(
request
.
ExpectationFailed
)
{
await
clientStreamWriter
.
WriteResponseStatusAsync
(
args
.
WebSession
.
Response
.
HttpVersion
,
await
clientStreamWriter
.
WriteResponseStatusAsync
(
args
.
HttpClient
.
Response
.
HttpVersion
,
(
int
)
HttpStatusCode
.
ExpectationFailed
,
"Expectation Failed"
,
cancellationToken
);
await
clientStreamWriter
.
WriteLineAsync
(
cancellationToken
);
}
...
...
@@ -342,8 +377,8 @@ namespace Titanium.Web.Proxy
// If expect continue is not enabled then set the connectio and send request headers
if
(!
request
.
ExpectContinue
)
{
args
.
WebSession
.
SetConnection
(
serverConnection
);
await
args
.
WebSession
.
SendRequest
(
Enable100ContinueBehaviour
,
args
.
IsTransparent
,
args
.
HttpClient
.
SetConnection
(
serverConnection
);
await
args
.
HttpClient
.
SendRequest
(
Enable100ContinueBehaviour
,
args
.
IsTransparent
,
cancellationToken
);
}
...
...
@@ -352,7 +387,7 @@ namespace Titanium.Web.Proxy
{
if
(
request
.
IsBodyRead
)
{
var
writer
=
args
.
WebSession
.
Server
Connection
.
StreamWriter
;
var
writer
=
args
.
HttpClient
.
Connection
.
StreamWriter
;
await
writer
.
WriteBodyAsync
(
body
,
request
.
IsChunked
,
cancellationToken
);
}
else
...
...
@@ -361,7 +396,7 @@ namespace Titanium.Web.Proxy
{
if
(
request
.
HasBody
)
{
HttpWriter
writer
=
args
.
WebSession
.
Server
Connection
.
StreamWriter
;
HttpWriter
writer
=
args
.
HttpClient
.
Connection
.
StreamWriter
;
await
args
.
CopyRequestBodyAsync
(
writer
,
TransformationMode
.
None
,
cancellationToken
);
}
}
...
...
src/Titanium.Web.Proxy/ResponseHandler.cs
View file @
a7cab15f
...
...
@@ -22,11 +22,11 @@ namespace Titanium.Web.Proxy
var
cancellationToken
=
args
.
CancellationTokenSource
.
Token
;
// read response & headers from server
await
args
.
WebSession
.
ReceiveResponse
(
cancellationToken
);
await
args
.
HttpClient
.
ReceiveResponse
(
cancellationToken
);
args
.
TimeLine
[
"Response Received"
]
=
DateTime
.
Now
;
var
response
=
args
.
WebSession
.
Response
;
var
response
=
args
.
HttpClient
.
Response
;
args
.
ReRequest
=
false
;
// check for windows authentication
...
...
@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy
}
else
{
WinAuthEndPoint
.
AuthenticatedResponse
(
args
.
WebSession
.
Data
);
WinAuthEndPoint
.
AuthenticatedResponse
(
args
.
HttpClient
.
Data
);
}
}
...
...
@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy
}
// it may changed in the user event
response
=
args
.
WebSession
.
Response
;
response
=
args
.
HttpClient
.
Response
;
var
clientStreamWriter
=
args
.
ProxyClient
.
ClientStreamWriter
;
...
...
@@ -63,8 +63,8 @@ namespace Titanium.Web.Proxy
//write custom user response with body and return.
await
clientStreamWriter
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
if
(
args
.
WebSession
.
Server
Connection
!=
null
&&
!
args
.
WebSession
.
CloseServerConnection
)
if
(
args
.
HttpClient
.
Connection
!=
null
&&
!
args
.
HttpClient
.
CloseServerConnection
)
{
// syphon out the original response body from server connection
// so that connection will be good to be reused.
...
...
@@ -80,7 +80,8 @@ namespace Titanium.Web.Proxy
{
// clear current response
await
args
.
ClearResponse
(
cancellationToken
);
await
handleHttpSessionRequest
(
args
.
WebSession
.
ServerConnection
,
args
);
await
handleHttpSessionRequest
(
args
,
args
.
HttpClient
.
Connection
,
args
.
ClientConnection
.
NegotiatedApplicationProtocol
,
cancellationToken
);
return
;
}
...
...
src/Titanium.Web.Proxy/WebSocketHandler.cs
View file @
a7cab15f
...
...
@@ -58,7 +58,7 @@ namespace Titanium.Web.Proxy
}
// If user requested call back then do it
if
(!
args
.
WebSession
.
Response
.
Locked
)
if
(!
args
.
HttpClient
.
Response
.
Locked
)
{
await
invokeBeforeResponse
(
args
);
}
...
...
src/Titanium.Web.Proxy/WinAuthHandler.cs
View file @
a7cab15f
...
...
@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy
string
headerName
=
null
;
HttpHeader
authHeader
=
null
;
var
response
=
args
.
WebSession
.
Response
;
var
response
=
args
.
HttpClient
.
Response
;
// check in non-unique headers first
var
header
=
response
.
Headers
.
NonUniqueHeaders
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Contains
(
x
.
Key
));
...
...
@@ -96,14 +96,14 @@ namespace Titanium.Web.Proxy
var
expectedAuthState
=
scheme
==
null
?
State
.
WinAuthState
.
INITIAL_TOKEN
:
State
.
WinAuthState
.
UNAUTHORIZED
;
if
(!
WinAuthEndPoint
.
ValidateWinAuthState
(
args
.
WebSession
.
Data
,
expectedAuthState
))
if
(!
WinAuthEndPoint
.
ValidateWinAuthState
(
args
.
HttpClient
.
Data
,
expectedAuthState
))
{
// Invalid state, create proper error message to client
await
rewriteUnauthorizedResponse
(
args
);
return
;
}
var
request
=
args
.
WebSession
.
Request
;
var
request
=
args
.
HttpClient
.
Request
;
// clear any existing headers to avoid confusing bad servers
request
.
Headers
.
RemoveHeader
(
KnownHeaders
.
Authorization
);
...
...
@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy
// initial value will match exactly any of the schemes
if
(
scheme
!=
null
)
{
string
clientToken
=
WinAuthHandler
.
GetInitialAuthToken
(
request
.
Host
,
scheme
,
args
.
WebSession
.
Data
);
string
clientToken
=
WinAuthHandler
.
GetInitialAuthToken
(
request
.
Host
,
scheme
,
args
.
HttpClient
.
Data
);
string
auth
=
string
.
Concat
(
scheme
,
clientToken
);
...
...
@@ -133,7 +133,7 @@ namespace Titanium.Web.Proxy
authHeader
.
Value
.
Length
>
x
.
Length
+
1
);
string
serverToken
=
authHeader
.
Value
.
Substring
(
scheme
.
Length
+
1
);
string
clientToken
=
WinAuthHandler
.
GetFinalAuthToken
(
request
.
Host
,
serverToken
,
args
.
WebSession
.
Data
);
string
clientToken
=
WinAuthHandler
.
GetFinalAuthToken
(
request
.
Host
,
serverToken
,
args
.
HttpClient
.
Data
);
string
auth
=
string
.
Concat
(
scheme
,
clientToken
);
...
...
@@ -146,7 +146,7 @@ namespace Titanium.Web.Proxy
request
.
ContentLength
=
request
.
Body
.
Length
;
}
args
.
WebSession
.
Server
Connection
.
IsWinAuthenticated
=
true
;
args
.
HttpClient
.
Connection
.
IsWinAuthenticated
=
true
;
}
// Need to revisit this.
...
...
@@ -165,7 +165,7 @@ namespace Titanium.Web.Proxy
/// <returns></returns>
private
async
Task
rewriteUnauthorizedResponse
(
SessionEventArgs
args
)
{
var
response
=
args
.
WebSession
.
Response
;
var
response
=
args
.
HttpClient
.
Response
;
// Strip authentication headers to avoid credentials prompt in client web browser
foreach
(
string
authHeaderName
in
authHeaderNames
)
...
...
@@ -176,7 +176,7 @@ namespace Titanium.Web.Proxy
// Add custom div to body to clarify that the proxy (not the client browser) failed authentication
string
authErrorMessage
=
"<div class=\"inserted-by-proxy\"><h2>NTLM authentication through Titanium.Web.Proxy ("
+
args
.
ProxyClient
.
C
lientC
onnection
.
LocalEndPoint
+
args
.
ProxyClient
.
Connection
.
LocalEndPoint
+
") failed. Please check credentials.</h2></div>"
;
string
originalErrorMessage
=
"<div class=\"inserted-by-proxy\"><h3>Response from remote web server below.</h3></div><br/>"
;
...
...
tests/Titanium.Web.Proxy.IntegrationTests/InterceptionTests.cs
View file @
a7cab15f
...
...
@@ -46,9 +46,9 @@ namespace Titanium.Web.Proxy.IntegrationTests
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
if
(
e
.
WebSession
.
Request
.
Url
.
Contains
(
"interceptthis.com"
))
if
(
e
.
HttpClient
.
Request
.
Url
.
Contains
(
"interceptthis.com"
))
{
if
(
e
.
WebSession
.
Request
.
HasBody
)
if
(
e
.
HttpClient
.
Request
.
HasBody
)
{
var
body
=
await
e
.
GetRequestBodyAsString
();
}
...
...
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