Как поддерживать сжатые HTTP-запросы в Asp.Net 4.0 / IIS7? - PullRequest
8 голосов
/ 10 декабря 2010

Для веб-приложения ASP.NET 4.0 / IIS7 мне бы хотелось поддерживать сжатые HTTP запросы . По сути, я хотел бы поддержать клиентов, которые добавили бы Content-Encoding: gzip в заголовки запроса и соответственно сжали тело.

Кто-нибудь знает, как мне добиться такого поведения?

Ps: касательно, у меня есть несколько конечных точек REST и SOAP, и он чувствует себя лучшим решением для поддержки сжатия на уровне HTTP, а не пользовательских кодеров для каждой конечной точки.

Ответы [ 3 ]

5 голосов
/ 11 декабря 2010

Для тех, кто может быть заинтересован, реализация довольно проста с IHttpModule, который просто фильтрует входящие запросы.

public class GZipDecompressModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += BeginRequest;
    }

    void BeginRequest(object sender, EventArgs e)
    {
        var app = (HttpApplication)sender;

        if ("gzip" == app.Request.Headers["Content-Encoding"])
        {
            app.Request.Filter = new GZipStream(
               app.Request.Filter, CompressionMode.Decompress);
        }
    }

    public void Dispose()
    {
    }
}

Обновление: Похоже, что этот подход вызывает проблему в WCF, поскольку WCF полагается на исходное Content-Length, а не на значение, полученное после распаковки.

1 голос
/ 24 мая 2013

Попробуйте ответ Wiktor на мой аналогичный вопрос здесь:

Как включить сжатие GZIP для запросов POST (выгрузка) к SOAP WebService на IIS 7?

... но учтите, что его реализация в его блоге содержала несколько ошибок / проблем совместимости, поэтому, пожалуйста, попробуйте мою исправленную версию класса HttpCompressionModule, размещенную на той же странице.

0 голосов
/ 16 июня 2019

Несмотря на хакерство, вы можете обойти WCF, используя исходный Content-Length даже после распаковки запроса, установив приватное поле _contentLength в классе HttpRequest с помощью отражения. Используя код Джоанн Верморель:

    void BeginRequest(object sender, EventArgs e)
    {
        var app = (HttpApplication)sender;

        if ("gzip" == app.Request.Headers["Content-Encoding"])
        {
            app.Request.Filter = new GZipStream(
                app.Request.Filter, CompressionMode.Decompress);

            // set private _contentLength field with new content length after the request has been decompressed
            var contentLengthProperty = typeof(HttpRequest).GetField("_contentLength", BindingFlags.NonPublic | BindingFlags.Instance);
            contentLengthProperty.SetValue(app.Request, (Int32)app.Request.InputStream.Length);
        }
    }
...