WCF Content-Length HTTP header on outbound message
Asked Answered
M

3

3

I'm in a tough situation in which a Java web service endpoint hosted on an IBM HTTP Server (IHS) requires a Content-Length header, although it supposedly conforms to HTTP/1.1. If I send the header, everything works. If I leave it off, I get a 500 error response informing me that my POST entity body was empty (even though it was not).

We've invested significant time into our WCF client for these services (developed by a third party) and I can't seem to find a good way to append a Content-Length header to the request. I am able to add arbitrary headers (i.e. X-Dan-Lynn-Header) to the request using an IClientMessageInspector as described in blog posts like this, but WCF seems to ignore a Content-Length header.

My options are:

a) figure out how to force WCF to append a Content-Length header to the HTTP POST request or,

b) find or write an extremely simple-yet-transparent HTTP proxy that decorates the request with a Content-Length header.

Thanks!

Sample 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;
}

Sample request generated by WCF (and the preceding 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>
Marla answered 2/9, 2009 at 0:18 Comment(2)
Is it using a different header like "Transfer-Encoding: chunked" or something like that? The lack of a Content-Length header might indicate that you're streaming the requests, etc.Bigotry
Perhaps the chunked header is causing the problem. I'll investigate and reportMarla
M
5

Figured it out. Setting the binding to use transferMode="Streamed" was causing a Transfer-Encoding: chunked. We needed streamed transfers due to very large responses from the web service, so I was able to go with:

Bad:

transferMode="Streamed"

Good:

transferMode="StreamedResponse"

Changing the binding to this solved the problem:

<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>
Marla answered 2/9, 2009 at 1:21 Comment(2)
thanks for sharing your solution - but could you explain what about this binding you changed? Did you change to "basicHttpBinding"? From what? Just interested to document these things for other folks who might run into the same (or similar) problems!Lawlor
I was using basicHttpBinding from the onset, but it was previously set to transferMode="Streamed". This causes the binding to treat both requests and responses as streamd (aka chunked). The IBM HTTP Server configuration was throwing errors for a chunked Transfer-EncodingMarla
D
1

I am not currently able to actually try to run the code to see what happens but something like

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;      
}

see http://msdn.microsoft.com/en-us/library/aa395196.aspx for more information on how you can use the OperationContextScope object to include additional headers.

update: I do have to say I find this a strange issue. I wonder why the content length isn't being set. I wouldn't be surprissed if your actual problem is somewhere else.

Deadeye answered 2/9, 2009 at 0:34 Comment(0)
C
0

transferMode=StreamedResponse in the app.config helped me too for an issue similar to yours. I had a WCF architecture for Sync Framework and Squid proxy 3.1.20 didn't like the Streamed transferMode Many thanks !

Catholicity answered 5/3, 2015 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.