Сжатие HttpWebRequest с помощью gzip
Я разрабатываю .NET 4.0
Консольное приложение в качестве SOAP Web Service
клиент, который будет отправлять данные (POST) сторонним лицам. У меня нет контроля над веб-службой на стороне сервера. Сторонние предоставили WSDL's
использовать, и я смог импортировать их и использовать их с разумным успехом. Однако существует требование сжать сообщение запроса, используя gzip
и я не мог на всю жизнь понять, как это сделать, используя прокси-сервисы.
Эта тема на SO привела меня к мысли, что без контроля над клиентским и серверным кодом запрос не может быть сжат. В результате этого я написал код в своем приложении, чтобы вручную создать SOAP XML
в XDocument
объект; затем заполнил значения из WSDL
объекты прокси-класса, которые я ранее кодировал в своем клиентском приложении.
Первым требованием для этого клиента является отправка сжатого сообщения через gzip
, После некоторого исследования я увидел ответы так же просто, как просто добавить HttpRequestHeader.AcceptEncoding, "gzip, deflate"
в заголовок запроса. К сожалению, это не помогло.
В настоящее время сертификат, который я получаю, не является настоящим сертификатом. Я пытаюсь сделать код как можно более надежным, прежде чем развертывать его в тестовой среде для проведения реального тестирования сервиса.
- Есть ли способ сжать запрос через вызов прокси (
wsdl
)? - Есть ли что-то, что мне не хватает, чтобы правильно сжать
HttpWebRequest
? - Может ли быть что-то еще не так, что приведет к возвращению сообщения об ошибке?
Я ожидаю, что другое сообщение, относящееся к аутентификации, будет недействительным, если сам запрос будет в порядке. - Есть ли способ сжатия может быть сделан через
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)". Не могу точно сказать, как этот параметр конструктора повлияет на поток веб-запросов.