Bug 46709 - Expect: 100-continue to an HTTP/1.0 server change Breaks .NET Web Services
Summary: Expect: 100-continue to an HTTP/1.0 server change Breaks .NET Web Services
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy (show other bugs)
Version: 2.5-HEAD
Hardware: PC Linux
: P2 regression with 5 votes (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
Depends on:
Reported: 2009-02-12 15:38 UTC by Ian Reynolds
Modified: 2013-08-12 21:56 UTC (History)
0 users

Add support to completely ignore an "Expect: 100-continue" if env "ignorecontinue" is set (805 bytes, patch)
2009-11-06 05:45 UTC, Sven Mueller
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ian Reynolds 2009-02-12 15:38:45 UTC
Our environment uses a HTTP 1.1 mod_proxy server with 1.0 back-end webs. This is for various compatibility reasons, but in order to make this arrangement work in versions of Apache after 2.2.10 due to this change:
*) mod_proxy_http: Do not forward requests with 'Expect: 100-continue' to
     known HTTP/1.0 servers. Return 'Expectation failed' (417) instead.
     [Ruediger Pluem]

This change breaks .NET web service clients that use Expect: 100-continue by default when initiating a session. To Replicate, attempt to connect to a proxy setup similar to the one mentioned above with any web service url hosted by a back-end web. The connection will fail due to the Expectation failed response. Regardless of what the RFC declares, this worked previous to the change. We have been patching manually just by applying the below simple patch:

--- mod_proxy_http.c.orig       2009-02-12 18:35:55.000000000 -0500
+++ mod_proxy_http.c    2009-02-12 18:35:26.000000000 -0500
@@ -703,10 +703,11 @@
          * According to RFC 2616 8.2.3 we are not allowed to forward an
          * Expect: 100-continue to an HTTP/1.0 server. Instead we MUST return
-         */
+         * Disabled for .NET clients
         if (r->expecting_100) {
             return HTTP_EXPECTATION_FAILED;
+         */
     } else {
         buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
Comment 1 Nick Kew 2009-02-12 16:29:29 UTC
If you need the 100-response, why do you tell it to talk HTTP/1.0 to the backend?

The behaviour you describe is not a bug, and the change you identify is a bug fix.  It may very well be that you have a legitimate need for different behaviour, but you should at least tell us why you can't just use HTTP/1.1.  The place for that would be the mailinglist, not bugzilla.

I'll leave this open, in case you want to clarify the above and turn this into an enhancement request.
Comment 2 Sven Mueller 2009-11-06 05:45:21 UTC
Created attachment 24500 [details]
Add support to completely ignore an "Expect: 100-continue" if env "ignorecontinue" is set

We had a very similar issue, also with .NET clients.
As we have only relatively few clients affected by the problem (more detailed description below), and those clients always come from the same IP, we were able to solve the problem by the attached patch and setting the new "ignorecontinue" environment variable for those clients.

Now to the problem itself:

In our case, the relevant URL is protected by HTTP basic auth. .Net clients send the following header in our case:

>>>> CLIENT ----
POST /url HTTP/1.1
Content-Type: text/xml
Content-Length: 1113
Expect: 100-continue
Connection: Keep-Alive
Host: host.do.main

<<<< CLIENT ----

At this point, apache httpd (2.2.3 with patches from RedHat 5.4, but I saw no relevant changes up to the current 2.2.14) reacts like requested by the client:
It responds immediately with an error code, in this case:

>>>> SERVER  ----
HTTP/1.1 401 Authorization Required
Date: Wed, 04 Nov 2009 10:24:52 GMT
Server: Apache
WWW-Authenticate: Basic realm="Our Gateway"
Last-Modified: Thu, 17 Sep 2009 08:52:08 GMT
ETag: "23-473c221659e00"
Accept-Ranges: bytes
Content-Length: 35
Keep-Alive: timeout=15, max=10
Connection: Keep-Alive
Content-Type: text/html

This is an error page
<<<< SERVER ----

Problem here is that .Net can't handle this the way it should, the .Net client actually keeps going by sending the body of the request, immediately followed by the authenticated copy of the first request

>>>> CLIENT  ----
<?xml version="1.0" encoding="UTF-8"?>
POST /url HTTP/1.1
Content-Type: text/xml
Authorization: Basic <zensiert>
Content-Length: 1113
Expect: 100-continue
Host: host.do.main

<?xml version="1.0" encoding="UTF-8"?>
<<<< CLIENT ----

Which httpd interprets as being a request of type:
Which is obviously not a valid request, so httpd returns code 400

For some clients, it seems to help to simply disable keepalive (setenv nokeepalive), but for some others, this only results in no authenticated request being sent at all.

So we tried several workarounds:
1) Use any combination of the typical MSIE workaround settings, including
   unclean ssl shutdown, downgrade-1.0, force-response-1.0. This resulted
   in varying errors, mostly having just a single request come in, for which
   code 401 was returned, then no other request following.
2) Return 417 if we knew it was a problematic customer and the Expect header
   was set. This also just resulted in no further request coming in (no matter
   wether nokeepalive was set or not).

Finally, I tried patching the httpd to allow to simply ignore the Expect header from the known-bad clients. The resulting patch is attached. Please note that I'm in no way an apache httpd expert, so the formating might be non-standard and - more importantly - the logging I added might be wrong (ap_log_rerror might be more correct than ap_log_error).

Anyway, I think the patch might be off use for others as well, and I would be glad to see something similar in a future httpd release. 

I don't think anyone would thing copyright might apply to this simple patch, but just in case anyone is insane enough to do so, I hereby grant all rights related to this patch to the apache foundation. I also release the "code" under the apache license, the GNU (L)GPL (v2 or higher) or the BSD copyright (without the advertisement clause), at the recipients choice.
Comment 3 Nick Kew 2009-12-07 10:13:29 UTC
Comment 2 describes PR 47087.  Are you in a position to test-drive that patch?

*** This bug has been marked as a duplicate of bug 47087 ***
Comment 4 Christoph Anton Mitterer 2013-08-12 21:56:14 UTC
I see the same (version 2.2.22)... having a HTTP 1.0 only backend with force-proxy-request-1.0 set.

The client sends an "Expect: 100-continue" Apache (correctly follows the RFC) and returns 417.

I don't say that this is a bug in Apache, since AFAIU it does what the RFC says but rather from the clients...

And even if one would unset force-proxy-request-1.0 it wouldn't really make things better, since while it would work then, the RFC would be more or less broken ... or at least the functionality of "Expect: 100-continue" wouldn't work.

The only solution right now seems to strip the header, which is IMHO not very nice though, as Expect may get further use (even if right now only 100-continue is defined).

Therefore, can re-opening this with the question whether you can reconsider the patch from comment #2.

It would allow to only ignore 100-continue, and not any other future values for Expect: .