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
46140093
Commit
46140093
authored
Jun 25, 2017
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Websocket fix in GUI demo + handle user exceptions in TWP
parent
91f00ec7
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
112 additions
and
58 deletions
+112
-58
MainWindow.xaml.cs
Examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
+22
-7
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+22
-15
FuncExtensions.cs
Titanium.Web.Proxy/Extensions/FuncExtensions.cs
+15
-2
Response.cs
Titanium.Web.Proxy/Http/Response.cs
+25
-0
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+4
-4
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+24
-30
No files found.
Examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
View file @
46140093
...
...
@@ -119,7 +119,10 @@ namespace Titanium.Web.Proxy.Examples.Wpf
if
(
item
!=
null
)
{
item
.
ResponseBody
=
await
e
.
GetResponseBody
();
if
(
e
.
WebSession
.
Response
.
HasBody
)
{
item
.
ResponseBody
=
await
e
.
GetResponseBody
();
}
}
}
...
...
@@ -195,18 +198,30 @@ namespace Titanium.Web.Proxy.Examples.Wpf
return
;
}
const
int
truncateLimit
=
1024
;
var
session
=
SelectedSession
;
var
data
=
session
.
RequestBody
??
new
byte
[
0
];
data
=
data
.
Take
(
1024
).
ToArray
();
bool
truncated
=
data
.
Length
>
truncateLimit
;
if
(
truncated
)
{
data
=
data
.
Take
(
truncateLimit
).
ToArray
();
}
string
dataStr
=
string
.
Join
(
" "
,
data
.
Select
(
x
=>
x
.
ToString
(
"X2"
)));
TextBoxRequest
.
Text
=
session
.
Request
.
HeaderText
+
dataStr
;
//string hexStr = string.Join(" ", data.Select(x => x.ToString("X2")));
TextBoxRequest
.
Text
=
session
.
Request
.
HeaderText
+
session
.
Request
.
Encoding
.
GetString
(
data
)
+
(
truncated
?
Environment
.
NewLine
+
$"Data is truncated after
{
truncateLimit
}
bytes"
:
null
);
data
=
session
.
ResponseBody
??
new
byte
[
0
];
data
=
data
.
Take
(
1024
).
ToArray
();
truncated
=
data
.
Length
>
truncateLimit
;
if
(
truncated
)
{
data
=
data
.
Take
(
truncateLimit
).
ToArray
();
}
dataStr
=
string
.
Join
(
" "
,
data
.
Select
(
x
=>
x
.
ToString
(
"X2"
)));
TextBoxResponse
.
Text
=
session
.
Response
.
HeaderText
+
dataStr
;
//hexStr = string.Join(" ", data.Select(x => x.ToString("X2")));
TextBoxResponse
.
Text
=
session
.
Response
.
HeaderText
+
session
.
Response
.
Encoding
.
GetString
(
data
)
+
(
truncated
?
Environment
.
NewLine
+
$"Data is truncated after
{
truncateLimit
}
bytes"
:
null
);
}
}
}
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
46140093
...
...
@@ -198,28 +198,35 @@ namespace Titanium.Web.Proxy.EventArguments
//If not already read (not cached yet)
if
(
WebSession
.
Response
.
ResponseBody
==
null
)
{
using
(
var
responseBodyStream
=
new
MemoryStream
()
)
if
(
WebSession
.
Response
.
HasBody
)
{
//If chuncked the read chunk by chunk until we hit chunk end symbol
if
(
WebSession
.
Response
.
IsChunked
)
using
(
var
responseBodyStream
=
new
MemoryStream
())
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStreamChunked
(
responseBodyStream
);
}
else
{
if
(
WebSession
.
Response
.
ContentLength
>
0
)
//If chuncked the read chunk by chunk until we hit chunk end symbol
if
(
WebSession
.
Response
.
IsChunked
)
{
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
WebSession
.
Response
.
ContentLength
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStreamChunked
(
responseBodyStream
);
}
else
if
(
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
||
WebSession
.
Response
.
ContentLength
==
-
1
)
else
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
long
.
MaxValue
);
if
(
WebSession
.
Response
.
ContentLength
>
0
)
{
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
WebSession
.
Response
.
ContentLength
);
}
else
if
(
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
||
WebSession
.
Response
.
ContentLength
==
-
1
)
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
long
.
MaxValue
);
}
}
}
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
());
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
());
}
}
else
{
WebSession
.
Response
.
ResponseBody
=
new
byte
[
0
];
}
//set this to true for caching
...
...
Titanium.Web.Proxy/Extensions/FuncExtensions.cs
View file @
46140093
...
...
@@ -18,17 +18,30 @@ namespace Titanium.Web.Proxy.Extensions
Task
.
WhenAll
(
handlerTasks
).
Wait
();
}
public
static
async
Task
InvokeParallelAsync
<
T
>(
this
Func
<
object
,
T
,
Task
>
callback
,
object
sender
,
T
args
)
public
static
async
Task
InvokeParallelAsync
<
T
>(
this
Func
<
object
,
T
,
Task
>
callback
,
object
sender
,
T
args
,
Action
<
Exception
>
exceptionFunc
)
{
var
invocationList
=
callback
.
GetInvocationList
();
var
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
handlerTasks
[
i
]
=
((
Func
<
object
,
T
,
Task
>)
invocationList
[
i
])(
sender
,
args
);
handlerTasks
[
i
]
=
InvokeAsync
((
Func
<
object
,
T
,
Task
>)
invocationList
[
i
],
sender
,
args
,
exceptionFunc
);
}
await
Task
.
WhenAll
(
handlerTasks
);
}
private
static
async
Task
InvokeAsync
<
T
>(
Func
<
object
,
T
,
Task
>
callback
,
object
sender
,
T
args
,
Action
<
Exception
>
exceptionFunc
)
{
try
{
await
callback
(
sender
,
args
);
}
catch
(
Exception
ex
)
{
var
ex2
=
new
Exception
(
"Exception thrown in user event"
,
ex
);
exceptionFunc
(
ex2
);
}
}
}
}
Titanium.Web.Proxy/Http/Response.cs
View file @
46140093
...
...
@@ -37,6 +37,31 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
public
Version
HttpVersion
{
get
;
set
;
}
/// <summary>
/// Has response body?
/// </summary>
public
bool
HasBody
{
get
{
//Has body only if response is chunked or content length >0
//If none are true then check if connection:close header exist, if so write response until server or client terminates the connection
if
(
IsChunked
||
ContentLength
>
0
||
!
ResponseKeepAlive
)
{
return
true
;
}
//has response if connection:keep-alive header exist and when version is http/1.0
//Because in Http 1.0 server can return a response without content-length (expectation being client would read until end of stream)
if
(
ResponseKeepAlive
&&
HttpVersion
.
Minor
==
0
)
{
return
true
;
}
return
false
;
}
}
/// <summary>
/// Keep the connection alive?
/// </summary>
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
46140093
...
...
@@ -111,14 +111,14 @@ namespace Titanium.Web.Proxy
if
(
TunnelConnectRequest
!=
null
)
{
await
TunnelConnectRequest
.
InvokeParallelAsync
(
this
,
connectArgs
);
await
TunnelConnectRequest
.
InvokeParallelAsync
(
this
,
connectArgs
,
ExceptionFunc
);
}
if
(!
excluded
&&
await
CheckAuthorization
(
clientStreamWriter
,
connectArgs
)
==
false
)
{
if
(
TunnelConnectResponse
!=
null
)
{
await
TunnelConnectResponse
.
InvokeParallelAsync
(
this
,
connectArgs
);
await
TunnelConnectResponse
.
InvokeParallelAsync
(
this
,
connectArgs
,
ExceptionFunc
);
}
return
;
...
...
@@ -133,7 +133,7 @@ namespace Titanium.Web.Proxy
if
(
TunnelConnectResponse
!=
null
)
{
connectArgs
.
IsHttps
=
isClientHello
;
await
TunnelConnectResponse
.
InvokeParallelAsync
(
this
,
connectArgs
);
await
TunnelConnectResponse
.
InvokeParallelAsync
(
this
,
connectArgs
,
ExceptionFunc
);
}
if
(!
excluded
&&
isClientHello
)
...
...
@@ -349,7 +349,7 @@ namespace Titanium.Web.Proxy
//If user requested interception do it
if
(
BeforeRequest
!=
null
)
{
await
BeforeRequest
.
InvokeParallelAsync
(
this
,
args
);
await
BeforeRequest
.
InvokeParallelAsync
(
this
,
args
,
ExceptionFunc
);
}
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
46140093
...
...
@@ -31,10 +31,12 @@ namespace Titanium.Web.Proxy
//read response & headers from server
await
args
.
WebSession
.
ReceiveResponse
();
var
response
=
args
.
WebSession
.
Response
;
//check for windows authentication
if
(
EnableWinAuth
&&
!
RunTime
.
IsRunningOnMono
&&
args
.
WebSession
.
R
esponse
.
ResponseStatusCode
==
"401"
)
&&
r
esponse
.
ResponseStatusCode
==
"401"
)
{
bool
disposed
=
await
Handle401UnAuthorized
(
args
);
...
...
@@ -47,9 +49,9 @@ namespace Titanium.Web.Proxy
args
.
ReRequest
=
false
;
//If user requested call back then do it
if
(
BeforeResponse
!=
null
&&
!
args
.
WebSession
.
R
esponse
.
ResponseLocked
)
if
(
BeforeResponse
!=
null
&&
!
r
esponse
.
ResponseLocked
)
{
await
BeforeResponse
.
InvokeParallelAsync
(
this
,
args
);
await
BeforeResponse
.
InvokeParallelAsync
(
this
,
args
,
ExceptionFunc
);
}
//if user requested to send request again
...
...
@@ -62,63 +64,55 @@ namespace Titanium.Web.Proxy
return
disposed
;
}
args
.
WebSession
.
R
esponse
.
ResponseLocked
=
true
;
r
esponse
.
ResponseLocked
=
true
;
//Write back to client 100-conitinue response if that's what server returned
if
(
args
.
WebSession
.
R
esponse
.
Is100Continue
)
if
(
r
esponse
.
Is100Continue
)
{
await
WriteResponseStatus
(
args
.
WebSession
.
R
esponse
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
WriteResponseStatus
(
r
esponse
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
args
.
ProxyClient
.
ClientStreamWriter
.
WriteLineAsync
();
}
else
if
(
args
.
WebSession
.
R
esponse
.
ExpectationFailed
)
else
if
(
r
esponse
.
ExpectationFailed
)
{
await
WriteResponseStatus
(
args
.
WebSession
.
R
esponse
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
WriteResponseStatus
(
r
esponse
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
args
.
ProxyClient
.
ClientStreamWriter
.
WriteLineAsync
();
}
//Write back response status to client
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
args
.
WebSession
.
R
esponse
.
ResponseStatusCode
,
args
.
WebSession
.
R
esponse
.
ResponseStatusDescription
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
WriteResponseStatus
(
response
.
HttpVersion
,
r
esponse
.
ResponseStatusCode
,
r
esponse
.
ResponseStatusDescription
,
args
.
ProxyClient
.
ClientStreamWriter
);
if
(
args
.
WebSession
.
R
esponse
.
ResponseBodyRead
)
if
(
r
esponse
.
ResponseBodyRead
)
{
bool
isChunked
=
args
.
WebSession
.
R
esponse
.
IsChunked
;
string
contentEncoding
=
args
.
WebSession
.
R
esponse
.
ContentEncoding
;
bool
isChunked
=
r
esponse
.
IsChunked
;
string
contentEncoding
=
r
esponse
.
ContentEncoding
;
if
(
contentEncoding
!=
null
)
{
args
.
WebSession
.
Response
.
ResponseBody
=
await
GetCompressedResponseBody
(
contentEncoding
,
args
.
WebSession
.
R
esponse
.
ResponseBody
);
response
.
ResponseBody
=
await
GetCompressedResponseBody
(
contentEncoding
,
r
esponse
.
ResponseBody
);
if
(
isChunked
==
false
)
{
args
.
WebSession
.
Response
.
ContentLength
=
args
.
WebSession
.
R
esponse
.
ResponseBody
.
Length
;
response
.
ContentLength
=
r
esponse
.
ResponseBody
.
Length
;
}
else
{
args
.
WebSession
.
R
esponse
.
ContentLength
=
-
1
;
r
esponse
.
ContentLength
=
-
1
;
}
}
await
WriteResponseHeaders
(
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
R
esponse
);
await
args
.
ProxyClient
.
ClientStream
.
WriteResponseBody
(
args
.
WebSession
.
R
esponse
.
ResponseBody
,
isChunked
);
await
WriteResponseHeaders
(
args
.
ProxyClient
.
ClientStreamWriter
,
r
esponse
);
await
args
.
ProxyClient
.
ClientStream
.
WriteResponseBody
(
r
esponse
.
ResponseBody
,
isChunked
);
}
else
{
await
WriteResponseHeaders
(
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
R
esponse
);
await
WriteResponseHeaders
(
args
.
ProxyClient
.
ClientStreamWriter
,
r
esponse
);
//Write body only if response is chunked or content length >0
//Is none are true then check if connection:close header exist, if so write response until server or client terminates the connection
if
(
args
.
WebSession
.
Response
.
IsChunked
||
args
.
WebSession
.
Response
.
ContentLength
>
0
||
!
args
.
WebSession
.
Response
.
ResponseKeepAlive
)
{
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BufferSize
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
}
//write response if connection:keep-alive header exist and when version is http/1.0
//Because in Http 1.0 server can return a response without content-length (expectation being client would read until end of stream)
else
if
(
args
.
WebSession
.
Response
.
ResponseKeepAlive
&&
args
.
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
//Write body if exists
if
(
response
.
HasBody
)
{
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BufferSize
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
R
esponse
.
ContentLength
);
response
.
IsChunked
,
r
esponse
.
ContentLength
);
}
}
...
...
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