使用 gzip 压缩 HttpWebRequest

Compress a HttpWebRequest using gzip

我正在开发一个 .NET 4.0 控制台应用程序作为 SOAP Web Service 客户端,它将数据 (POST) 发送到 third-party。我无法控制 server-side 上的 Web 服务。 third-party 确实提供了 WSDL's 供使用,我能够导入它们并成功使用它们。但是,需要使用 gzip 压缩请求消息,而我终究无法弄清楚如何使用代理服务来压缩请求消息。

This topic 在这里,让我相信如果不能同时控制客户端和服务器代码,就无法压缩请求。由于这一发现,我在我的应用程序中编写了代码,以在 XDocument object 中手动创建 SOAP XML;然后,填充 WSDL 代理 class object 中的值,我之前已对客户端应用程序进行编码以使用这些值。

此客户端的第一个要求是发送通过 gzip 压缩的消息。经过一些研究,我发现答案很简单,只需将 HttpRequestHeader.AcceptEncoding, "gzip, deflate" 添加到请求 header 即可。不幸的是,这样做似乎没有用。

目前,我正在检索的证书不是真正的证书。在部署到测试环境以进行实际服务测试之前,我正在尝试使代码尽可能合理。

  1. 有没有办法通过代理调用 (wsdl) 压缩请求?
  2. 为了正确压缩 HttpWebRequest 我是否遗漏了什么?
  3. 是否有其他错误导致返回错误消息?
    如果请求本身没问题,我希望与身份验证有关的不同消息无效
  4. 有没有办法通过 app.config 完成压缩?

下一组要求我对如何handle/what有点困惑。假设我已将请求的 ContentType 设置为什么,我应该如何(以及添加什么)才能将 content-transfer-encoding 部分添加到请求中?如果ContentType不正确,我应该如何添加这些信息?

The content type for the SOAP Evenlope with MTOM encoded attachment must be "application/xop+xml" and the content-transfer-encoding must be 8-bit.

我已经对下面的代码进行了几次迭代,但是,我相信相关片段是最简单形式的代码。如果还有其他有用的信息,请告诉我。

创建 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());
        }
    }
}

收到错误消息:

The request message must be sent using HTTP compression (RFC 1952 - GZIP).

使用以下代码代替您当前的代码发送请求。

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

编辑:可能需要使用 "new GZipStream(stream, CompressionMode.Compress, true)"。不能确定该构造函数参数将如何影响 Web 请求流。

我想我可以通过将以下内容添加到 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;
}