出站消息上的WCF内容长度HTTP标头

时间:2009-09-02 00:18:54

标签: wcf http-headers wcf-client http-content-length

我处境艰难,IBM HTTP Server(IHS)上托管的Java Web服务端点需要Content-Length标头,尽管它应该符合HTTP / 1.1。如果我发送标题,一切正常。如果我将其关闭,我会收到500错误响应,通知我我的POST实体主体是空的(即使它不是)。

我们已经为这些服务(由第三方开发)投入了大量时间进入我们的WCF客户端,我似乎无法找到向请求附加Content-Length标头的好方法。我可以使用blog posts like this中描述的IClientMessageInspector向请求添加任意标头(即X-Dan-Lynn-Header),但WCF似乎忽略了Content-Length标头。

我的选择是:

a)弄清楚如何强制WCF将Content-Length标头附加到HTTP POST请求,或者

b)查找或编写一个非常简单但透明的HTTP代理,该代理使用Content-Length标头来装饰请求。

谢谢!

示例IClientMessageInspector.BeforeSendRequest:


public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
    var buffer = request.CreateBufferedCopy(Int32.MaxValue);
    var tempRequest = buffer.CreateMessage();


    HttpRequestMessageProperty httpRequest = GetHttpRequestProp(tempRequest);
    if (httpRequest != null)
    {
        if (string.IsNullOrEmpty(httpRequest.Headers[HttpRequestHeader.ContentLength]))
        {
            httpRequest.Headers.Add(HttpRequestHeader.ContentLength, GetMessageLength(buffer).ToString());
            httpRequest.Headers.Add("X-Dan-Lynn-Header", "abcdefghijk");
        }

    }

    request = tempRequest;
    request.Properties[HttpRequestMessageProperty.Name] = httpRequest;

    return null;
}

WCF(以及前面的IClientMessageInspector)生成的示例请求:

POST /path/to/service HTTP/1.1
Content-Type: text/xml; charset=utf-8
X-Dan-Lynn-Header: abcdefghijk
SOAPAction: "http://tempuri.org/path/to/service/action"
Host: service.host.tld
Transfer-Encoding: chunked
Connection: Keep-Alive


<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        .......body removed for clarity......

    </s:Body>
</s:Envelope>

3 个答案:

答案 0 :(得分:4)

想出来。将绑定设置为使用transferMode =“Streamed”导致Transfer-Encoding:chunked。由于来自Web服务的响应非常大,我们需要流式传输,因此我可以选择:

为:

transferMode="Streamed"

好:

transferMode="StreamedResponse"

更改绑定到此解决了问题:

<basicHttpBinding>
    <binding name="MyBinding" closeTimeout="00:30:00" openTimeout="00:30:00"
      receiveTimeout="00:30:00" sendTimeout="00:30:00" allowCookies="false"
      bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
      maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="16777216"
      messageEncoding="Text" textEncoding="utf-8" transferMode="StreamedResponse"
      useDefaultWebProxy="false">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="65536"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="None" />
    </binding>
  </basicHttpBinding>

答案 1 :(得分:1)

我目前无法真正尝试运行代码来查看会发生什么,但类似

WCFClient client = new WCFClient();
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))    
{     
    HttpRequestMessageProperty req = new HttpRequestMessageProperty();            
    req.Headers.Add("Content-Length", "YOUR CONTENT LENGTH HERE");      
    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = req;      
}

有关如何使用OperationContextScope对象包含其他标头的详细信息,请参阅http://msdn.microsoft.com/en-us/library/aa395196.aspx

<强>更新 我不得不说我发现这是一个奇怪的问题。我想知道为什么没有设置内容长度。如果您的实际问题在其他地方,我不会感到惊讶。

答案 2 :(得分:0)

app.config中的

transferMode = StreamedResponse帮助我解决了与你类似的问题。 我有一个用于Sync Framework的WCF架构和Squid代理3.1.20并不像Streamed transferMode 非常感谢!