Expect: 100-Continue issue with WebClient Class in .Net 2.0.

We're using the WebClient Class (2.0.50727) to POST soap transactions to a Web Service which requires authentication.

It appears that the client is issuing the "Expect: 100-Continue" header correctly but then not appropriately handling the "100-Continue" response from the server (IIS 6).

The following code will reproduce the behavior:

Dim _WebClient asNew WebClient

_WebClient.Credentials =New NetworkCredential("User", "Password","Domain")

_WebClient.Headers.Add(HttpRequestHeader.UserAgent,"USERAGENTSTRING")

_WebClient.Headers.Add("SOAPAction", Chr(34) &http://tempURI.org/Command & Chr(34))

_WebClient.Headers.Add("Content-Type","text/xml; charset=utf-8")

_WebClient.UploadString(_Uri, _BodyData)

This request results in multiple data POST's to the web server. This behavior has reproduced itself in every configuration we've tried.

The network capture stream is included below.

- Client traffic is in Green

- Server traffic is in Blue

- The POST body of the first request (which to my knowledge shouldn't be sent until after the "100-Continue"

--

POST /path/to/file.php HTTP/1.1

SOAPAction: "http://tempURI.org/Command"

Content-Type: text/xml; charset=utf-8

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.832)

Host: XXX.XXX.XXX.XXX

Content-Length: 426

Expect: 100-continue

Connection: Keep-Alive

HTTP/1.1 401 Unauthorized

Content-Length: 1656

Content-Type: text/html

Server: Microsoft-IIS/6.0

WWW-Authenticate: Basic realm="XXX.XXX.XXX.XXX"

X-Powered-By: ASP.NET

Date: Wed, 01 Aug 2007 23:35:48 GMT

<HTML>*ERROR TEXT DELETED*</HTML>

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns: soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<soap:Body>

<command xmlns="http://tempURI.org/service">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

</command>

</soap:Body>

</soap:Envelope>

POST /path/to/file.php HTTP/1.1

SOAPAction: "http://tempURI.org/command"

Content-Type: text/xml; charset=utf-8

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.832)

Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Host: XXX.XXX.XXX.XXX

Content-Length: 426

Expect: 100-continue

HTTP/1.1 100 Continue

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns: soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<soap:Body>

<command

xmlns="http://tempURI.org/service">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

</command>

</soap:Body>

</soap:Envelope>

--
[7598 byte] By [`Andrew] at [2008-1-7]
# 1
Well 100 Continue is a bit of a mess, see RFC 2616 section 8.2.3 etc:

Because of the presence of older implementations, the protocol allows
ambiguous situations in which a client may send "Expect: 100-
continue" without receiving either a 417 (Expectation Failed) status
or a 100 (Continue) status. Therefore, when a client sends this
header field to an origin server (possibly via a proxy) from which it
has never seen a 100 (Continue) status, the client SHOULD NOT wait
for an indefinite period before sending the request body.

Really the 100 Continue mechanism is to enable the client not to send huge payloads up to the server if the server knows it can't process the request. However if the POST payload is small then its best to send it rather than wait for the 100 Continue or error to arrive which due to round-trip latencies could be a 'long' time. Its a case of optimize for the normal case -- where the downside is not great: the waste of bandwidth is small.

I think this is implied by the RFC:

[...] In some cases, it might either be inappropriate or highly
inefficient for the client to send the body if the server will reject
the message without looking at the body.

AlanJ.McFarlane at 2007-10-2 > top of Msdn Tech,.NET Development,.NET Framework Networking and Communication...
# 2

Yes, and thank you for the response. I'm aware that of the various scenarios and that in some cases it should attempt to send the data in advance of the 100-Continue. As for our test environment there is no proxy to muddle the issue.

I realize the testing capture I posted contained a relatively small post body. However the actual operational messages are significantly larger. To facilitate testing if post size was the cause I built a test app that allowed for a configurable body size to see if I could identify any size threshold where the request would start acting as expected.

However even when sending a 10 meg post body to the server it was still sent twice. As it stands in order to minimize wasted bandwidth we're having to implementing an empty server request to complete authentication prior to the post body to mitigate this issue.

Ideally I'm hoping to identify if it's an environmental issue, something perhaps security related that could cause this behavior consistently or if the client just always works this way.

`Andrew at 2007-10-2 > top of Msdn Tech,.NET Development,.NET Framework Networking and Communication...
# 3
Ahh right. :-,) Well I don't know whether that's the normal behaviour. Maybe someone from Microsoft could help?
AlanJ.McFarlane at 2007-10-2 > top of Msdn Tech,.NET Development,.NET Framework Networking and Communication...

.NET Development

Site Classified