Сжатие HttpWebRequest с помощью gzip

Я разрабатываю .NET 4.0 Консольное приложение в качестве SOAP Web Service клиент, который будет отправлять данные (POST) сторонним лицам. У меня нет контроля над веб-службой на стороне сервера. Сторонние предоставили WSDL's использовать, и я смог импортировать их и использовать их с разумным успехом. Однако существует требование сжать сообщение запроса, используя gzipи я не мог на всю жизнь понять, как это сделать, используя прокси-сервисы.

Эта тема на SO привела меня к мысли, что без контроля над клиентским и серверным кодом запрос не может быть сжат. В результате этого я написал код в своем приложении, чтобы вручную создать SOAP XML в XDocument объект; затем заполнил значения из WSDL объекты прокси-класса, которые я ранее кодировал в своем клиентском приложении.

Первым требованием для этого клиента является отправка сжатого сообщения через gzip, После некоторого исследования я увидел ответы так же просто, как просто добавить HttpRequestHeader.AcceptEncoding, "gzip, deflate" в заголовок запроса. К сожалению, это не помогло.

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

  1. Есть ли способ сжать запрос через вызов прокси (wsdl)?
  2. Есть ли что-то, что мне не хватает, чтобы правильно сжать HttpWebRequest?
  3. Может ли быть что-то еще не так, что приведет к возвращению сообщения об ошибке?
    Я ожидаю, что другое сообщение, относящееся к аутентификации, будет недействительным, если сам запрос будет в порядке.
  4. Есть ли способ сжатия может быть сделан через app.config?

Следующий набор требований Я немного запутался в том, как справляться / что делать. При условии, что я установил ContentType запроса, как (и что) мне добавить, чтобы добавить content-transfer-encoding кусок к запросу? Если ContentType неверно, как мне добавить эту информацию?

Тип содержимого для SOAP Evenlope с вложением в кодировке MTOM должен быть "application/xop+xml", а кодирование передачи содержимого должно быть 8-разрядным.

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

Метод для создания HttpWebRequest:

private static HttpWebRequest CreateWebRequest(SoapAction action)
{
    string url = GetUrlAddress(action);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

    request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
    request.Headers.Add("SOAPAction", action.ToString());
    request.ContentType = "application/xop+xml";
    request.Accept = "text/xml";
    request.Method = "POST";

    request.ClientCertificates.Add(/* Retrieve X509Certificate Object*/);

    return request;
}

Код для отправки запроса:

using (Stream stream = request.GetRequestStream())
{
    soapXml.Save(stream);
}

Код для получения ответа:
Вот как я получаю сообщение об ошибке, которая происходит

try
{
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        using (StreamReader reader = new StreamReader(response, Encoding.Default))
        {
            File.AppendAllText(filePath, response.Headers.ToString());
            File.AppendAllText(filePath, reader.ReadToEnd());
        }
    }
}
catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    {
        using (var reader = new StreamReader(stream))
        {
            Console.WriteLine(reader.ReadToEnd());
        }
    }
}

Получено сообщение об ошибке:

Сообщение с запросом должно быть отправлено с использованием сжатия HTTP (RFC 1952 - GZIP).

2 ответа

Решение

Я думаю, что мне удалось решить сообщение об ошибке сжатия, добавив следующее к HttpWebRequest метод:

request.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip"); 

Обновленный метод для создания HttpWebRequest:

private static HttpWebRequest CreateWebRequest(SoapAction action)
{
    string url = GetUrlAddress(action);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

    request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
    request.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip"); 
    request.Headers.Add("SOAPAction", action.ToString());
    request.ContentType = "application/xop+xml";
    request.Accept = "text/xml";
    request.Method = "POST";

    request.ClientCertificates.Add(/* Retrieve X509Certificate Object*/);

    return request;
}

Используйте следующую информацию вместо вашего текущего кода для отправки запроса.

using (Stream stream = request.GetRequestStream())
using (GZipStream gz = new GZipStream(stream, CompressionMode.Compress, false))
{
    soapXml.Save(gz);
}

Изменить: Возможно, нужно использовать "новый GZipStream(поток, CompressionMode.Compress, true)". Не могу точно сказать, как этот параметр конструктора повлияет на поток веб-запросов.

Другие вопросы по тегам