Skip to content

Commit 021dba3

Browse files
committed
saving work
1 parent 5a2b730 commit 021dba3

6 files changed

Lines changed: 94 additions & 21 deletions

File tree

Source/Pinata.Client.Tests/IntegrationTests/AllTests.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public async Task data_pin_total()
4444
[Test]
4545
public async Task pinning_unpin()
4646
{
47-
var r = await this.client.Pinning.UnpinAsync("foobar");
47+
var r = await this.client.Pinning.UnpinAsync("QmR9HwzakHVr67HFzzgJHoRjwzTTt4wtD6KU4NFe2ArYuj");
4848
}
4949

5050
[Test]
@@ -131,14 +131,10 @@ public async Task pinning_pinFileToIPFS_bytes()
131131
";
132132
var r = await this.client.Pinning.PinFileToIPFSAsync(content =>
133133
{
134-
var fileData = new StringContent(html, Encoding.UTF8, MediaTypeNames.Text.Html);
135-
var header = new ContentDispositionHeaderValue("form-data") {
136-
Name = "file",
137-
FileName = "test.html"
138-
};
139-
fileData.Headers.ContentDisposition = header;
134+
var file = new StringContent(html, Encoding.UTF8, MediaTypeNames.Text.Html)
135+
.AsPinataFile("test2.html");
140136

141-
content.Add(fileData);
137+
content.Add(file);
142138
});
143139

144140
}

Source/Pinata.Client.Tests/PinningTests.cs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
using System.Linq;
2+
using System.Net.Http;
3+
using System.Net.Mime;
4+
using System.Text;
15
using System.Threading.Tasks;
26
using FluentAssertions;
7+
using Flurl.Http.Content;
38
using NUnit.Framework;
49
using static System.Net.Http.HttpMethod;
510

@@ -138,15 +143,39 @@ public async Task new_user_pin_policy()
138143
}
139144

140145
[Test]
141-
public async Task upload()
146+
public async Task pin_html_file()
142147
{
143-
var svg = @"
144-
<svg xmlns=""http://www.w3.org/2000/svg"" viewBox=""0 0 100 100"">
145-
<circle cx=""50"" cy=""50"" r=""48"" fill=""none"" stroke=""#000""/>
146-
<path d=""M50,2a48,48 0 1 1 0,96a24 24 0 1 1 0-48a24 24 0 1 0 0-48""/>
147-
<circle cx=""50"" cy=""26"" r=""6""/>
148-
<circle cx=""50"" cy=""74"" r=""6"" fill=""#FFF""/>
149-
</svg>";
148+
this.server.RespondWithJsonTestFile();
149+
150+
var html = @"
151+
<html>
152+
<head>
153+
<title>Hello IPFS!</title>
154+
</head>
155+
<body>
156+
<h1>Hello World</h1>
157+
</body>
158+
</html>
159+
";
160+
var r = await this.client.Pinning.PinFileToIPFSAsync(payload =>
161+
{
162+
var file = new StringContent(html, Encoding.UTF8, MediaTypeNames.Text.Html)
163+
.AsPinataFile("index.html");
164+
165+
payload.Add(file);
166+
});
167+
168+
169+
this.server.ShouldHaveCalledPath("/pinning/pinFileToIPFS")
170+
.With(fc =>
171+
{
172+
var content = fc.HttpRequestMessage.Content as CapturedMultipartContent;
173+
174+
var cds = content.Headers.ContentDisposition;
175+
cds.Name.Should().Be("file");
176+
cds.FileName.Should().Be("index.html");
177+
return true;
178+
});
150179

151180

152181
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"IpfsHash":"QmR9HwzakHVr67HFzzgJHoRjwzTTt4wtD6KU4NFe2ArYuj","PinSize":136,"Timestamp":"2020-11-28T02:23:26.663Z"}

Source/Pinata.Client/Models/Response.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ public partial class PinJsonToIpfsResponse : Response
5555
public DateTimeOffset Timestamp { get; set; }
5656
}
5757

58+
public partial class PinFileToIpfsResponse : Response
59+
{
60+
[JsonProperty("IpfsHash")]
61+
public string IpfsHash { get; set; }
62+
63+
[JsonProperty("PinSize")]
64+
public long PinSize { get; set; }
65+
66+
[JsonProperty("Timestamp")]
67+
public DateTimeOffset Timestamp { get; set; }
68+
}
69+
5870
public class UserPinPolicyResponse : Response
5971
{
6072
public string Result { get; set; }

Source/Pinata.Client/PinataClient.Pinning.cs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.IO;
44
using System.Linq;
55
using System.Net.Http;
6+
using System.Net.Http.Headers;
7+
using System.Net.Mime;
68
using System.Text;
79
using System.Threading;
810
using System.Threading.Tasks;
@@ -110,7 +112,7 @@ public interface IPinningEndpoint
110112
/// <summary>
111113
/// This endpoint allows the sender to add and pin any file, or directory, to Pinata's IPFS nodes.
112114
/// </summary>
113-
Task<IFlurlResponse> PinFileToIPFSAsync(Action<CapturedMultipartContent> callback, PinataMetadata pinataMetadata = null, PinataOptions pinataOptions = null, CancellationToken cancellationToken = default);
115+
Task<PinFileToIpfsResponse> PinFileToIPFSAsync(Action<CapturedMultipartContent> payloadBuilder, PinataMetadata pinataMetadata = null, PinataOptions pinataOptions = null, CancellationToken cancellationToken = default);
114116
}
115117

116118
public partial class PinataClient : IPinningEndpoint
@@ -187,14 +189,32 @@ public Task<UserPinPolicyResponse> UserPinPolicyAsync(PinPolicy newPinPolicy, bo
187189
.ReceiveJson<UserPinPolicyResponse>();
188190
}
189191

190-
public Task<IFlurlResponse> PinFileToIPFSAsync(Action<CapturedMultipartContent> callback, PinataMetadata pinataMetadata = null, PinataOptions pinataOptions = null, CancellationToken cancellationToken = default)
192+
public Task<PinFileToIpfsResponse> PinFileToIPFSAsync(Action<CapturedMultipartContent> payloadBuilder, PinataMetadata pinataMetadata = null, PinataOptions pinataOptions = null, CancellationToken cancellationToken = default)
191193
{
194+
static void AssertAllHttpContentHasFileName(CapturedMultipartContent content)
195+
{
196+
foreach( var part in content )
197+
{
198+
var name = part?.Headers?.ContentDisposition?.Name;
199+
var fileName = part?.Headers?.ContentDisposition?.FileName;
200+
if( string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(fileName) )
201+
{
202+
throw new HttpRequestException("The 'httpContent.Headers.ContentDisposition.(Name|FileName)' is null or whitespace. "+
203+
"All multi-part upload content must contain a 'Name' and 'FileName' content disposition header value. "+
204+
"Try using the httpContent.AsPinataFile('name.txt') extension method to set the required fields on the HttpContent you are adding.");
205+
}
206+
}
207+
}
208+
192209
return this.PinningEndpoint
193210
.WithClient(this)
194211
.AppendPathSegment("pinFileToIPFS")
195212
.PostMultipartAsync(multiPart =>
196213
{
197-
callback(multiPart);
214+
payloadBuilder(multiPart);
215+
216+
AssertAllHttpContentHasFileName(multiPart);
217+
198218
if( pinataMetadata is not null )
199219
{
200220
multiPart.AddJson("pinataMetadata", pinataMetadata);
@@ -203,7 +223,22 @@ public Task<IFlurlResponse> PinFileToIPFSAsync(Action<CapturedMultipartContent>
203223
{
204224
multiPart.AddJson("pinataOptions", pinataOptions);
205225
}
206-
}, cancellationToken);
226+
}, cancellationToken)
227+
.ReceiveJson<PinFileToIpfsResponse>();
228+
}
229+
}
230+
231+
public static class ExtensionsForHttpContent
232+
{
233+
public static T AsPinataFile<T>(this T content, string remoteFilePath) where T : HttpContent
234+
{
235+
var header = new ContentDispositionHeaderValue("form-data")
236+
{
237+
Name = "file",
238+
FileName = remoteFilePath
239+
};
240+
content.Headers.ContentDisposition = header;
241+
return content;
207242
}
208243
}
209244
}

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ deploy:
4646
symbol_server:
4747
skip_symbols: false
4848
api_key:
49-
secure: 1nPS2ttf+N4+FUhd+GZycrL7YzSWQpZjnGOMCb5+pGJXSdx0IFvVF8xhTGna7B9t
49+
secure: 2iGWqMNZzSL3RUQ7ColFsbAAVKvx+KKALxdDWjv8wgQh8z1ZrJMbAVVlTx35ehvg
5050
artifact: NuGet, Symbols
5151
on:
5252
branch: master

0 commit comments

Comments
 (0)