Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

Commit a9c2924

Browse files
committed
content length limit fix
1 parent 72cd50d commit a9c2924

File tree

7 files changed

+57
-100
lines changed

7 files changed

+57
-100
lines changed

Titanium.Web.Proxy/Compression/CompressionFactory.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,11 @@ namespace Titanium.Web.Proxy.Compression
66
/// <summary>
77
/// A factory to generate the compression methods based on the type of compression
88
/// </summary>
9-
internal class CompressionFactory
9+
internal static class CompressionFactory
1010
{
11-
public static readonly CompressionFactory Instance = new CompressionFactory();
12-
1311
//cache
1412
private static readonly Lazy<ICompression> gzip = new Lazy<ICompression>(() => new GZipCompression());
1513
private static readonly Lazy<ICompression> deflate = new Lazy<ICompression>(() => new DeflateCompression());
16-
private static readonly Lazy<ICompression> def = new Lazy<ICompression>(() => new DefaultCompression());
1714

1815
public static ICompression GetCompression(string type)
1916
{
@@ -24,7 +21,7 @@ public static ICompression GetCompression(string type)
2421
case KnownHeaders.ContentEncodingDeflate:
2522
return deflate.Value;
2623
default:
27-
return def.Value;
24+
throw new Exception($"Unsupported compression mode: {type}");
2825
}
2926
}
3027
}

Titanium.Web.Proxy/Compression/DefaultCompression.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.

Titanium.Web.Proxy/Decompression/DecompressionFactory.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,11 @@ namespace Titanium.Web.Proxy.Decompression
88
/// </summary>
99
internal class DecompressionFactory
1010
{
11-
public static readonly DecompressionFactory Instance = new DecompressionFactory();
12-
1311
//cache
1412
private static readonly Lazy<IDecompression> gzip = new Lazy<IDecompression>(() => new GZipDecompression());
1513
private static readonly Lazy<IDecompression> deflate = new Lazy<IDecompression>(() => new DeflateDecompression());
16-
private static readonly Lazy<IDecompression> def = new Lazy<IDecompression>(() => new DefaultDecompression());
1714

18-
internal IDecompression Create(string type)
15+
public static IDecompression Create(string type)
1916
{
2017
switch (type)
2118
{
@@ -24,7 +21,7 @@ internal IDecompression Create(string type)
2421
case KnownHeaders.ContentEncodingDeflate:
2522
return deflate.Value;
2623
default:
27-
return def.Value;
24+
throw new Exception($"Unsupported decompression mode: {type}");
2825
}
2926
}
3027
}

Titanium.Web.Proxy/Decompression/DefaultDecompression.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.

Titanium.Web.Proxy/EventArguments/ChunkedStream.cs renamed to Titanium.Web.Proxy/EventArguments/LimitedStream.cs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,21 @@
88

99
namespace Titanium.Web.Proxy.EventArguments
1010
{
11-
internal class ChunkedStream : Stream
11+
internal class LimitedStream : Stream
1212
{
1313
private readonly CustomBufferedStream baseStream;
1414
private readonly CustomBinaryReader baseReader;
15+
private readonly bool isChunked;
1516

1617
private bool readChunkTrail;
17-
private int chunkBytesRemaining;
18+
private long bytesRemaining;
1819

19-
public ChunkedStream(CustomBufferedStream baseStream, CustomBinaryReader baseReader)
20+
public LimitedStream(CustomBufferedStream baseStream, CustomBinaryReader baseReader, bool isChunked, long contentLength)
2021
{
2122
this.baseStream = baseStream;
2223
this.baseReader = baseReader;
24+
this.isChunked = isChunked;
25+
bytesRemaining = isChunked ? 0 : contentLength;
2326
}
2427

2528
private void GetNextChunk()
@@ -41,11 +44,11 @@ private void GetNextChunk()
4144
}
4245

4346
int chunkSize = int.Parse(chunkHead, NumberStyles.HexNumber);
44-
chunkBytesRemaining = chunkSize;
47+
bytesRemaining = chunkSize;
4548

4649
if (chunkSize == 0)
4750
{
48-
chunkBytesRemaining = -1;
51+
bytesRemaining = -1;
4952

5053
//chunk trail
5154
string s = baseReader.ReadLineAsync().Result;
@@ -69,24 +72,31 @@ public override void SetLength(long value)
6972

7073
public override int Read(byte[] buffer, int offset, int count)
7174
{
72-
if (chunkBytesRemaining == -1)
75+
if (bytesRemaining == -1)
7376
{
7477
return 0;
7578
}
7679

77-
if (chunkBytesRemaining == 0)
80+
if (bytesRemaining == 0)
7881
{
79-
GetNextChunk();
82+
if (isChunked)
83+
{
84+
GetNextChunk();
85+
}
86+
else
87+
{
88+
bytesRemaining = -1;
89+
}
8090
}
8191

82-
if (chunkBytesRemaining == -1)
92+
if (bytesRemaining == -1)
8393
{
8494
return 0;
8595
}
8696

87-
int toRead = Math.Min(count, chunkBytesRemaining);
97+
int toRead = (int)Math.Min(count, bytesRemaining);
8898
int res = baseStream.Read(buffer, offset, toRead);
89-
chunkBytesRemaining -= res;
99+
bytesRemaining -= res;
90100

91101
return res;
92102
}
@@ -96,7 +106,7 @@ public async Task Finish()
96106
var buffer = BufferPool.GetBuffer(baseReader.Buffer.Length);
97107
try
98108
{
99-
while (chunkBytesRemaining != -1)
109+
while (bytesRemaining != -1)
100110
{
101111
await ReadAsync(buffer, 0, buffer.Length);
102112
}

Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -294,73 +294,58 @@ internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode t
294294
}
295295
else
296296
{
297-
await CopyBodyAsync(ProxyClient.ClientStream, reader, writer,
298-
request.IsChunked, transformation, request.ContentEncoding, contentLength, OnDataSent);
297+
await CopyBodyAsync(ProxyClient.ClientStream, reader, writer, request, transformation, OnDataSent);
299298
}
300299
}
301300

302-
private async Task CopyBodyAsync(CustomBufferedStream stream, CustomBinaryReader reader, HttpWriter writer,
303-
bool isChunked, TransformationMode transformation, string contentEncoding, long contentLength,
304-
Action<byte[], int, int> onCopy)
301+
internal async Task CopyResponseBodyAsync(HttpWriter writer, TransformationMode transformation)
305302
{
306-
bool newReader = false;
303+
var response = WebSession.Response;
304+
var reader = WebSession.ServerConnection.StreamReader;
307305

308-
Stream s = stream;
309-
ChunkedStream chunkedStream = null;
310-
Stream decompressStream = null;
306+
await CopyBodyAsync(WebSession.ServerConnection.Stream, reader, writer, response, transformation, OnDataReceived);
307+
}
311308

312-
if (isChunked && transformation != TransformationMode.None)
309+
private async Task CopyBodyAsync(CustomBufferedStream stream, CustomBinaryReader reader, HttpWriter writer,
310+
RequestResponseBase requestResponse, TransformationMode transformation, Action<byte[], int, int> onCopy)
311+
{
312+
bool isChunked = requestResponse.IsChunked;
313+
long contentLength = requestResponse.ContentLength;
314+
if (transformation == TransformationMode.None)
313315
{
314-
s = chunkedStream = new ChunkedStream(stream, reader);
315-
isChunked = false;
316-
newReader = true;
316+
await writer.CopyBodyAsync(reader, isChunked, contentLength, onCopy);
317+
return;
317318
}
318319

319-
if (transformation == TransformationMode.Uncompress)
320+
LimitedStream limitedStream;
321+
Stream decompressStream = null;
322+
323+
string contentEncoding = requestResponse.ContentEncoding;
324+
325+
Stream s = limitedStream = new LimitedStream(stream, reader, isChunked, contentLength);
326+
327+
if (transformation == TransformationMode.Uncompress && contentEncoding != null)
320328
{
321-
s = decompressStream = DecompressionFactory.Instance.Create(contentEncoding).GetStream(s);
322-
newReader = true;
329+
s = decompressStream = DecompressionFactory.Create(contentEncoding).GetStream(s);
323330
}
324331

325332
try
326333
{
327-
if (newReader)
328-
{
329-
var bufStream = new CustomBufferedStream(s, bufferSize, true);
330-
s = bufStream;
331-
reader = new CustomBinaryReader(bufStream, bufferSize);
332-
}
334+
var bufStream = new CustomBufferedStream(s, bufferSize, true);
335+
reader = new CustomBinaryReader(bufStream, bufferSize);
333336

334-
await writer.CopyBodyAsync(reader, isChunked, contentLength, onCopy);
337+
await writer.CopyBodyAsync(reader, false, -1, onCopy);
335338
}
336339
finally
337340
{
338-
if (newReader)
339-
{
340-
reader?.Dispose();
341-
if (decompressStream != null && decompressStream != stream)
342-
{
343-
decompressStream.Dispose();
344-
}
341+
reader?.Dispose();
342+
decompressStream?.Dispose();
345343

346-
if (chunkedStream != null)
347-
{
348-
await chunkedStream.Finish();
349-
chunkedStream.Dispose();
350-
}
351-
}
344+
await limitedStream.Finish();
345+
limitedStream.Dispose();
352346
}
353347
}
354348

355-
internal async Task CopyResponseBodyAsync(HttpWriter writer, TransformationMode transformation)
356-
{
357-
var response = WebSession.Response;
358-
var reader = WebSession.ServerConnection.StreamReader;
359-
360-
await CopyBodyAsync(WebSession.ServerConnection.Stream, reader, writer,
361-
response.IsChunked, transformation, response.ContentEncoding, response.ContentLength, OnDataReceived);
362-
}
363-
364349
/// <summary>
365350
/// Read a line from the byte stream
366351
/// </summary>

Titanium.Web.Proxy/Helpers/HttpWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ internal Task CopyBodyAsync(CustomBinaryReader streamReader, bool isChunked, lon
165165
return CopyBodyChunkedAsync(streamReader, onCopy);
166166
}
167167

168-
//http 1.0
168+
//http 1.0 or the stream reader limits the stream
169169
if (contentLength == -1)
170170
{
171171
contentLength = long.MaxValue;

0 commit comments

Comments
 (0)