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
2661ae02
Commit
2661ae02
authored
Dec 30, 2017
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Http writer refactored
parent
a6956ee1
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
153 additions
and
148 deletions
+153
-148
HttpRequestWriter.cs
Titanium.Web.Proxy/Helpers/HttpRequestWriter.cs
+1
-2
HttpResponseWriter.cs
Titanium.Web.Proxy/Helpers/HttpResponseWriter.cs
+1
-2
HttpWriter.cs
Titanium.Web.Proxy/Helpers/HttpWriter.cs
+70
-41
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+24
-32
HttpHeader.cs
Titanium.Web.Proxy/Models/HttpHeader.cs
+2
-8
TcpConnection.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
+0
-1
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+12
-15
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+0
-1
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+42
-43
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+0
-2
ProxyConstants.cs
Titanium.Web.Proxy/Shared/ProxyConstants.cs
+1
-1
No files found.
Titanium.Web.Proxy/Helpers/HttpRequestWriter.cs
View file @
2661ae02
...
...
@@ -4,8 +4,7 @@ namespace Titanium.Web.Proxy.Helpers
{
sealed
class
HttpRequestWriter
:
HttpWriter
{
public
HttpRequestWriter
(
Stream
stream
,
int
bufferSize
)
:
base
(
stream
,
bufferSize
,
true
)
public
HttpRequestWriter
(
Stream
stream
,
int
bufferSize
)
:
base
(
stream
,
bufferSize
)
{
}
}
...
...
Titanium.Web.Proxy/Helpers/HttpResponseWriter.cs
View file @
2661ae02
...
...
@@ -7,8 +7,7 @@ namespace Titanium.Web.Proxy.Helpers
{
sealed
class
HttpResponseWriter
:
HttpWriter
{
public
HttpResponseWriter
(
Stream
stream
,
int
bufferSize
)
:
base
(
stream
,
bufferSize
,
true
)
public
HttpResponseWriter
(
Stream
stream
,
int
bufferSize
)
:
base
(
stream
,
bufferSize
)
{
}
...
...
Titanium.Web.Proxy/Helpers/HttpWriter.cs
View file @
2661ae02
using
System.Globalization
;
using
System
;
using
System.Globalization
;
using
System.IO
;
using
System.Text
;
using
System.Threading.Tasks
;
using
StreamExtended.Helpers
;
using
StreamExtended.Network
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Http
;
...
...
@@ -9,31 +11,64 @@ using Titanium.Web.Proxy.Shared;
namespace
Titanium.Web.Proxy.Helpers
{
abstract
class
HttpWriter
:
StreamWriter
abstract
class
HttpWriter
{
protected
HttpWriter
(
Stream
stream
,
int
bufferSize
,
bool
leaveOpen
)
:
base
(
stream
,
Encoding
.
ASCII
,
bufferSize
,
leaveOpen
)
public
int
BufferSize
{
get
;
}
private
readonly
Stream
stream
;
private
readonly
char
[]
charBuffer
;
private
static
readonly
byte
[]
newLine
=
ProxyConstants
.
NewLine
;
private
static
readonly
Encoder
encoder
=
Encoding
.
ASCII
.
GetEncoder
();
protected
HttpWriter
(
Stream
stream
,
int
bufferSize
)
{
NewLine
=
ProxyConstants
.
NewLine
;
BufferSize
=
bufferSize
;
// ASCII encoder max byte count is char count + 1
charBuffer
=
new
char
[
BufferSize
-
1
];
this
.
stream
=
stream
;
}
public
void
WriteHeaders
(
HeaderCollection
headers
,
bool
flush
=
true
)
public
Task
WriteLineAsync
(
)
{
if
(
headers
!=
null
)
return
WriteAsync
(
newLine
);
}
public
async
Task
WriteAsync
(
string
value
)
{
int
charCount
=
value
.
Length
;
value
.
CopyTo
(
0
,
charBuffer
,
0
,
charCount
);
if
(
charCount
<
BufferSize
)
{
foreach
(
var
header
in
headers
)
var
buffer
=
BufferPool
.
GetBuffer
(
BufferSize
);
try
{
header
.
WriteToStream
(
this
);
int
idx
=
encoder
.
GetBytes
(
charBuffer
,
0
,
charCount
,
buffer
,
0
,
true
);
await
WriteAsync
(
buffer
,
0
,
idx
);
}
finally
{
BufferPool
.
ReturnBuffer
(
buffer
);
}
}
WriteLine
();
if
(
flush
)
else
{
Flush
();
var
buffer
=
new
byte
[
charCount
+
1
];
int
idx
=
encoder
.
GetBytes
(
charBuffer
,
0
,
charCount
,
buffer
,
0
,
true
);
await
WriteAsync
(
buffer
,
0
,
idx
);
}
}
public
async
Task
WriteLineAsync
(
string
value
)
{
await
WriteAsync
(
value
);
await
WriteLineAsync
();
}
/// <summary>
/// Write the headers to client
/// </summary>
...
...
@@ -53,29 +88,28 @@ namespace Titanium.Web.Proxy.Helpers
await
WriteLineAsync
();
if
(
flush
)
{
await
FlushAsync
();
// flush the stream
await
stream
.
FlushAsync
();
}
}
public
async
Task
WriteAsync
(
byte
[]
data
,
bool
flush
=
false
)
{
await
FlushAsync
();
await
BaseStream
.
WriteAsync
(
data
,
0
,
data
.
Length
);
await
stream
.
WriteAsync
(
data
,
0
,
data
.
Length
);
if
(
flush
)
{
// flush the stream
and the encoder, too
await
FlushAsync
();
// flush the stream
await
stream
.
FlushAsync
();
}
}
public
async
Task
WriteAsync
(
byte
[]
data
,
int
offset
,
int
count
,
bool
flush
=
false
)
{
await
FlushAsync
();
await
BaseStream
.
WriteAsync
(
data
,
offset
,
count
);
await
stream
.
WriteAsync
(
data
,
offset
,
count
);
if
(
flush
)
{
// flush the stream
and the encoder, too
await
FlushAsync
();
// flush the stream
await
stream
.
FlushAsync
();
}
}
...
...
@@ -85,16 +119,14 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="data"></param>
/// <param name="isChunked"></param>
/// <returns></returns>
internal
async
Task
WriteBodyAsync
(
byte
[]
data
,
bool
isChunked
)
internal
Task
WriteBodyAsync
(
byte
[]
data
,
bool
isChunked
)
{
if
(
isChunked
)
{
await
WriteBodyChunkedAsync
(
data
);
}
else
{
await
WriteAsync
(
data
);
return
WriteBodyChunkedAsync
(
data
);
}
return
WriteAsync
(
data
);
}
/// <summary>
...
...
@@ -105,24 +137,22 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="isChunked"></param>
/// <param name="contentLength"></param>
/// <returns></returns>
internal
async
Task
CopyBodyAsync
(
CustomBinaryReader
streamReader
,
bool
isChunked
,
long
contentLength
)
internal
Task
CopyBodyAsync
(
CustomBinaryReader
streamReader
,
bool
isChunked
,
long
contentLength
)
{
if
(
isChunked
)
{
//Need to revist, find any potential bugs
//send the body bytes to server in chunks
await
CopyBodyChunkedAsync
(
streamReader
);
return
CopyBodyChunkedAsync
(
streamReader
);
}
else
//http 1.0
if
(
contentLength
==
-
1
)
{
//http 1.0
if
(
contentLength
==
-
1
)
{
contentLength
=
long
.
MaxValue
;
}
await
CopyBytesFromStream
(
streamReader
,
contentLength
);
contentLength
=
long
.
MaxValue
;
}
return
CopyBytesFromStream
(
streamReader
,
contentLength
);
}
/// <summary>
...
...
@@ -175,10 +205,9 @@ namespace Titanium.Web.Proxy.Helpers
}
}
private
async
Task
CopyBytesFromStream
(
CustomBinaryReader
reader
,
long
count
)
private
Task
CopyBytesFromStream
(
CustomBinaryReader
reader
,
long
count
)
{
await
FlushAsync
();
await
reader
.
CopyBytesToStream
(
BaseStream
,
count
);
return
reader
.
CopyBytesToStream
(
stream
,
count
);
}
}
}
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
2661ae02
...
...
@@ -74,53 +74,45 @@ namespace Titanium.Web.Proxy.Http
connection
.
LastAccess
=
DateTime
.
Now
;
ServerConnection
=
connection
;
}
/// <summary>
/// Prepare and send the http(s) request
/// </summary>
/// <returns></returns>
internal
async
Task
SendRequest
(
bool
enable100ContinueBehaviour
)
{
byte
[]
requestBytes
;
using
(
var
ms
=
new
MemoryStream
())
using
(
var
writer
=
new
HttpRequestWriter
(
ms
,
bufferSize
))
{
var
upstreamProxy
=
ServerConnection
.
UpStreamProxy
;
var
upstreamProxy
=
ServerConnection
.
UpStreamProxy
;
bool
useUpstreamProxy
=
upstreamProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
;
bool
useUpstreamProxy
=
upstreamProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
;
//prepare the request & headers
writer
.
WriteLine
(
Request
.
CreateRequestLine
(
Request
.
Method
,
useUpstreamProxy
?
Request
.
OriginalUrl
:
Request
.
RequestUri
.
PathAndQuery
,
Request
.
HttpVersion
));
var
writer
=
ServerConnection
.
StreamWriter
;
//prepare the request & headers
await
writer
.
WriteLineAsync
(
Request
.
CreateRequestLine
(
Request
.
Method
,
useUpstreamProxy
?
Request
.
OriginalUrl
:
Request
.
RequestUri
.
PathAndQuery
,
Request
.
HttpVersion
));
//Send Authentication to Upstream proxy if needed
if
(
upstreamProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
upstreamProxy
.
UserName
)
&&
upstreamProxy
.
Password
!=
null
)
{
HttpHeader
.
ProxyConnectionKeepAlive
.
WriteToStream
(
writer
);
HttpHeader
.
GetProxyAuthorizationHeader
(
upstreamProxy
.
UserName
,
upstreamProxy
.
Password
).
WriteToStream
(
writer
);
}
//write request headers
foreach
(
var
header
in
Request
.
Headers
)
//Send Authentication to Upstream proxy if needed
if
(
upstreamProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
upstreamProxy
.
UserName
)
&&
upstreamProxy
.
Password
!=
null
)
{
await
HttpHeader
.
ProxyConnectionKeepAlive
.
WriteToStreamAsync
(
writer
);
await
HttpHeader
.
GetProxyAuthorizationHeader
(
upstreamProxy
.
UserName
,
upstreamProxy
.
Password
).
WriteToStreamAsync
(
writer
);
}
//write request headers
foreach
(
var
header
in
Request
.
Headers
)
{
if
(
header
.
Name
!=
"Proxy-Authorization"
)
{
if
(
header
.
Name
!=
"Proxy-Authorization"
)
{
header
.
WriteToStream
(
writer
);
}
await
header
.
WriteToStreamAsync
(
writer
);
}
writer
.
WriteLine
();
writer
.
Flush
();
requestBytes
=
ms
.
ToArray
();
}
await
ServerConnection
.
StreamWriter
.
WriteAsync
(
requestBytes
,
true
);
await
writer
.
WriteLineAsync
(
);
if
(
enable100ContinueBehaviour
)
{
...
...
Titanium.Web.Proxy/Models/HttpHeader.cs
View file @
2661ae02
...
...
@@ -2,6 +2,7 @@
using
System.IO
;
using
System.Text
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Helpers
;
namespace
Titanium.Web.Proxy.Models
{
...
...
@@ -61,14 +62,7 @@ namespace Titanium.Web.Proxy.Models
return
result
;
}
internal
void
WriteToStream
(
StreamWriter
writer
)
{
writer
.
Write
(
Name
);
writer
.
Write
(
": "
);
writer
.
WriteLine
(
Value
);
}
internal
async
Task
WriteToStreamAsync
(
StreamWriter
writer
)
internal
async
Task
WriteToStreamAsync
(
HttpWriter
writer
)
{
await
writer
.
WriteAsync
(
Name
);
await
writer
.
WriteAsync
(
": "
);
...
...
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
View file @
2661ae02
...
...
@@ -65,7 +65,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
public
void
Dispose
()
{
StreamReader
?.
Dispose
();
StreamWriter
?.
Dispose
();
Stream
?.
Dispose
();
...
...
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
2661ae02
...
...
@@ -68,24 +68,21 @@ namespace Titanium.Web.Proxy.Network.Tcp
if
(
useUpstreamProxy
&&
(
isConnect
||
isHttps
))
{
using
(
var
writer
=
new
HttpRequestWriter
(
stream
,
server
.
BufferSize
))
{
await
writer
.
WriteLineAsync
(
$"CONNECT
{
remoteHostName
}
:
{
remotePort
}
HTTP/
{
httpVersion
}
"
);
await
writer
.
WriteLineAsync
(
$"Host:
{
remoteHostName
}
:
{
remotePort
}
"
);
await
writer
.
WriteLineAsync
(
"Connection: Keep-Alive"
);
if
(!
string
.
IsNullOrEmpty
(
externalProxy
.
UserName
)
&&
externalProxy
.
Password
!=
null
)
{
await
HttpHeader
.
ProxyConnectionKeepAlive
.
WriteToStreamAsync
(
writer
);
await
writer
.
WriteLineAsync
(
"Proxy-Authorization"
+
": Basic "
+
Convert
.
ToBase64String
(
Encoding
.
UTF8
.
GetBytes
(
externalProxy
.
UserName
+
":"
+
externalProxy
.
Password
)));
}
var
writer
=
new
HttpRequestWriter
(
stream
,
server
.
BufferSize
);
await
writer
.
WriteLineAsync
(
$"CONNECT
{
remoteHostName
}
:
{
remotePort
}
HTTP/
{
httpVersion
}
"
);
await
writer
.
WriteLineAsync
(
$"Host:
{
remoteHostName
}
:
{
remotePort
}
"
);
await
writer
.
WriteLineAsync
(
"Connection: Keep-Alive"
);
await
writer
.
WriteLineAsync
();
await
writer
.
FlushAsync
();
if
(!
string
.
IsNullOrEmpty
(
externalProxy
.
UserName
)
&&
externalProxy
.
Password
!=
null
)
{
await
HttpHeader
.
ProxyConnectionKeepAlive
.
WriteToStreamAsync
(
writer
);
await
writer
.
WriteLineAsync
(
"Proxy-Authorization"
+
": Basic "
+
Convert
.
ToBase64String
(
Encoding
.
UTF8
.
GetBytes
(
externalProxy
.
UserName
+
":"
+
externalProxy
.
Password
)));
}
await
writer
.
WriteLineAsync
();
using
(
var
reader
=
new
CustomBinaryReader
(
stream
,
server
.
BufferSize
))
{
string
result
=
await
reader
.
ReadLineAsync
();
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
2661ae02
...
...
@@ -613,7 +613,6 @@ namespace Titanium.Web.Proxy
private
void
Dispose
(
CustomBufferedStream
clientStream
,
CustomBinaryReader
clientStreamReader
,
HttpResponseWriter
clientStreamWriter
,
TcpConnection
serverConnection
)
{
clientStreamReader
?.
Dispose
();
clientStreamWriter
?.
Dispose
();
clientStream
?.
Dispose
();
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
2661ae02
...
...
@@ -378,16 +378,8 @@ namespace Titanium.Web.Proxy
{
//prepare the prefix content
var
requestHeaders
=
args
.
WebSession
.
Request
.
Headers
;
byte
[]
requestBytes
;
using
(
var
ms
=
new
MemoryStream
())
using
(
var
writer
=
new
HttpRequestWriter
(
ms
,
BufferSize
))
{
writer
.
WriteLine
(
httpCmd
);
writer
.
WriteHeaders
(
requestHeaders
);
requestBytes
=
ms
.
ToArray
();
}
await
connection
.
StreamWriter
.
WriteAsync
(
requestBytes
);
await
connection
.
StreamWriter
.
WriteLineAsync
(
httpCmd
);
await
connection
.
StreamWriter
.
WriteHeadersAsync
(
requestHeaders
);
string
httpStatus
=
await
connection
.
StreamReader
.
ReadLineAsync
();
Response
.
ParseResponseLine
(
httpStatus
,
out
var
responseVersion
,
out
int
responseStatusCode
,
out
string
responseStatusDescription
);
...
...
@@ -670,57 +662,64 @@ namespace Titanium.Web.Proxy
// try to use the thread static buffer
var
buffer
=
BufferPool
.
GetBuffer
(
BufferSize
);
int
boundaryLength
=
boundary
.
Length
+
4
;
long
bytesRead
=
0
;
while
(
bytesRead
<
totalBytesToRead
&&
(
inputStream
.
DataAvailable
||
await
inputStream
.
FillBufferAsync
()))
try
{
byte
newChar
=
inputStream
.
ReadByteFromBuffer
();
buffer
[
bufferDataLength
]
=
newChar
;
bufferDataLength
++;
bytesRead
++;
int
boundaryLength
=
boundary
.
Length
+
4
;
long
bytesRead
=
0
;
if
(
bufferDataLength
>=
boundaryLength
)
while
(
bytesRead
<
totalBytesToRead
&&
(
inputStream
.
DataAvailable
||
await
inputStream
.
FillBufferAsync
())
)
{
int
startIdx
=
bufferDataLength
-
boundaryLength
;
if
(
buffer
[
startIdx
]
==
'-'
&&
buffer
[
startIdx
+
1
]
==
'-'
&&
buffer
[
bufferDataLength
-
2
]
==
'\r'
&&
buffer
[
bufferDataLength
-
1
]
==
'\n'
)
byte
newChar
=
inputStream
.
ReadByteFromBuffer
();
buffer
[
bufferDataLength
]
=
newChar
;
bufferDataLength
++;
bytesRead
++;
if
(
bufferDataLength
>=
boundaryLength
)
{
startIdx
+=
2
;
bool
ok
=
true
;
for
(
int
i
=
0
;
i
<
boundary
.
Length
;
i
++
)
int
startIdx
=
bufferDataLength
-
boundaryLength
;
if
(
buffer
[
startIdx
]
==
'-'
&&
buffer
[
startIdx
+
1
]
==
'-'
&&
buffer
[
bufferDataLength
-
2
]
==
'\r'
&&
buffer
[
bufferDataLength
-
1
]
==
'\n'
)
{
if
(
buffer
[
startIdx
+
i
]
!=
boundary
[
i
])
startIdx
+=
2
;
bool
ok
=
true
;
for
(
int
i
=
0
;
i
<
boundary
.
Length
;
i
++)
{
if
(
buffer
[
startIdx
+
i
]
!=
boundary
[
i
])
{
ok
=
false
;
break
;
}
}
if
(
ok
)
{
ok
=
false
;
break
;
}
}
}
if
(
ok
)
{
break
;
}
if
(
bufferDataLength
==
buffer
.
Length
)
{
//boundary is not longer than 70 bytes according to the specification, so keeping the last 100 (minimum 74) bytes is enough
const
int
bytesToKeep
=
100
;
await
outputStream
.
WriteAsync
(
buffer
,
0
,
buffer
.
Length
-
bytesToKeep
);
Buffer
.
BlockCopy
(
buffer
,
buffer
.
Length
-
bytesToKeep
,
buffer
,
0
,
bytesToKeep
);
bufferDataLength
=
bytesToKeep
;
}
}
if
(
b
ufferDataLength
==
buffer
.
Length
)
if
(
b
ytesRead
>
0
)
{
//boundary is not longer than 70 bytes according to the specification, so keeping the last 100 (minimum 74) bytes is enough
const
int
bytesToKeep
=
100
;
await
outputStream
.
WriteAsync
(
buffer
,
0
,
buffer
.
Length
-
bytesToKeep
);
Buffer
.
BlockCopy
(
buffer
,
buffer
.
Length
-
bytesToKeep
,
buffer
,
0
,
bytesToKeep
);
bufferDataLength
=
bytesToKeep
;
await
outputStream
.
WriteAsync
(
buffer
,
0
,
bufferDataLength
);
}
}
if
(
bytesRead
>
0
)
return
bytesRead
;
}
finally
{
await
outputStream
.
WriteAsync
(
buffer
,
0
,
bufferDataLength
);
BufferPool
.
ReturnBuffer
(
buffer
);
}
return
bytesRead
;
}
}
}
Titanium.Web.Proxy/ResponseHandler.cs
View file @
2661ae02
...
...
@@ -109,8 +109,6 @@ namespace Titanium.Web.Proxy
response
.
IsChunked
,
response
.
ContentLength
);
}
}
await
clientStreamWriter
.
FlushAsync
();
}
catch
(
Exception
e
)
{
...
...
Titanium.Web.Proxy/Shared/ProxyConstants.cs
View file @
2661ae02
...
...
@@ -14,6 +14,6 @@ namespace Titanium.Web.Proxy.Shared
internal
static
readonly
char
[]
SemiColonSplit
=
{
';'
};
internal
static
readonly
char
[]
EqualSplit
=
{
'='
};
internal
const
string
NewLine
=
"\r\n"
;
internal
static
readonly
byte
[]
NewLine
=
{(
byte
)
'\r'
,
(
byte
)
'\n'
}
;
}
}
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