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
f69bed23
Commit
f69bed23
authored
Jan 01, 2016
by
titanium007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix connection cache
parent
8242536d
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
137 additions
and
68 deletions
+137
-68
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+2
-2
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+17
-16
TcpConnectionManager.cs
Titanium.Web.Proxy/Http/TcpConnectionManager.cs
+17
-9
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+1
-1
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+31
-10
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+69
-30
No files found.
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
f69bed23
...
...
@@ -93,8 +93,8 @@ namespace Titanium.Web.Proxy.EventArguments
//if (ProxyRequest != null)
// ProxyRequest.Abort();
if
(
ResponseStream
!=
null
)
ResponseStream
.
Dispose
();
//
if (ResponseStream != null)
//
ResponseStream.Dispose();
//if (ServerResponse != null)
// ServerResponse.Close();
...
...
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
f69bed23
...
...
@@ -81,36 +81,42 @@ namespace Titanium.Web.Proxy.Http
public
Request
Request
{
get
;
set
;
}
public
Response
Response
{
get
;
set
;
}
public
TcpC
lient
Client
{
get
;
set
;
}
public
TcpC
onnection
Client
{
get
;
set
;
}
public
void
SetConnection
(
TcpConnection
Connection
)
{
Client
=
Connection
;
ServerStreamReader
=
Client
.
ServerStreamReader
;
}
public
HttpWebSession
()
{
this
.
Request
=
new
Request
();
this
.
Response
=
new
Response
();
}
public
CustomBinaryReader
ServerStreamReader
{
get
;
set
;
}
public
async
Task
SendRequest
()
{
Stream
stream
=
Client
.
GetStream
()
;
Stream
stream
=
Client
.
Stream
;
StringBuilder
requestLines
=
new
StringBuilder
();
requestLines
.
AppendLine
(
string
.
Join
(
" "
,
new
string
[
3
]
{
this
.
Request
.
Method
,
this
.
Request
.
RequestUri
.
AbsolutePath
,
this
.
Request
.
RequestUri
.
PathAndQuery
,
this
.
Request
.
Version
}));
foreach
(
HttpHeader
httpHeader
in
this
.
Request
.
RequestHeaders
)
{
requestLines
.
AppendLine
(
httpHeader
.
Name
+
':'
+
httpHeader
.
Value
);
}
requestLines
.
AppendLine
();
requestLines
.
AppendLine
();
...
...
@@ -122,9 +128,7 @@ namespace Titanium.Web.Proxy.Http
public
void
ReceiveResponse
()
{
Stream
stream
=
Client
.
GetStream
();
ServerStreamReader
=
new
CustomBinaryReader
(
stream
,
Encoding
.
ASCII
);
var
httpResult
=
ServerStreamReader
.
ReadLine
().
Split
(
' '
);
var
httpResult
=
ServerStreamReader
.
ReadLine
().
Split
(
new
char
[]
{
' '
},
3
);
var
httpVersion
=
httpResult
[
0
];
...
...
@@ -141,17 +145,14 @@ namespace Titanium.Web.Proxy.Http
this
.
Response
.
ResponseProtocolVersion
=
version
;
this
.
Response
.
ResponseStatusCode
=
httpResult
[
1
];
string
status
=
httpResult
[
2
];
for
(
int
i
=
3
;
i
<
httpResult
.
Length
;
i
++)
{
status
=
status
+
Space
+
httpResult
[
i
];
}
this
.
Response
.
ResponseStatusDescription
=
status
;
List
<
string
>
responseLines
=
ServerStreamReader
.
ReadAllLines
();
for
(
int
index
=
0
;
index
<
responseLines
.
Count
;
++
index
)
{
string
[]
strArray
=
responseLines
[
index
].
Split
(
':'
);
string
[]
strArray
=
responseLines
[
index
].
Split
(
new
char
[]
{
':'
},
2
);
this
.
Response
.
ResponseHeaders
.
Add
(
new
HttpHeader
(
strArray
[
0
],
strArray
[
1
]));
}
}
...
...
Titanium.Web.Proxy/Http/TcpConnectionManager.cs
View file @
f69bed23
...
...
@@ -7,25 +7,32 @@ using System.Collections.Concurrent;
using
System.Threading.Tasks
;
using
System.IO
;
using
System.Net.Security
;
using
Titanium.Web.Proxy.Helpers
;
namespace
Titanium.Web.Proxy.Http
{
public
class
TcpConnection
{
public
TcpClient
Client
{
get
;
set
;
}
public
CustomBinaryReader
ServerStreamReader
{
get
;
set
;
}
public
Stream
Stream
{
get
;
set
;
}
}
internal
class
TcpConnectionManager
{
static
ConcurrentDictionary
<
string
,
ConcurrentStack
<
TcpC
lient
>>
ConnectionCache
=
new
ConcurrentDictionary
<
string
,
ConcurrentStack
<
TcpClient
>>();
static
ConcurrentDictionary
<
string
,
ConcurrentStack
<
TcpC
onnection
>>
ConnectionCache
=
new
ConcurrentDictionary
<
string
,
ConcurrentStack
<
TcpConnection
>>();
public
static
async
Task
<
TcpC
lient
>
GetClient
(
string
Hostname
,
int
port
,
bool
IsSecure
)
public
static
async
Task
<
TcpC
onnection
>
GetClient
(
string
Hostname
,
int
port
,
bool
IsSecure
)
{
var
key
=
string
.
Concat
(
Hostname
,
":"
,
port
,
":"
,
IsSecure
);
ConcurrentStack
<
TcpC
lient
>
connections
;
ConcurrentStack
<
TcpC
onnection
>
connections
;
if
(!
ConnectionCache
.
TryGetValue
(
key
,
out
connections
))
{
return
await
CreateClient
(
Hostname
,
port
,
IsSecure
);
}
TcpC
lient
client
;
TcpC
onnection
client
;
if
(!
connections
.
TryPop
(
out
client
))
{
return
await
CreateClient
(
Hostname
,
port
,
IsSecure
);
...
...
@@ -33,7 +40,7 @@ namespace Titanium.Web.Proxy.Http
return
client
;
}
private
static
async
Task
<
TcpC
lient
>
CreateClient
(
string
Hostname
,
int
port
,
bool
IsSecure
)
private
static
async
Task
<
TcpC
onnection
>
CreateClient
(
string
Hostname
,
int
port
,
bool
IsSecure
)
{
var
client
=
new
TcpClient
(
Hostname
,
port
);
var
stream
=
(
Stream
)
client
.
GetStream
();
...
...
@@ -54,17 +61,18 @@ namespace Titanium.Web.Proxy.Http
throw
;
}
}
return
client
;
return
new
TcpConnection
()
{
Client
=
client
,
ServerStreamReader
=
new
CustomBinaryReader
(
stream
,
Encoding
.
ASCII
),
Stream
=
stream
};
}
public
static
void
AddClient
(
string
Hostname
,
int
port
,
bool
IsSecure
,
TcpC
lient
Client
)
public
static
void
AddClient
(
string
Hostname
,
int
port
,
bool
IsSecure
,
TcpC
onnection
Client
)
{
var
key
=
string
.
Concat
(
Hostname
,
":"
,
port
,
":"
,
IsSecure
);
ConcurrentStack
<
TcpC
lient
>
connections
;
ConcurrentStack
<
TcpC
onnection
>
connections
;
if
(!
ConnectionCache
.
TryGetValue
(
key
,
out
connections
))
{
connections
=
new
ConcurrentStack
<
TcpC
lient
>();
connections
=
new
ConcurrentStack
<
TcpC
onnection
>();
connections
.
Push
(
Client
);
ConnectionCache
.
TryAdd
(
key
,
connections
);
}
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
f69bed23
...
...
@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy
private
static
readonly
Regex
CookieSplitRegEx
=
new
Regex
(
@",(?! )"
);
private
static
readonly
byte
[]
ChunkTrail
=
Encoding
.
ASCII
.
GetBytes
(
Environment
.
NewLine
);
private
static
readonly
byte
[]
NewLineBytes
=
Encoding
.
ASCII
.
GetBytes
(
Environment
.
NewLine
);
private
static
readonly
byte
[]
ChunkEnd
=
Encoding
.
ASCII
.
GetBytes
(
0.
ToString
(
"x2"
)
+
Environment
.
NewLine
+
Environment
.
NewLine
);
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
f69bed23
...
...
@@ -30,6 +30,7 @@ namespace Titanium.Web.Proxy
try
{
//read the first line HTTP command
var
httpCmd
=
clientStreamReader
.
ReadLine
();
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
...
...
@@ -156,7 +157,7 @@ namespace Titanium.Web.Proxy
while
(!
string
.
IsNullOrEmpty
(
tmpLine
=
clientStreamReader
.
ReadLine
()))
{
var
header
=
tmpLine
.
Split
(
ColonSpaceSplit
,
2
,
StringSplitOptions
.
None
);
var
header
=
tmpLine
.
Split
(
new
char
[]
{
':'
},
2
);
args
.
RequestHeaders
.
Add
(
new
HttpHeader
(
header
[
0
],
header
[
1
]));
}
...
...
@@ -175,8 +176,9 @@ namespace Titanium.Web.Proxy
}
}
//construct the web request that we are going to issue on behalf of the client.
args
.
ProxySession
=
new
Http
.
HttpWebSession
();
args
.
ProxySession
.
Request
.
RequestUri
=
httpRemoteUri
;
//args.ProxyRequest.Proxy = null;
...
...
@@ -197,8 +199,8 @@ namespace Titanium.Web.Proxy
//args.RequestIsAlive = args.ProxyRequest.KeepAlive;
//args.ProxyRequest.AllowWriteStreamBuffering = true;
args
.
Client
=
await
TcpConnectionManager
.
GetClient
(
args
.
ProxySession
.
Request
.
RequestUri
.
Host
,
args
.
ProxySession
.
Request
.
RequestUri
.
Port
,
args
.
IsHttps
);
args
.
ProxySession
.
Client
=
args
.
Client
;
//If requested interception
if
(
BeforeRequest
!=
null
)
{
...
...
@@ -215,7 +217,9 @@ namespace Titanium.Web.Proxy
}
SetRequestHeaders
(
args
.
RequestHeaders
,
args
.
ProxySession
);
//construct the web request that we are going to issue on behalf of the client.
var
connection
=
await
TcpConnectionManager
.
GetClient
(
args
.
ProxySession
.
Request
.
RequestUri
.
Host
,
args
.
ProxySession
.
Request
.
RequestUri
.
Port
,
args
.
IsHttps
);
args
.
ProxySession
.
SetConnection
(
connection
);
await
args
.
ProxySession
.
SendRequest
();
//If request was modified by user
...
...
@@ -234,7 +238,7 @@ namespace Titanium.Web.Proxy
}
}
await
HandleHttpSessionResponse
(
args
);
HandleHttpSessionResponse
(
args
);
//if connection is closing exit
if
(
args
.
ResponseHeaders
.
Any
(
x
=>
x
.
Name
.
ToLower
()
==
"connection"
&&
x
.
Value
.
ToLower
()
==
"close"
))
...
...
@@ -243,7 +247,7 @@ namespace Titanium.Web.Proxy
return
;
}
//
TcpConnectionManager.AddClient(args.ProxySession.Request.RequestUri.Host, args.ProxySession.Request.RequestUri.Port, args.IsHttps, args.ProxySession.Client);
TcpConnectionManager
.
AddClient
(
args
.
ProxySession
.
Request
.
RequestUri
.
Host
,
args
.
ProxySession
.
Request
.
RequestUri
.
Port
,
args
.
IsHttps
,
args
.
ProxySession
.
Client
);
// read the next request
httpCmd
=
clientStreamReader
.
ReadLine
();
...
...
@@ -351,10 +355,27 @@ namespace Titanium.Web.Proxy
break
;
}
}
FixRequestProxyHeaders
(
requestHeaders
);
webRequest
.
Request
.
RequestHeaders
=
requestHeaders
;
}
private
static
void
FixRequestProxyHeaders
(
List
<
HttpHeader
>
headers
)
{
//If proxy-connection close was returned inform to close the connection
var
proxyHeader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
var
connectionheader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"connection"
);
if
(
proxyHeader
!=
null
)
if
(
connectionheader
==
null
)
{
headers
.
Add
(
new
HttpHeader
(
"connection"
,
proxyHeader
.
Value
));
}
else
{
connectionheader
.
Value
=
proxyHeader
.
Value
;
}
headers
.
RemoveAll
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
}
//This is called when the request is PUT/POST to read the body
private
static
void
SendClientRequestBody
(
SessionEventArgs
args
)
{
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
f69bed23
using
System
;
using
System.Collections.Generic
;
using
System.Globalization
;
using
System.IO
;
using
System.Linq
;
using
System.Net
;
...
...
@@ -17,7 +18,7 @@ namespace Titanium.Web.Proxy
partial
class
ProxyServer
{
//Called asynchronously when a request was successfully and we received the response
private
static
async
Task
HandleHttpSessionResponse
(
SessionEventArgs
args
)
private
static
void
HandleHttpSessionResponse
(
SessionEventArgs
args
)
{
args
.
ProxySession
.
ReceiveResponse
();
...
...
@@ -63,12 +64,14 @@ namespace Titanium.Web.Proxy
}
else
{
// var isChunked = args.ProxySession
.ResponseHeaders.Any(x => x.Name.ToLower() == "transfer-encoding" && x.Value.ToLower().Contains("chunked"));
var
isChunked
=
args
.
ProxySession
.
Response
.
ResponseHeaders
.
Any
(
x
=>
x
.
Name
.
ToLower
()
==
"transfer-encoding"
&&
x
.
Value
.
ToLower
().
Contains
(
"chunked"
));
WriteResponseStatus
(
args
.
ProxySession
.
Response
.
ResponseProtocolVersion
,
args
.
ProxySession
.
Response
.
ResponseStatusCode
,
args
.
ProxySession
.
Response
.
ResponseStatusDescription
,
args
.
ClientStreamWriter
);
WriteResponseHeaders
(
args
.
ClientStreamWriter
,
args
.
ResponseHeaders
);
WriteResponseBody
(
args
.
ResponseStream
,
args
.
ClientStream
,
false
,
args
.
ProxySession
.
Response
.
ContentLength
);
if
(
isChunked
||
args
.
ProxySession
.
Response
.
ContentLength
>
0
)
WriteResponseBody
(
args
.
ResponseStream
,
args
.
ClientStream
,
isChunked
,
args
.
ProxySession
.
Response
.
ContentLength
);
}
args
.
ClientStream
.
Flush
();
...
...
@@ -90,6 +93,10 @@ namespace Titanium.Web.Proxy
{
switch
(
response
.
Response
.
ResponseHeaders
[
i
].
Name
.
ToLower
())
{
case
"content-length"
:
response
.
Response
.
ContentLength
=
int
.
Parse
(
response
.
Response
.
ResponseHeaders
[
i
].
Value
);
break
;
case
"content-encoding"
:
response
.
Response
.
ResponseContentEncoding
=
response
.
Response
.
ResponseHeaders
[
i
].
Value
;
break
;
...
...
@@ -105,14 +112,10 @@ namespace Titanium.Web.Proxy
break
;
case
"connection"
:
break
;
default
:
break
;
}
}
// response.ResponseHeaders.RemoveAll(x => x.Name.ToLower() == "connection");
return
response
.
Response
.
ResponseHeaders
;
}
...
...
@@ -128,7 +131,7 @@ namespace Titanium.Web.Proxy
{
if
(
headers
!=
null
)
{
//Fix
ProxyHeaders(headers);
FixResponse
ProxyHeaders
(
headers
);
foreach
(
var
header
in
headers
)
{
...
...
@@ -139,23 +142,29 @@ namespace Titanium.Web.Proxy
responseWriter
.
WriteLine
();
responseWriter
.
Flush
();
}
private
static
void
FixProxyHeaders
(
List
<
HttpHeader
>
headers
)
private
static
void
Fix
Response
ProxyHeaders
(
List
<
HttpHeader
>
headers
)
{
//If proxy-connection close was returned inform to close the connection
if
(
headers
.
Any
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
&&
x
.
Value
.
ToLower
()
==
"close"
))
if
(
headers
.
Any
(
x
=>
x
.
Name
.
ToLower
()
==
"connection"
)
==
false
)
var
proxyHeader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
var
connectionHeader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"connection"
);
if
(
proxyHeader
!=
null
)
if
(
connectionHeader
==
null
)
{
headers
.
Add
(
new
HttpHeader
(
"connection"
,
"close"
));
headers
.
RemoveAll
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
headers
.
Add
(
new
HttpHeader
(
"connection"
,
proxyHeader
.
Value
));
}
else
headers
.
Find
(
x
=>
x
.
Name
.
ToLower
()
==
"connection"
).
Value
=
"close"
;
{
connectionHeader
.
Value
=
"close"
;
}
headers
.
RemoveAll
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
}
private
static
void
WriteResponseHeaders
(
StreamWriter
responseWriter
,
List
<
HttpHeader
>
headers
,
int
length
,
bool
isChunked
)
{
FixProxyHeaders
(
headers
);
Fix
Response
ProxyHeaders
(
headers
);
if
(!
isChunked
)
{
...
...
@@ -194,12 +203,27 @@ namespace Titanium.Web.Proxy
{
if
(!
isChunked
)
{
int
bytesToRead
=
BUFFER_SIZE
;
if
(
BodyLength
<
BUFFER_SIZE
)
bytesToRead
=
BodyLength
;
var
buffer
=
new
byte
[
BUFFER_SIZE
];
int
bytesRead
;
while
((
bytesRead
=
inStream
.
Read
(
buffer
,
0
,
buffer
.
Length
))
>
0
)
var
bytesRead
=
0
;
var
totalBytesRead
=
0
;
while
((
bytesRead
+=
inStream
.
Read
(
buffer
,
0
,
bytesToRead
))
>
0
)
{
outStream
.
Write
(
buffer
,
0
,
bytesRead
);
totalBytesRead
+=
bytesRead
;
if
(
totalBytesRead
==
BodyLength
)
break
;
bytesRead
=
0
;
var
remainingBytes
=
(
BodyLength
-
totalBytesRead
);
bytesToRead
=
remainingBytes
>
BUFFER_SIZE
?
BUFFER_SIZE
:
remainingBytes
;
}
}
else
...
...
@@ -209,20 +233,35 @@ namespace Titanium.Web.Proxy
//Send chunked response
private
static
void
WriteResponseBodyChunked
(
Stream
inStream
,
Stream
outStream
)
{
var
buffer
=
new
byte
[
BUFFER_SIZE
];
var
inStreamReader
=
new
CustomBinaryReader
(
inStream
,
Encoding
.
ASCII
);
while
(
true
)
{
var
chuchkHead
=
inStreamReader
.
ReadLine
();
var
chunkSize
=
int
.
Parse
(
chuchkHead
,
NumberStyles
.
HexNumber
);
int
bytesRead
;
while
((
bytesRead
=
inStream
.
Read
(
buffer
,
0
,
buffer
.
Length
))
>
0
)
if
(
chunkSize
!=
0
)
{
var
chunkHead
=
Encoding
.
ASCII
.
GetBytes
(
bytesRead
.
ToString
(
"x2"
));
var
buffer
=
inStreamReader
.
ReadBytes
(
chunkSize
);
var
chunkHead
=
Encoding
.
ASCII
.
GetBytes
(
chunkSize
.
ToString
(
"x2"
));
outStream
.
Write
(
chunkHead
,
0
,
chunkHead
.
Length
);
outStream
.
Write
(
ChunkTrail
,
0
,
ChunkTrail
.
Length
);
outStream
.
Write
(
buffer
,
0
,
bytesRead
);
outStream
.
Write
(
ChunkTrail
,
0
,
ChunkTrail
.
Length
);
}
outStream
.
Write
(
NewLineBytes
,
0
,
NewLineBytes
.
Length
);
outStream
.
Write
(
buffer
,
0
,
chunkSize
);
outStream
.
Write
(
NewLineBytes
,
0
,
NewLineBytes
.
Length
);
inStreamReader
.
ReadLine
();
}
else
{
inStreamReader
.
ReadLine
();
outStream
.
Write
(
ChunkEnd
,
0
,
ChunkEnd
.
Length
);
break
;
}
}
}
private
static
void
WriteResponseBodyChunked
(
byte
[]
data
,
Stream
outStream
)
...
...
@@ -230,9 +269,9 @@ namespace Titanium.Web.Proxy
var
chunkHead
=
Encoding
.
ASCII
.
GetBytes
(
data
.
Length
.
ToString
(
"x2"
));
outStream
.
Write
(
chunkHead
,
0
,
chunkHead
.
Length
);
outStream
.
Write
(
ChunkTrail
,
0
,
ChunkTrail
.
Length
);
outStream
.
Write
(
NewLineBytes
,
0
,
NewLineBytes
.
Length
);
outStream
.
Write
(
data
,
0
,
data
.
Length
);
outStream
.
Write
(
ChunkTrail
,
0
,
ChunkTrail
.
Length
);
outStream
.
Write
(
NewLineBytes
,
0
,
NewLineBytes
.
Length
);
outStream
.
Write
(
ChunkEnd
,
0
,
ChunkEnd
.
Length
);
}
...
...
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