Skip to content

Commit

Permalink
Adding AcceptEncodings override (#127)
Browse files Browse the repository at this point in the history
* Adding AcceptEncodings override

* Fixing docs
  • Loading branch information
Gekctek committed Apr 17, 2024
1 parent 86af424 commit 749a3e2
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 44 deletions.
37 changes: 36 additions & 1 deletion samples/Sample.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using EdjCase.ICP.Candid.Utilities;
using EdjCase.ICP.BLS.Models;
using System.Diagnostics;
using System.IO.Compression;

public class Program
{
Expand Down Expand Up @@ -162,7 +163,41 @@ string outputFilePath
AssetCanisterApiClient client = new(this.agent, canisterId);

Console.WriteLine($"Downloading asset '{key}'...");
byte[] assetBytes = await client.DownloadAssetAsync(key);
(byte[] assetBytes, string contentEncoding) = await client.DownloadAssetAsync(key);
switch (contentEncoding)
{
case "identity":
break;
case "gzip":
using (var memoryStream = new MemoryStream(assetBytes))
using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
using (var decompressedStream = new MemoryStream())
{
gzipStream.CopyTo(decompressedStream);
assetBytes = decompressedStream.ToArray();
}
break;
case "deflate":
using (var memoryStream = new MemoryStream(assetBytes))
using (var deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress))
using (var decompressedStream = new MemoryStream())
{
deflateStream.CopyTo(decompressedStream);
assetBytes = decompressedStream.ToArray();
}
break;
case "br":
using (var memoryStream = new MemoryStream(assetBytes))
using (var brotliStream = new BrotliStream(memoryStream, CompressionMode.Decompress))
using (var decompressedStream = new MemoryStream())
{
brotliStream.CopyTo(decompressedStream);
assetBytes = decompressedStream.ToArray();
}
break;
default:
throw new NotImplementedException($"Content encoding {contentEncoding} is not implemented");
}
File.WriteAllBytes(outputFilePath, assetBytes);
Console.WriteLine($"Downloaded asset '{key}' to {outputFilePath}");
}
Expand Down
3 changes: 2 additions & 1 deletion src/Agent/API.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 10 additions & 42 deletions src/Agent/Standards/AssetCanister/AssetCanisterApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,15 @@ public async Task UploadAssetChunkedAsync(
/// </summary>
/// <param name="key">The key of the asset to download.</param>
/// <param name="maxConcurrency">The maximum number of concurrent chunk downloads.</param>
/// <param name="acceptEncodings">The encodings to accept for the asset in order. Defaults to ["gzip", "deflate", "br", "identity"]</param>
/// <returns>The downloaded asset content as a byte array.</returns>
public async Task<byte[]> DownloadAssetAsync(string key, int maxConcurrency = 10)
public async Task<(byte[] Asset, string ContentEncoding)> DownloadAssetAsync(
string key,
int maxConcurrency = 10,
List<string>? acceptEncodings = null
)
{
List<string> acceptEncodings = new() { "identity", "gzip", "deflate", "br" };
acceptEncodings ??= new() { "gzip", "deflate", "br", "identity" };
GetResult result = await this.GetAsync(key, acceptEncodings);

if (!result.TotalLength.TryToUInt64(out ulong totalLength))
Expand All @@ -199,12 +204,12 @@ public async Task<byte[]> DownloadAssetAsync(string key, int maxConcurrency = 10
}
if (totalLength == (ulong)result.Content.Length)
{
return result.Content;
return (result.Content, result.ContentEncoding);
}
int chunkCount = (int)Math.Ceiling((double)totalLength / result.Content.Length);

// Create a list to store the chunk tasks
List<Task<byte[]>> chunkTasks = new List<Task<byte[]>>();
List<Task<byte[]>> chunkTasks = new();

// Create a semaphore to limit the number of concurrent tasks
SemaphoreSlim semaphore = new(maxConcurrency);
Expand Down Expand Up @@ -236,44 +241,7 @@ public async Task<byte[]> DownloadAssetAsync(string key, int maxConcurrency = 10
// Combine all the bytes into one byte[]
byte[] combinedBytes = result.Content.Concat(chunkTasks.SelectMany(t => t.Result)).ToArray();

switch (result.ContentEncoding)
{
case "identity":
case null:
case "":
break;
case "gzip":
using (var memoryStream = new MemoryStream(combinedBytes))
using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
using (var decompressedStream = new MemoryStream())
{
gzipStream.CopyTo(decompressedStream);
combinedBytes = decompressedStream.ToArray();
}
break;
case "deflate":
using (var memoryStream = new MemoryStream(combinedBytes))
using (var deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress))
using (var decompressedStream = new MemoryStream())
{
deflateStream.CopyTo(decompressedStream);
combinedBytes = decompressedStream.ToArray();
}
break;
case "br":
using (var memoryStream = new MemoryStream(combinedBytes))
using (var brotliStream = new BrotliStream(memoryStream, CompressionMode.Decompress))
using (var decompressedStream = new MemoryStream())
{
brotliStream.CopyTo(decompressedStream);
combinedBytes = decompressedStream.ToArray();
}
break;
default:
throw new NotImplementedException($"Content encoding {result.ContentEncoding} is not supported");
}

return combinedBytes;
return (combinedBytes, result.ContentEncoding);
}

/// <summary>
Expand Down

0 comments on commit 749a3e2

Please sign in to comment.