@@ -23,8 +23,7 @@ namespace Ipfs.Http
2323 /// <seealso href="https://ipfs.io/docs/api/">IPFS API</seealso>
2424 /// <seealso href="https://ipfs.io/docs/commands/">IPFS commands</seealso>
2525 /// <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.
2827 /// </remarks>
2928 public partial class IpfsClient : ICoreApi
3029 {
@@ -61,6 +60,7 @@ public IpfsClient()
6160
6261 var assembly = typeof ( IpfsClient ) . GetTypeInfo ( ) . Assembly ;
6362 var version = assembly . GetName ( ) . Version ;
63+
6464 UserAgent = string . Format ( "{0}/{1}.{2}.{3}" , assembly . GetName ( ) . Name , version . Major , version . Minor , version . Revision ) ;
6565 TrustedPeers = new TrustedPeerCollection ( this ) ;
6666
@@ -115,7 +115,7 @@ public IpfsClient(string host)
115115 /// The list of peers that are initially trusted by IPFS.
116116 /// </summary>
117117 /// <remarks>
118- /// This is equilivent to <c>ipfs bootstrap list</c>.
118+ /// This is equivalent to <c>ipfs bootstrap list</c>.
119119 /// </remarks>
120120 public TrustedPeerCollection TrustedPeers { get ; private set ; }
121121
@@ -174,6 +174,7 @@ Uri BuildCommand(string command, string arg = null, params string[] options)
174174 {
175175 var url = "/api/v0/" + command ;
176176 var q = new StringBuilder ( ) ;
177+
177178 if ( arg != null )
178179 {
179180 q . Append ( "&arg=" ) ;
@@ -223,23 +224,29 @@ HttpClient Api()
223224 {
224225 if ( api == null )
225226 {
226- var handler = new HttpClientHandler ( ) ;
227- if ( handler . SupportsAutomaticDecompression )
227+ if ( HttpMessageHandler is HttpClientHandler handler && handler . SupportsAutomaticDecompression )
228228 {
229229 handler . AutomaticDecompression = DecompressionMethods . GZip
230230 | DecompressionMethods . Deflate ;
231231 }
232- api = new HttpClient ( handler )
232+
233+ api = new HttpClient ( HttpMessageHandler )
233234 {
234- Timeout = System . Threading . Timeout . InfiniteTimeSpan
235+ Timeout = Timeout . InfiniteTimeSpan
235236 } ;
237+
236238 api . DefaultRequestHeaders . Add ( "User-Agent" , UserAgent ) ;
237239 }
238240 }
239241 }
240242 return api ;
241243 }
242244
245+ /// <summary>
246+ /// The message handler to use for communicating over HTTP.
247+ /// </summary>
248+ public HttpMessageHandler HttpMessageHandler { get ; set ; } = new HttpClientHandler ( ) ;
249+
243250 /// <summary>
244251 /// Perform an <see href="https://ipfs.io/docs/api/">IPFS API command</see> returning a string.
245252 /// </summary>
@@ -265,29 +272,49 @@ HttpClient Api()
265272 public async Task < string > DoCommandAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
266273 {
267274 var url = BuildCommand ( command , arg , options ) ;
275+
268276 if ( log . IsDebugEnabled )
269- log . Debug ( "POST " + url . ToString ( ) ) ;
277+ log . Debug ( "POST " + url ) ;
278+
270279 using ( var response = await Api ( ) . PostAsync ( url , null , cancel ) )
271280 {
272281 await ThrowOnErrorAsync ( response ) ;
273282 var body = await response . Content . ReadAsStringAsync ( ) ;
283+
274284 if ( log . IsDebugEnabled )
275285 log . Debug ( "RSP " + body ) ;
286+
276287 return body ;
277288 }
278289 }
279290
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 )
281307 {
282308 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 ) )
285312 {
286313 await ThrowOnErrorAsync ( response ) ;
287314 var body = await response . Content . ReadAsStringAsync ( ) ;
315+
288316 if ( log . IsDebugEnabled )
289317 log . Debug ( "RSP " + body ) ;
290- return ;
291318 }
292319 }
293320
@@ -353,12 +380,15 @@ public async Task<T> DoCommandAsync<T>(string command, CancellationToken cancel,
353380 public async Task < Stream > PostDownloadAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
354381 {
355382 var url = BuildCommand ( command , arg , options ) ;
383+
356384 if ( log . IsDebugEnabled )
357- log . Debug ( "POST " + url . ToString ( ) ) ;
358- var request = new HttpRequestMessage ( HttpMethod . Post , url ) ;
385+ log . Debug ( "POST " + url ) ;
359386
387+ var request = new HttpRequestMessage ( HttpMethod . Post , url ) ;
360388 var response = await Api ( ) . SendAsync ( request , HttpCompletionOption . ResponseHeadersRead , cancel ) ;
389+
361390 await ThrowOnErrorAsync ( response ) ;
391+
362392 return await response . Content . ReadAsStreamAsync ( ) ;
363393 }
364394
@@ -388,10 +418,13 @@ public async Task<Stream> PostDownloadAsync(string command, CancellationToken ca
388418 public async Task < Stream > DownloadAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
389419 {
390420 var url = BuildCommand ( command , arg , options ) ;
421+
391422 if ( log . IsDebugEnabled )
392- log . Debug ( "GET " + url . ToString ( ) ) ;
423+ log . Debug ( "GET " + url ) ;
424+
393425 var response = await Api ( ) . GetAsync ( url , HttpCompletionOption . ResponseHeadersRead , cancel ) ;
394426 await ThrowOnErrorAsync ( response ) ;
427+
395428 return await response . Content . ReadAsStreamAsync ( ) ;
396429 }
397430
@@ -421,10 +454,13 @@ public async Task<Stream> DownloadAsync(string command, CancellationToken cancel
421454 public async Task < byte [ ] > DownloadBytesAsync ( string command , CancellationToken cancel , string arg = null , params string [ ] options )
422455 {
423456 var url = BuildCommand ( command , arg , options ) ;
457+
424458 if ( log . IsDebugEnabled )
425- log . Debug ( "GET " + url . ToString ( ) ) ;
459+ log . Debug ( "GET " + url ) ;
460+
426461 var response = await Api ( ) . GetAsync ( url , HttpCompletionOption . ResponseHeadersRead , cancel ) ;
427462 await ThrowOnErrorAsync ( response ) ;
463+
428464 return await response . Content . ReadAsByteArrayAsync ( ) ;
429465 }
430466
@@ -460,21 +496,26 @@ public async Task<String> UploadAsync(string command, CancellationToken cancel,
460496 {
461497 var content = new MultipartFormDataContent ( ) ;
462498 var streamContent = new StreamContent ( data ) ;
499+
463500 streamContent . Headers . ContentType = new MediaTypeHeaderValue ( "application/octet-stream" ) ;
501+
464502 if ( string . IsNullOrEmpty ( name ) )
465503 content . Add ( streamContent , "file" , unknownFilename ) ;
466504 else
467505 content . Add ( streamContent , "file" , name ) ;
468506
469507 var url = BuildCommand ( command , null , options ) ;
470508 if ( log . IsDebugEnabled )
471- log . Debug ( "POST " + url . ToString ( ) ) ;
509+ log . Debug ( "POST " + url ) ;
510+
472511 using ( var response = await Api ( ) . PostAsync ( url , content , cancel ) )
473512 {
474513 await ThrowOnErrorAsync ( response ) ;
475514 var json = await response . Content . ReadAsStringAsync ( ) ;
515+
476516 if ( log . IsDebugEnabled )
477517 log . Debug ( "RSP " + json ) ;
518+
478519 return json ;
479520 }
480521 }
@@ -510,17 +551,19 @@ public async Task<Stream> Upload2Async(string command, CancellationToken cancel,
510551 {
511552 var content = new MultipartFormDataContent ( ) ;
512553 var streamContent = new StreamContent ( data ) ;
554+
513555 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 ) ;
518558
519559 var url = BuildCommand ( command , null , options ) ;
560+
520561 if ( log . IsDebugEnabled )
521- log . Debug ( "POST " + url . ToString ( ) ) ;
562+ log . Debug ( "POST " + url ) ;
563+
522564 var response = await Api ( ) . PostAsync ( url , content , cancel ) ;
523565 await ThrowOnErrorAsync ( response ) ;
566+
524567 return await response . Content . ReadAsStreamAsync ( ) ;
525568 }
526569
@@ -531,18 +574,24 @@ public async Task<String> UploadAsync(string command, CancellationToken cancel,
531574 {
532575 var content = new MultipartFormDataContent ( ) ;
533576 var streamContent = new ByteArrayContent ( data ) ;
577+
534578 streamContent . Headers . ContentType = new MediaTypeHeaderValue ( "application/octet-stream" ) ;
535579 content . Add ( streamContent , "file" , unknownFilename ) ;
536580
537581 var url = BuildCommand ( command , null , options ) ;
582+
538583 if ( log . IsDebugEnabled )
539- log . Debug ( "POST " + url . ToString ( ) ) ;
584+ log . Debug ( "POST " + url ) ;
585+
540586 using ( var response = await Api ( ) . PostAsync ( url , content , cancel ) )
541587 {
542588 await ThrowOnErrorAsync ( response ) ;
589+
543590 var json = await response . Content . ReadAsStringAsync ( ) ;
591+
544592 if ( log . IsDebugEnabled )
545593 log . Debug ( "RSP " + json ) ;
594+
546595 return json ;
547596 }
548597 }
@@ -562,24 +611,31 @@ async Task<bool> ThrowOnErrorAsync(HttpResponseMessage response)
562611 {
563612 if ( response . IsSuccessStatusCode )
564613 return true ;
614+
565615 if ( response . StatusCode == HttpStatusCode . NotFound )
566616 {
567- var error = "Invalid IPFS command: " + response . RequestMessage . RequestUri . ToString ( ) ;
617+ var error = "Invalid IPFS command: " + response . RequestMessage . RequestUri ;
618+
568619 if ( log . IsDebugEnabled )
569620 log . Debug ( "ERR " + error ) ;
621+
570622 throw new HttpRequestException ( error ) ;
571623 }
572624
573625 var body = await response . Content . ReadAsStringAsync ( ) ;
626+
574627 if ( log . IsDebugEnabled )
575628 log . Debug ( "ERR " + body ) ;
629+
576630 string message = body ;
631+
577632 try
578633 {
579634 var res = JsonConvert . DeserializeObject < dynamic > ( body ) ;
580635 message = ( string ) res . Message ;
581636 }
582637 catch { }
638+
583639 throw new HttpRequestException ( message ) ;
584640 }
585641
0 commit comments