On Sun, 3 Jul 2011, Daniel Stenberg wrote:

https://sourceforge.net/tracker/?func=detail&aid=3352341&group_id=976&atid=100976

Great. I'm working on this, a bit slowly due to vacation times here...

Hey,

Here's a patch attached that seems to work for my test cases I've made up for this. It'd be great to hear how it works against your live case...

--

 / daniel.haxx.se
From 3548d762c90d2e807fd6ba7e254c4a130fea83d6 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <[email protected]>
Date: Mon, 4 Jul 2011 22:16:07 +0200
Subject: [PATCH 1/3] expect 100: correct handling of error responses when
 posting data

When libcurl has said to the server that there's a POST or PUT coming
(with a content-length and all) it has to either deliver that amount of
data or it needs to close the connection before trying a second request.

Adds test case 1129.

Bug: http://curl.haxx.se/mail/lib-2011-06/0191.html
Reported by: Steven Parkes
---
 lib/http.c          |   60 ++++++++++++++++++++++++-------
 lib/urldata.h       |    6 +++-
 tests/data/test1129 |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 148 insertions(+), 15 deletions(-)
 create mode 100644 tests/data/test1129

diff --git a/lib/http.c b/lib/http.c
index 92f7c02..4d1d072 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -416,15 +416,15 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
     /* This is not NTLM or NTLM with many bytes left to send: close
      */
     conn->bits.close = TRUE;
-    data->req.size = 0; /* don't download any more than 0 bytes */
-
     /* There still is data left to send, but this connection is marked for
        closure so we can safely do the rewind right now */
   }
 
-  if(bytessent)
+  if(bytessent) {
     /* we rewind now at once since if we already sent something */
+    conn->rewindcount += bytessent;
     return Curl_readrewind(conn);
+  }
 
   return CURLE_OK;
 }
@@ -480,6 +480,10 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
       code = http_perhapsrewind(conn);
       if(code)
         return code;
+      if(conn->bits.close)
+        /* if asked to close the connection, we don't download anymore
+           data either */
+        data->req.size = 0;
     }
   }
 
@@ -2779,17 +2783,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
         }
       }
 
-      if(417 == k->httpcode) {
-        /*
-         * we got: "417 Expectation Failed" this means:
-         * we have made a HTTP call and our Expect Header
-         * seems to cause a problem => abort the write operations
-         * (or prevent them from starting).
-         */
-        k->exp100 = EXP100_FAILED;
-        k->keepon &= ~KEEP_SEND;
-      }
-
       /*
        * When all the headers have been parsed, see if we should give
        * up and return an error.
@@ -2829,6 +2822,41 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
         if(result)
           return result;
 
+        if(!data->req.newurl && /* a new request is not already fixed */
+           !conn->rewindcount && /* not rewound yet */
+           (data->state.expect100header && (k->httpcode >= 300))) {
+          /*
+           * General, not specific, treatment of errors including : "417
+           * Expectation Failed", while waiting for 100.
+           */
+
+          data->state.expect100header = FALSE; /* no more */
+          switch(data->set.httpreq) {
+          case HTTPREQ_PUT:
+          case HTTPREQ_POST:
+          case HTTPREQ_GET:
+          case HTTPREQ_POST_FORM:
+            /* we got an error response while waiting for 100, now if we said
+               we'd POST or PUT we might have a request body to handle */
+            result = http_perhapsrewind(conn);
+            if(result)
+              return result;
+            if(!conn->bits.close)
+              /* enable the write bit, we're not waiting anymore */
+              k->keepon |= KEEP_SEND;
+            else {
+              /* stop the sending, but keep reading the response */
+              k->upload_done = TRUE;
+              k->exp100 = EXP100_FAILED;
+              k->keepon &= ~KEEP_SEND;
+            }
+
+            break;
+          default: /* default label present to avoid compiler warnings */
+            break;
+          }
+        }
+
         if(conn->bits.rewindaftersend) {
           /* We rewind after a complete send, so thus we continue
              sending now */
@@ -3312,6 +3340,10 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
           result = http_perhapsrewind(conn);
           if(result)
             return result;
+          if(conn->bits.close)
+            /* if asked to close the connection, we don't download anymore
+               data either */
+            data->req.size = 0;
         }
       }
     }
diff --git a/lib/urldata.h b/lib/urldata.h
index d256968..0f755dc 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -534,7 +534,7 @@ struct SingleRequest {
 
   curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
                              -1 means unlimited */
-  curl_off_t *writebytecountp; /* return number of bytes written or NULL */
+  curl_off_t *writebytecountp;  /* return number of bytes written or NULL */
 
   curl_off_t bytecount;         /* total number of bytes read */
   curl_off_t writebytecount;    /* number of bytes written */
@@ -894,6 +894,10 @@ struct connectdata {
   curl_seek_callback seek_func; /* function that seeks the input */
   void *seek_client;            /* pointer to pass to the seek() above */
 
+  curl_off_t rewindcount;       /* counts how many bytes that were sent and
+                                   then rewound back so that they can be sent
+                                   again */
+
   /*************** Request - specific items ************/
 
   /* previously this was in the urldata struct */
diff --git a/tests/data/test1129 b/tests/data/test1129
new file mode 100644
index 0000000..85793cb
--- /dev/null
+++ b/tests/data/test1129
@@ -0,0 +1,97 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+Expect: 100-continue
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 404 NOOOOOOOOO

+Date: Thu, 09 Nov 2010 14:49:00 GMT

+Server: test-server/fake

+Content-Length: 6
+Content-Type: text/html
+
+-foo-
+</data>
+
+<data1>
+HTTP/1.1 404 NEITHER

+Date: Thu, 09 Nov 2010 14:49:00 GMT

+Server: test-server/fake

+Content-Length: 6
+Content-Type: text/html
+
+-foo-
+</data1>
+
+# we use skip to make the test server never read the full payload off
+# the socket and instead return the response at once 
+<servercmd>
+skip: 1025
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# 1025 x 'x'
+<file name="log/file1129">
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+</file>
+<server>
+http
+</server>
+ <name>
+HTTP POST expect 100-continue with a 404
+ </name>
+ <command option="no-output">
+-d @log/file1129 http://%HOSTIP:%HTTPPORT/1129 http://%HOSTIP:%HTTPPORT/11290001
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout>
+HTTP/1.1 404 NOOOOOOOOO

+Date: Thu, 09 Nov 2010 14:49:00 GMT

+Server: test-server/fake

+Content-Length: 6
+Content-Type: text/html
+
+-foo-
+HTTP/1.1 404 NEITHER

+Date: Thu, 09 Nov 2010 14:49:00 GMT

+Server: test-server/fake

+Content-Length: 6
+Content-Type: text/html
+
+-foo-
+</stdout>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+POST /1129 HTTP/1.1

+Host: %HOSTIP:%HTTPPORT

+Accept: */*

+Content-Length: 1025

+Content-Type: application/x-www-form-urlencoded

+Expect: 100-continue

+

+POST /11290001 HTTP/1.1

+Host: %HOSTIP:%HTTPPORT

+Accept: */*

+Content-Length: 1025

+Content-Type: application/x-www-form-urlencoded

+Expect: 100-continue

+

+</protocol>
+</verify>
+</testcase>
-- 
1.7.5.4

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to