HTTP Compression mit HTTP Client

Eigentlich ging ich davon aus, das der Network Stack von WinRT so ähnlich funktioniert wie ich das von Silverlight (webclient) kenne. Doch Windows 8 ist anders, es kennt keinen WebClient oder WebRequest. Es gibt dort nur Socket Klassen. Erst im .NET Layer ist eine HTTPClient Klasse vorhanden, die es erlaubt Web Requests abzusetzen. Beispiele dazu habe ich (vb.net) schon in meinem Blog gezeigt.

 Private Async Function Button_Click_1(sender As Object, e As RoutedEventArgs) As Task
        Dim http = New HttpClient
        http.MaxResponseContentBufferSize = 100000
        Dim resp = Await Http.GetStringAsync(New Uri("http://www.heise.de"))
        text1.Text = Windows.Data.Html.HtmlUtilities.ConvertToText(resp)
End Function

 

Im ersten Windows METRO VB.NET Beispiel hole ich den HTML Code aus einer Website und zeige ihn in einem Textblock an. die HTML Tags werden mit ConvertTo entfernt. Eine häufige Fehlerquelle ist, das der Inhalt des Requests plötzlich grösser ist als der Default Wert. Solche Exceptions kommen auch nicht beim User an, sondern erzeugen einfach kein Ergebnis.

Der HTML Code der hier übertragen wird, ist sozusagen pur (Zeile 1 im Fiddler Screenshot) . Wenn man diese Website mit dem Browser öffnet wird, diese komprimiert übertragen( Zeile 2). Der Unterschied ist in dem Fall gewaltig, fast die vierfache Datenmenge.

image

Der Grund liegt im HTTP Header. Der Client muss Accept-Encoding gzip und/oder deflate mitsenden, damit der Web Server weis, das er die Daten komprimieren darf.

image

Der Header des METRO Clients

image

Man kann den HTTP Header auch manuell anhängen.

Dim http = New HttpClient
http.DefaultRequestHeaders.AcceptEncoding.Add(Headers.StringWithQualityHeaderValue.Parse("gzip"))
http.DefaultRequestHeaders.AcceptEncoding.Add(Headers.StringWithQualityHeaderValue.Parse("deflate"))
http.MaxResponseContentBufferSize = 100000
Dim resp = Await Http.GetStringAsync(New Uri("http://www.heise.de"))
text1.Text = Windows.Data.Html.HtmlUtilities.ConvertToText(resp)

Das reduziert die übertragene Daten (Zeile 3) natürlich. Angezeigt werden können diese aber nicht, weil das decodieren der komprimierten HTML Daten fehlt.

Man sieht das im Fiddler sehr gut. Im Request Header die zusätzliche Zeile im Client. Im Response sieht man im Textview nur eine Raute. Eben komprimiert.

image

Das Fiddlertool ist so nett und bietet manuell die Möglichkeit zu dekodieren. Aber das reicht für eine laufende Anwendung natürlich nicht.

Im HttpClient kann man ähnlich der IIS Pipeline in den Request Prozess per Handler eingreifen und so auch den Header beeinflussen. In diesem Beispiel wird die automatische Kompression aktiviert. Sowohl für den Request als auch den Response.

 Dim http = New HttpClient(New HttpClientHandler() With
                                 {.AutomaticDecompression = DecompressionMethods.Deflate Or DecompressionMethods.GZip})

 

Das Ergebnis sieht man im Fiddler Zeile 4.

Kommentar schreiben