@@ -23,8 +23,7 @@ namespace Ipfs.Http
23
23
/// <seealso href="https://ipfs.io/docs/api/">IPFS API</seealso>
24
24
/// <seealso href="https://ipfs.io/docs/commands/">IPFS commands</seealso>
25
25
/// <remarks>
26
- /// <b>IpfsClient</b> is thread safe, only one instance is required
27
- /// by the application.
26
+ /// <b>IpfsClient</b> is thread safe, only one instance is required by the application.
28
27
/// </remarks>
29
28
public partial class IpfsClient : ICoreApi
30
29
{
@@ -61,6 +60,7 @@ public IpfsClient()
61
60
62
61
var assembly = typeof ( IpfsClient ) . GetTypeInfo ( ) . Assembly ;
63
62
var version = assembly . GetName ( ) . Version ;
63
+
64
64
UserAgent = string . Format ( "{0}/{1}.{2}.{3}" , assembly . GetName ( ) . Name , version . Major , version . Minor , version . Revision ) ;
65
65
TrustedPeers = new TrustedPeerCollection ( this ) ;
66
66
@@ -115,7 +115,7 @@ public IpfsClient(string host)
115
115
/// The list of peers that are initially trusted by IPFS.
116
116
/// </summary>
117
117
/// <remarks>
118
- /// This is equilivent to <c>ipfs bootstrap list</c>.
118
+ /// This is equivalent to <c>ipfs bootstrap list</c>.
119
119
/// </remarks>
120
120
public TrustedPeerCollection TrustedPeers { get ; private set ; }
121
121
@@ -174,6 +174,7 @@ Uri BuildCommand(string command, string arg = null, params string[] options)
174
174
{
175
175
var url = "/api/v0/" + command ;
176
176
var q = new StringBuilder ( ) ;
177
+
177
178
if ( arg != null )
178
179
{
179
180
q . Append ( "&arg=" ) ;
@@ -223,23 +224,29 @@ HttpClient Api()
223
224
{
224
225
if ( api == null )
225
226
{
226
- var handler = new HttpClientHandler ( ) ;
227
- if ( handler . SupportsAutomaticDecompression )
227
+ if ( HttpMessageHandler is HttpClientHandler handler && handler . SupportsAutomaticDecompression )
228
228
{
229
229
handler . AutomaticDecompression = DecompressionMethods . GZip
230
230
| DecompressionMethods . Deflate ;
231
231
}
232
- api = new HttpClient ( handler )
232
+
233
+ api = new HttpClient ( HttpMessageHandler )
233
234
{
234
- Timeout = System . Threading . Timeout . InfiniteTimeSpan
235
+ Timeout = Timeout . InfiniteTimeSpan
235
236
} ;
237
+
236
238
api . DefaultRequestHeaders . Add ( "User-Agent" , UserAgent ) ;
237
239
}
238
240
}
239
241
}
240
242
return api ;
241
243
}
242
244
245
+ /// <summary>
246
+ /// The message handler to use for communicating over HTTP.
247
+ /// </summary>
248
+ public HttpMessageHandler HttpMessageHandler { get ; set ; } = new HttpClientHandler ( ) ;
249
+
243
250
/// <summary>
244
251
/// Perform an <see href="https://ipfs.io/docs/api/">IPFS API command</see> returning a string.
245
252
/// </summary>
@@ -265,29 +272,49 @@ HttpClient Api()
265
272
public async Task < string > DoCommandAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
266
273
{
267
274
var url = BuildCommand ( command , arg , options ) ;
275
+
268
276
if ( log . IsDebugEnabled )
269
- log . Debug ( "POST " + url . ToString ( ) ) ;
277
+ log . Debug ( "POST " + url ) ;
278
+
270
279
using ( var response = await Api ( ) . PostAsync ( url , null , cancel ) )
271
280
{
272
281
await ThrowOnErrorAsync ( response ) ;
273
282
var body = await response . Content . ReadAsStringAsync ( ) ;
283
+
274
284
if ( log . IsDebugEnabled )
275
285
log . Debug ( "RSP " + body ) ;
286
+
276
287
return body ;
277
288
}
278
289
}
279
290
280
- internal async Task DoCommandAsync ( Uri url , CancellationToken cancel )
291
+ internal Task DoCommandAsync ( Uri url , byte [ ] bytes , CancellationToken cancel )
292
+ {
293
+ return DoCommandAsync ( url , new ByteArrayContent ( bytes ) , cancel ) ;
294
+ }
295
+
296
+ internal Task DoCommandAsync ( Uri url , Stream stream , CancellationToken cancel )
297
+ {
298
+ return DoCommandAsync ( url , new StreamContent ( stream ) , cancel ) ;
299
+ }
300
+
301
+ internal Task DoCommandAsync ( Uri url , string str , CancellationToken cancel )
302
+ {
303
+ return DoCommandAsync ( url , new StringContent ( str ) , cancel ) ;
304
+ }
305
+
306
+ internal async Task DoCommandAsync ( Uri url , HttpContent content , CancellationToken cancel )
281
307
{
282
308
if ( log . IsDebugEnabled )
283
- log . Debug ( "POST " + url . ToString ( ) ) ;
284
- using ( var response = await Api ( ) . PostAsync ( url , null , cancel ) )
309
+ log . Debug ( "POST " + url ) ;
310
+
311
+ using ( var response = await Api ( ) . PostAsync ( url , new MultipartFormDataContent { { content , "\" file\" " } } , cancel ) )
285
312
{
286
313
await ThrowOnErrorAsync ( response ) ;
287
314
var body = await response . Content . ReadAsStringAsync ( ) ;
315
+
288
316
if ( log . IsDebugEnabled )
289
317
log . Debug ( "RSP " + body ) ;
290
- return ;
291
318
}
292
319
}
293
320
@@ -353,12 +380,15 @@ public async Task<T> DoCommandAsync<T>(string command, CancellationToken cancel,
353
380
public async Task < Stream > PostDownloadAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
354
381
{
355
382
var url = BuildCommand ( command , arg , options ) ;
383
+
356
384
if ( log . IsDebugEnabled )
357
- log . Debug ( "POST " + url . ToString ( ) ) ;
358
- var request = new HttpRequestMessage ( HttpMethod . Post , url ) ;
385
+ log . Debug ( "POST " + url ) ;
359
386
387
+ var request = new HttpRequestMessage ( HttpMethod . Post , url ) ;
360
388
var response = await Api ( ) . SendAsync ( request , HttpCompletionOption . ResponseHeadersRead , cancel ) ;
389
+
361
390
await ThrowOnErrorAsync ( response ) ;
391
+
362
392
return await response . Content . ReadAsStreamAsync ( ) ;
363
393
}
364
394
@@ -388,10 +418,13 @@ public async Task<Stream> PostDownloadAsync(string command, CancellationToken ca
388
418
public async Task < Stream > DownloadAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
389
419
{
390
420
var url = BuildCommand ( command , arg , options ) ;
421
+
391
422
if ( log . IsDebugEnabled )
392
- log . Debug ( "GET " + url . ToString ( ) ) ;
423
+ log . Debug ( "GET " + url ) ;
424
+
393
425
var response = await Api ( ) . GetAsync ( url , HttpCompletionOption . ResponseHeadersRead , cancel ) ;
394
426
await ThrowOnErrorAsync ( response ) ;
427
+
395
428
return await response . Content . ReadAsStreamAsync ( ) ;
396
429
}
397
430
@@ -421,10 +454,13 @@ public async Task<Stream> DownloadAsync(string command, CancellationToken cancel
421
454
public async Task < byte [ ] > DownloadBytesAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
422
455
{
423
456
var url = BuildCommand ( command , arg , options ) ;
457
+
424
458
if ( log . IsDebugEnabled )
425
- log . Debug ( "GET " + url . ToString ( ) ) ;
459
+ log . Debug ( "GET " + url ) ;
460
+
426
461
var response = await Api ( ) . GetAsync ( url , HttpCompletionOption . ResponseHeadersRead , cancel ) ;
427
462
await ThrowOnErrorAsync ( response ) ;
463
+
428
464
return await response . Content . ReadAsByteArrayAsync ( ) ;
429
465
}
430
466
@@ -460,21 +496,26 @@ public async Task<String> UploadAsync(string command, CancellationToken cancel,
460
496
{
461
497
var content = new MultipartFormDataContent ( ) ;
462
498
var streamContent = new StreamContent ( data ) ;
499
+
463
500
streamContent . Headers . ContentType = new MediaTypeHeaderValue ( "application/octet-stream" ) ;
501
+
464
502
if ( string . IsNullOrEmpty ( name ) )
465
503
content . Add ( streamContent , "file" , unknownFilename ) ;
466
504
else
467
505
content . Add ( streamContent , "file" , name ) ;
468
506
469
507
var url = BuildCommand ( command , null , options ) ;
470
508
if ( log . IsDebugEnabled )
471
- log . Debug ( "POST " + url . ToString ( ) ) ;
509
+ log . Debug ( "POST " + url ) ;
510
+
472
511
using ( var response = await Api ( ) . PostAsync ( url , content , cancel ) )
473
512
{
474
513
await ThrowOnErrorAsync ( response ) ;
475
514
var json = await response . Content . ReadAsStringAsync ( ) ;
515
+
476
516
if ( log . IsDebugEnabled )
477
517
log . Debug ( "RSP " + json ) ;
518
+
478
519
return json ;
479
520
}
480
521
}
@@ -510,17 +551,19 @@ public async Task<Stream> Upload2Async(string command, CancellationToken cancel,
510
551
{
511
552
var content = new MultipartFormDataContent ( ) ;
512
553
var streamContent = new StreamContent ( data ) ;
554
+
513
555
streamContent . Headers . ContentType = new MediaTypeHeaderValue ( "application/octet-stream" ) ;
514
- if ( string . IsNullOrEmpty ( name ) )
515
- content . Add ( streamContent , "file" , unknownFilename ) ;
516
- else
517
- content . Add ( streamContent , "file" , name ) ;
556
+
557
+ content . Add ( streamContent , "file" , string . IsNullOrEmpty ( name ) ? unknownFilename : name ) ;
518
558
519
559
var url = BuildCommand ( command , null , options ) ;
560
+
520
561
if ( log . IsDebugEnabled )
521
- log . Debug ( "POST " + url . ToString ( ) ) ;
562
+ log . Debug ( "POST " + url ) ;
563
+
522
564
var response = await Api ( ) . PostAsync ( url , content , cancel ) ;
523
565
await ThrowOnErrorAsync ( response ) ;
566
+
524
567
return await response . Content . ReadAsStreamAsync ( ) ;
525
568
}
526
569
@@ -531,18 +574,24 @@ public async Task<String> UploadAsync(string command, CancellationToken cancel,
531
574
{
532
575
var content = new MultipartFormDataContent ( ) ;
533
576
var streamContent = new ByteArrayContent ( data ) ;
577
+
534
578
streamContent . Headers . ContentType = new MediaTypeHeaderValue ( "application/octet-stream" ) ;
535
579
content . Add ( streamContent , "file" , unknownFilename ) ;
536
580
537
581
var url = BuildCommand ( command , null , options ) ;
582
+
538
583
if ( log . IsDebugEnabled )
539
- log . Debug ( "POST " + url . ToString ( ) ) ;
584
+ log . Debug ( "POST " + url ) ;
585
+
540
586
using ( var response = await Api ( ) . PostAsync ( url , content , cancel ) )
541
587
{
542
588
await ThrowOnErrorAsync ( response ) ;
589
+
543
590
var json = await response . Content . ReadAsStringAsync ( ) ;
591
+
544
592
if ( log . IsDebugEnabled )
545
593
log . Debug ( "RSP " + json ) ;
594
+
546
595
return json ;
547
596
}
548
597
}
@@ -562,24 +611,31 @@ async Task<bool> ThrowOnErrorAsync(HttpResponseMessage response)
562
611
{
563
612
if ( response . IsSuccessStatusCode )
564
613
return true ;
614
+
565
615
if ( response . StatusCode == HttpStatusCode . NotFound )
566
616
{
567
- var error = "Invalid IPFS command: " + response . RequestMessage . RequestUri . ToString ( ) ;
617
+ var error = "Invalid IPFS command: " + response . RequestMessage . RequestUri ;
618
+
568
619
if ( log . IsDebugEnabled )
569
620
log . Debug ( "ERR " + error ) ;
621
+
570
622
throw new HttpRequestException ( error ) ;
571
623
}
572
624
573
625
var body = await response . Content . ReadAsStringAsync ( ) ;
626
+
574
627
if ( log . IsDebugEnabled )
575
628
log . Debug ( "ERR " + body ) ;
629
+
576
630
string message = body ;
631
+
577
632
try
578
633
{
579
634
var res = JsonConvert . DeserializeObject < dynamic > ( body ) ;
580
635
message = ( string ) res . Message ;
581
636
}
582
637
catch { }
638
+
583
639
throw new HttpRequestException ( message ) ;
584
640
}
585
641
0 commit comments