【问题标题】:Compress a HttpWebRequest using gzip使用 gzip 压缩 HttpWebRequest
【发布时间】:2016-03-09 09:55:20
【问题描述】:

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

This topic 在这里,让我相信如果无法控制客户端和服务器代码,则无法压缩请求。作为这个发现的结果,我在我的应用程序中编写了代码以在XDocument 对象中手动创建SOAP XML;然后,填充来自WSDL 代理类对象的值,我之前编写了我的客户端应用程序以供使用。

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

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

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

我对如何处理/做什么有点困惑。假设我已经将请求的ContentType 设置为,我应该如何(以及)添加什么以便将content-transfer-encoding 添加到请求中?如果ContentType 不正确,我应该如何添加此信息?

带有 MTOM 编码附件的 SOAP Evenlope 的内容类型必须是“application/xop+xml”,并且内容传输编码必须是 8 位。

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

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) 发送请求消息。

【问题讨论】:

    标签: c# soap gzip soap-client irs


    【解决方案1】:

    我想我可以通过在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;
    }
    

    【讨论】:

    • 啊哈,看起来像是另一个基于约定的编程示例。我鄙视基于约定的,因为它非常不直观。要么你知道要添加什么魔法属性,要么你不知道。我曾经花了一天的时间把头撞在桌子上试图弄清楚为什么我在 ASP.NET 中创建的控制器不起作用,直到我意识到类名 - 必须 - 以“Controller”结尾(如在 MyClassController 中)或ASP.NET 无法识别它......即使它继承自 Controller。好痛苦。
    【解决方案2】:

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

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

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

    【讨论】:

    • 首先,感谢您的回复。不幸的是,使用 true 或 false 作为构造函数参数会导致 WebException 输出相同的错误消息。
    • 很奇怪。我得检查一下我过去写的代码。
    • 查看我对克服错误所必须做的事情的回应。我还保留了您的建议,并在HttpWebResponse 上添加了CompressionMode.Decompress
    猜你喜欢
    • 2013-10-01
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 2015-07-14
    • 2012-06-17
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多