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

Dan*_*ynn 3 wcf wcf-client http-content-length http-headers

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

我们为这些服务(由第三方开发)在 WCF 客户端上投入了大量时间,但我似乎找不到将 Content-Length 标头附加到请求的好方法。我可以使用 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;
}

Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

Dan*_*ynn 5

弄清楚了。将绑定设置为使用 transferMode="Streamed" 会导致 Transfer-Encoding: chunked。由于来自 Web 服务的响应非常大,我们需要流式传输,因此我能够使用:

坏的:

transferMode="Streamed"
Run Code Online (Sandbox Code Playgroud)

好的:

transferMode="StreamedResponse"
Run Code Online (Sandbox Code Playgroud)

将绑定更改为 this 解决了问题:

<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>
Run Code Online (Sandbox Code Playgroud)