Je suis en train de travailler sur la Google Cloud Storage .NET client de la bibliothèque. Il y a trois fonctions (entre les deux .NET, mon client la bibliothèque et le service de Stockage) qui sont en combinant en un manière désagréable:
Lors du téléchargement des fichiers (des objets dans Google Cloud Storage la terminologie), le serveur comprend une table de hachage de données stockées. Mon code client valide ensuite que de hachage contre les données qu'il est téléchargé.
Une fonction séparée de Google Cloud Storage est que l'utilisateur peut définir l'Encodage de Contenu de l'objet, et qui est inclus comme un l'en-tête lors du téléchargement, lorsque la demande contient une correspondance Accept-Encoding. (Pour le moment, nous allons ignorer le comportement lors de l' la demande ne comprend pas que...)
HttpClientHandler
pouvez décompresser gzip (ou deflate) contenu automatiquement et de manière transparente.
Quand tous les trois sont combinées, nous avons des ennuis. Voici un courte mais complète du programme, ce qui démontre que, mais sans l'aide de mon de la bibliothèque du client (et de frapper un dossier accessible au public):
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
string url = "https://www.googleapis.com/download/storage/v1/b/"
+ "storage-library-test-bucket/o/gzipped-text.txt?alt=media";
var handler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
};
var client = new HttpClient(handler);
var response = await client.GetAsync(url);
byte[] content = await response.Content.ReadAsByteArrayAsync();
string text = Encoding.UTF8.GetString(content);
Console.WriteLine($"Content: {text}");
var hashHeader = response.Headers.GetValues("X-Goog-Hash").FirstOrDefault();
Console.WriteLine($"Hash header: {hashHeader}");
using (var md5 = MD5.Create())
{
var md5Hash = md5.ComputeHash(content);
var md5HashBase64 = Convert.ToBase64String(md5Hash);
Console.WriteLine($"MD5 of content: {md5HashBase64}");
}
}
}
.NET de Base du fichier de projet:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
</Project>
Sortie:
Content: hello world
Hash header: crc32c=T1s5RQ==,md5=xhF4M6pNFRDQnvaRRNVnkA==
MD5 of content: XrY7u+Ae7tCTyyK7j1rNww==
Comme vous pouvez le voir, le MD5 du contenu n'est pas le même que le MD5
une partie de l' X-Goog-Hash
- tête. (Dans ma bibliothèque cliente, je suis en utilisant le crc32c
de hachage, mais qui montre le même comportement.)
Ce n'est pas un bug en HttpClientHandler
- c'est prévu, mais une douleur
quand je veux valider le code de hachage. En gros, j'ai besoin d'au
contenu avant et après la décompression. Et je ne trouve pas de toute façon
de le faire.
Pour préciser ma exigences un peu, je sais comment éviter la décompression en HttpClient
et au lieu de décompresser après, lors de la lecture de ce cours d'eau, mais j'ai besoin d'être en mesure de le faire sans changer tout le code qui utilise l'résultant HttpResponseMessage
de la HttpClient
. (Il y a beaucoup de code qui traite les réponses, et je veux seulement faire le changement dans un endroit central.)
J'ai un plan que j'ai conçu et qui travaille autant que je l'ai trouvé à ce jour, mais il est un peu moche. Elle implique la création d'un trois-couche gestionnaire:
-
HttpClientHandler
avec décompression automatique désactivé. - Un nouveau gestionnaire qui remplace les flux de contenu avec un nouveau
Stream
sous-classe les délégués de l'origine et du contenu de flux, mais les hachages les données comme il est lu. - Une décompression seule gestionnaire, basée sur la Microsoft
DecompressionHandler
code.
Bien que cela fonctionne, il a les inconvénients de l':
- La licence Open source: vérifier exactement ce que je dois faire dans l'ordre pour créer un nouveau fichier dans mon repo basé sur le MIT sous licence Microsoft code
- Effectivement la fourche du MME code, ce qui signifie que je devrais probablement faire un contrôle régulier pour voir si les bugs ont été retrouvés
- Le code Microsoft utilise en interne des membres de l'assemblée, de sorte qu'il ne pas port le plus proprement qu'il le pourrait.
Si Microsoft fait DecompressionHandler
du public, ça aiderait
beaucoup - mais qui est susceptible d'être dans un délai plus long que j'ai besoin.
Ce que je recherche est une approche alternative si possible -
quelque chose que j'ai raté qui me permet d'obtenir le contenu avant
la décompression. Je ne veux pas réinventer HttpClient
- la réponse
est souvent chunked par exemple, et je ne veux pas entrer dans
cet aspect des choses. C'est une jolie interception spécifique au point que
Je suis à la recherche pour.