Skip to content

Commit

Permalink
#580 CapturedMultipartContent shouldn't lose parts when sent
Browse files Browse the repository at this point in the history
  • Loading branch information
tmenier committed Dec 14, 2020
1 parent b5716f3 commit 7eaa57a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 12 deletions.
35 changes: 24 additions & 11 deletions Test/Flurl.Test/Http/MultipartTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Flurl.Http;
using Flurl.Http.Content;
using Flurl.Http.Testing;
using NUnit.Framework;

namespace Flurl.Test.Http
{
[TestFixture, Parallelizable]
public class MultipartTests
{
[Test]
public void can_build_multipart_content() {
[Test]
public async Task can_build_and_send_multipart_content() {
var content = new CapturedMultipartContent()
.AddString("string", "foo")
.AddString("string2", "bar", "text/blah")
Expand All @@ -24,15 +26,26 @@ public void can_build_multipart_content() {
.AddJson("json", new { foo = "bar" })
.AddUrlEncoded("urlEnc", new { fizz = "buzz" });

Assert.AreEqual(8, content.Parts.Length);
AssertStringPart<CapturedStringContent>(content.Parts[0], "string", "foo", null);
AssertStringPart<CapturedStringContent>(content.Parts[1], "string2", "bar", "text/blah");
AssertStringPart<CapturedStringContent>(content.Parts[2], "part1", "1", null);
AssertStringPart<CapturedStringContent>(content.Parts[3], "part2", "2", null);
AssertFilePart(content.Parts[4], "file1", "image1.jpg", "image/jpeg");
AssertFilePart(content.Parts[5], "file2", "new-name.jpg", "image/jpeg");
AssertStringPart<CapturedJsonContent>(content.Parts[6], "json", "{\"foo\":\"bar\"}", "application/json; charset=UTF-8");
AssertStringPart<CapturedUrlEncodedContent>(content.Parts[7], "urlEnc", "fizz=buzz", "application/x-www-form-urlencoded");
void AssertAll() {
Assert.AreEqual(8, content.Parts.Count);
AssertStringPart<CapturedStringContent>(content.Parts[0], "string", "foo", null);
AssertStringPart<CapturedStringContent>(content.Parts[1], "string2", "bar", "text/blah");
AssertStringPart<CapturedStringContent>(content.Parts[2], "part1", "1", null);
AssertStringPart<CapturedStringContent>(content.Parts[3], "part2", "2", null);
AssertFilePart(content.Parts[4], "file1", "image1.jpg", "image/jpeg");
AssertFilePart(content.Parts[5], "file2", "new-name.jpg", "image/jpeg");
AssertStringPart<CapturedJsonContent>(content.Parts[6], "json", "{\"foo\":\"bar\"}", "application/json; charset=UTF-8");
AssertStringPart<CapturedUrlEncodedContent>(content.Parts[7], "urlEnc", "fizz=buzz", "application/x-www-form-urlencoded");
}

// Assert before and after sending a request. MultipartContent clears the parts collection after request is sent;
// CapturedMultipartContent (as the name implies) should preserve it (#580)

AssertAll();
using (var test = new HttpTest()) {
await "https://upload.com".PostAsync(content);
}
AssertAll();
}

private void AssertStringPart<TContent>(HttpContent part, string name, string content, string contentType) {
Expand Down
7 changes: 6 additions & 1 deletion src/Flurl.Http/Content/CapturedMultipartContent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
Expand All @@ -15,11 +16,12 @@ namespace Flurl.Http.Content
public class CapturedMultipartContent : MultipartContent
{
private readonly FlurlHttpSettings _settings;
private readonly List<HttpContent> _capturedParts = new List<HttpContent>();

/// <summary>
/// Gets an array of HttpContent objects that make up the parts of the multipart request.
/// </summary>
public HttpContent[] Parts => this.ToArray();
public IReadOnlyList<HttpContent> Parts => _capturedParts;

/// <summary>
/// Initializes a new instance of the <see cref="CapturedMultipartContent"/> class.
Expand Down Expand Up @@ -122,6 +124,9 @@ private CapturedMultipartContent AddInternal(string name, HttpContent content, s
FileName = fileName,
FileNameStar = fileName
};
// The base class's collection of parts is cleared on Dispose, which isn't exactly in the spirit of "Captured",
// which is why we need to add it to this other collection. (#580)
_capturedParts.Add(content);
base.Add(content);
return this;
}
Expand Down

0 comments on commit 7eaa57a

Please sign in to comment.