Skip to content

Commit 32b65dc

Browse files
committed
Merge branch 'feature/handle_empty_forms' into develop
Resolves #33
2 parents 6fefa11 + 7407787 commit 32b65dc

2 files changed

Lines changed: 110 additions & 7 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System.IO;
2+
using System.Linq;
3+
using System.Text;
4+
using System.Threading.Tasks;
5+
using Xunit;
6+
7+
namespace HttpMultipartParser.UnitTests.ParserScenarios
8+
{
9+
public class EmptyForm
10+
{
11+
private static readonly string _testData = TestUtil.TrimAllLines(
12+
@"------WebKitFormBoundaryb4SfPlH9Bv7c2PKS--"
13+
);
14+
15+
private static readonly TestData _testCase = new TestData(
16+
_testData,
17+
Enumerable.Empty<ParameterPart>().ToList(),
18+
Enumerable.Empty<FilePart>().ToList()
19+
);
20+
21+
public EmptyForm()
22+
{
23+
foreach (var filePart in _testCase.ExpectedFileData)
24+
{
25+
filePart.Data.Position = 0;
26+
}
27+
}
28+
29+
[Fact]
30+
public void Parse_empty_form_boundary_specified()
31+
{
32+
using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
33+
{
34+
var parser = MultipartFormDataParser.Parse(stream, "----WebKitFormBoundaryb4SfPlH9Bv7c2PKS");
35+
Assert.True(_testCase.Validate(parser));
36+
}
37+
}
38+
39+
[Fact]
40+
public void Parse_empty_form_boundary_omitted()
41+
{
42+
using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
43+
{
44+
var parser = MultipartFormDataParser.Parse(stream);
45+
Assert.True(_testCase.Validate(parser));
46+
}
47+
}
48+
49+
[Fact]
50+
public async Task Parse_empty_form_boundary_specified_async()
51+
{
52+
using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
53+
{
54+
var parser = await MultipartFormDataParser.ParseAsync(stream, "----WebKitFormBoundaryb4SfPlH9Bv7c2PKS").ConfigureAwait(false);
55+
Assert.True(_testCase.Validate(parser));
56+
}
57+
}
58+
59+
[Fact]
60+
public async Task Parse_empty_form_boundary_omitted_async()
61+
{
62+
using (Stream stream = TestUtil.StringToStream(_testCase.Request, Encoding.UTF8))
63+
{
64+
var parser = await MultipartFormDataParser.ParseAsync(stream).ConfigureAwait(false);
65+
Assert.True(_testCase.Validate(parser));
66+
}
67+
}
68+
}
69+
}

Source/HttpMultipartParser/StreamingMultipartFormDataParser.cs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,19 @@ private static string DetectBoundary(RebufferableBinaryReader reader)
351351
// Presumably the boundary is --|||||||||||||| where -- is the stuff added on to
352352
// the front as per the protocol and ||||||||||||| is the part we care about.
353353
string boundary = string.Concat(reader.ReadLine().Skip(2));
354-
reader.Buffer("--" + boundary + "\n");
354+
355+
// If the string ends with '--' it means that we found the "end" boundary and we
356+
// need to trim the two dashes to get the actual boundary
357+
if (boundary.EndsWith("--"))
358+
{
359+
boundary = boundary.Substring(0, boundary.Length - 2);
360+
reader.Buffer($"--{boundary}--\n");
361+
}
362+
else
363+
{
364+
reader.Buffer($"--{boundary}\n");
365+
}
366+
355367
return boundary;
356368
}
357369

@@ -374,8 +386,20 @@ private static async Task<string> DetectBoundaryAsync(RebufferableBinaryReader r
374386
// Presumably the boundary is --|||||||||||||| where -- is the stuff added on to
375387
// the front as per the protocol and ||||||||||||| is the part we care about.
376388
var line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
377-
var boundary = string.Concat(line.Skip(2));
378-
reader.Buffer("--" + boundary + "\n");
389+
string boundary = string.Concat(line.Skip(2));
390+
391+
// If the string ends with '--' it means that we found the "end" boundary and we
392+
// need to trim the two dashes to get the actual boundary.
393+
if (boundary.EndsWith("--"))
394+
{
395+
boundary = boundary.Substring(0, boundary.Length - 2);
396+
reader.Buffer($"--{boundary}--\n");
397+
}
398+
else
399+
{
400+
reader.Buffer($"--{boundary}\n");
401+
}
402+
379403
return boundary;
380404
}
381405

@@ -470,12 +494,17 @@ private void Parse(RebufferableBinaryReader reader)
470494
while (true)
471495
{
472496
string line = reader.ReadLine();
497+
473498
if (line == boundary)
474499
{
475500
break;
476501
}
477-
478-
if (line == null)
502+
else if (line == endBoundary)
503+
{
504+
readEndBoundary = true;
505+
break;
506+
}
507+
else if (line == null)
479508
{
480509
throw new MultipartParseException("Could not find expected boundary");
481510
}
@@ -518,12 +547,17 @@ private async Task ParseAsync(RebufferableBinaryReader reader, CancellationToken
518547
while (true)
519548
{
520549
string line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
550+
521551
if (line == boundary)
522552
{
523553
break;
524554
}
525-
526-
if (line == null)
555+
else if (line == endBoundary)
556+
{
557+
readEndBoundary = true;
558+
break;
559+
}
560+
else if (line == null)
527561
{
528562
throw new MultipartParseException("Could not find expected boundary");
529563
}

0 commit comments

Comments
 (0)