asp.net webservice обработка сжатого gzip запроса - PullRequest
9 голосов
/ 07 декабря 2010

У меня есть веб-сервис asp.net .asmx, написанный для обработки запросов от стороннего инструмента.Сторонний инструмент отправляет HTTP-запрос POST веб-службе для получения информации о пользователе.Я использую IIS7

Запуск Fiddler с проверкой «Удалить все кодировки», я вижу вызов веб-службы и все работает правильно.Если снять флажок «Удалить все кодировки», вызов веб-службы завершится с ошибкой 400.Различие, которое я вижу, состоит в том, что заголовок «Content-Encoding: gzip» удаляется Fiddler, а содержимое распаковывается.

Итак, когда заголовок Content-Encoding удаляется, а содержимое распаковывается, мойвеб-сервис работает отлично.Когда присутствует заголовок и содержимое сжато, веб-служба перестает работать.

Как я могу:

  1. настроить мой веб-сервис так, чтобы он говорил клиенту, что он не будет принимать сжатые запросы(и надеюсь, что сторонний инструмент это учитывает)
  2. Распаковывает содержимое на ранней стадии обработки asp.net
  3. Измените мой веб-сервис для работы со сжатыми данными

Обновление : Для ясности, мне не нужно настраивать кодировку gzip в ответе, мне нужно иметь дело с запросом к моему веб-сервису, который закодирован gzip.

Обновление2 : сторонним инструментом является плагин Salesforce.com Outlook.Таким образом, у меня нет доступа, чтобы изменить его, и он используется многими другими компаниями без проблем.Это должно быть то, что я делаю (или не делаю)

Обновление 3 : я нашел один пост здесь , в котором говорится, что IIS не поддерживает входящие POST-запросысо сжатыми данными он поддерживает только сжатые ответы.Может ли это все еще быть правдой?

Ответы [ 5 ]

5 голосов
/ 04 января 2013

Самый простой метод - создать HttpModule, который заменит фильтр запроса. Он более пригоден для повторного использования и позволяет избежать использования Global.asax. Также нет необходимости создавать новый класс потока распаковки, так как GZipStream готов к этому. Вот полный код, который также удаляет Content-Encoding: gzip, который больше не нужен:

public class GZipRequestDecompressingModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, e) =>
        {
            var request = (sender as HttpApplication).Request;

            string contentEncoding = request.Headers["Content-Encoding"];

            if (string.Equals(contentEncoding, "gzip",
                StringComparison.OrdinalIgnoreCase))
            {
                request.Filter = new GZipStream(request.Filter,
                    CompressionMode.Decompress);
                request.Headers.Remove("Content-Encoding");
            }
        };
    }
    public void Dispose()
    {
    }
}

Чтобы активировать этот модуль, добавьте в ваш web.config следующий раздел:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="AnyUniqueName"
            type="YourNamespace.GZipRequestDecompressingModule, YourAssembly"
            preCondition="integratedMode" />
    </modules>
</system.webServer>
2 голосов
/ 09 декабря 2010

Так как сторонний сервис просто отправляет вам POST, я не думаю, что можно сказать им не отправлять сжатый.

Вы можете попробовать переопределить GetWebRequest и распаковать его по пути в

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol

{
protected override WebRequest GetWebRequest(Uri uri)
{
    base.GetWebRequest(uri);request.AutomaticDecompression = System.Net.DecompressionMethods.GZip;
    return request;
}
}
1 голос
/ 13 декабря 2010

Я нашел частичный ответ здесь .

class DecompressStream : Stream
{
    ...

    public override int Read(byte[] buffer, int offset, int count)
    {
        GZipStream test = new GZipStream(_sink, CompressionMode.Decompress);

        int c = test.Read(buffer, offset, count);

        return c;
    }

    ...
}

Затем я могу указать фильтр для объекта запроса следующим образом:

void Application_BeginRequest(object sender, EventArgs e)
    {
        string contentEncoding = Request.Headers["Content-Encoding"];
        Stream prevCompressedStream = Request.Filter;

        if(contentEncoding == null || contentEncoding.Length == 0)
            return;

        contentEncoding = contentEncoding.ToLower();

        if(contentEncoding.Contains("gzip"))
        {
            Request.Filter = new DecompressStream(Request.Filter);
        }
    }

Iскажем частичный ответ, потому что, хотя теперь я могу обработать входящий запрос, ответ получает заголовок «Content-Encoding: gzip», даже если ответ не закодирован.Я могу проверить в Fiddler, что содержимое не закодировано.

Если я закодирую ответ, произойдет сбой клиента для веб-службы.Кажется, что даже при отправке «Accept-Encoding: gzip» он фактически не принимает сжатый gzip ответ.Я могу проверить в Fiddler, что ответ сжат, и Fiddler успешно распакует его.

Итак, я застрял, пытаясь удалить блуждающий заголовок «Content-Encoding: gzip» из ответа.Я удалил все ссылки, которые могу найти на сжатие, из приложения, web.config и IIS.

1 голос
/ 09 декабря 2010

Я не уверен, что IIS поддерживает распаковку входящих запросов, поэтому, возможно, это придется делать дальше по трубе.

Ответ Шираз может сработать, и это будет первое, что я попробую.

Если это не сработает, вы можете подумать о переключении службы сервера .asmx на WCF, что немного сложнее в настройке, но и обеспечивает большую гибкость.

На стороне WCF естьдве вещи, которые я могу предложить.Первый довольно прост в реализации и основан на настройке объекта WebRequest, используемого WCF, для автоматического принятия сжатия.Вы можете найти детали здесь .Этот вариант является эквивалентом WCF решения, предложенного Ширазом.

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

Пожалуйста, дайте мне знать, если это помогло или вам нужна дополнительная помощь.

1 голос
/ 07 декабря 2010

Сжатие GZIP является функцией сервера.

Если вы используете IIS6, обратитесь к по этой ссылке .

Если вы используете IIS7, вы можетеиспользуйте ISAPI_Rewrite, чтобы отключить gzip.См. эту ссылку .

Тем не менее, поскольку gzip является функцией IIS, вам действительно не нужно делать ничего «особенного», чтобы заставить его работать с веб-службой (IISдолжен обрабатывать распаковку и сжатие запросов).Надеемся, что эта информация поможет вам в дальнейшем устранении неполадок и решении проблемы.

...