aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2011-07-11 23:24:45 +0200
committerDaniel Stenberg <daniel@haxx.se>2011-07-20 00:08:41 +0200
commit3f9b4afdfd7dd3ea16e07af98bb324b9f4277696 (patch)
tree264a369b6475ea128c1d2949ab31d172abb34395 /lib
parentd007c3ca76cf0587a3222279ebda0f3a8727807f (diff)
http error response: stop sending when error is received
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, 1130 and 1131 The bug report is about when used with 100-continue, but the change is more generic. Bug: http://curl.haxx.se/mail/lib-2011-06/0191.html Reported by: Steven Parkes
Diffstat (limited to 'lib')
-rw-r--r--lib/http.c67
-rw-r--r--lib/transfer.c6
2 files changed, 61 insertions, 12 deletions
diff --git a/lib/http.c b/lib/http.c
index bb6af2cb4..5c529231f 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -404,8 +404,10 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
data left to send, keep on sending. */
/* rewind data when completely done sending! */
- if(!conn->bits.authneg)
+ if(!conn->bits.authneg) {
conn->bits.rewindaftersend = TRUE;
+ infof(data, "Rewind stream after send\n");
+ }
return CURLE_OK;
}
@@ -1683,6 +1685,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!data->state.first_host)
return CURLE_OUT_OF_MEMORY;
}
+ http->writebytecount = http->readbytecount = 0;
if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) &&
data->set.upload) {
@@ -2543,6 +2546,17 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_pgrsSetUploadCounter(data, http->writebytecount);
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
+
+ if(http->writebytecount >= postsize) {
+ /* already sent the entire request body, mark the "upload" as
+ complete */
+ infof(data, "upload completely sent off: %" FORMAT_OFF_T "out of "
+ "%" FORMAT_OFF_T " bytes\n",
+ http->writebytecount, postsize);
+ data->req.upload_done = TRUE;
+ data->req.keepon &= ~KEEP_SEND; /* we're done writing */
+ data->req.exp100 = EXP100_SEND_DATA; /* already sent */
+ }
}
return result;
@@ -2814,17 +2828,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.
@@ -2864,6 +2867,46 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
if(result)
return result;
+ if(k->httpcode >= 300) {
+ if((!conn->bits.authneg) && !conn->bits.close &&
+ !conn->bits.rewindaftersend) {
+ /*
+ * General treatment of errors when about to send data. Including :
+ * "417 Expectation Failed", while waiting for 100-continue.
+ *
+ * The check for close above is done simply because of something
+ * else has already deemed the connection to get closed then
+ * something else should've considered the big picture and we
+ * avoid this check.
+ *
+ * rewindaftersend indicates that something has told libcurl to
+ * continue sending even if it gets discarded
+ */
+
+ switch(data->set.httpreq) {
+ case HTTPREQ_PUT:
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ /* We got an error response. If this happened before the whole
+ * request body has been sent we stop sending and mark the
+ * connection for closure after we've read the entire response.
+ */
+ if(!k->upload_done) {
+ infof(data, "HTTP error before end of send, stop sending\n");
+ conn->bits.close = TRUE; /* close after this */
+ k->upload_done = TRUE;
+ k->keepon &= ~KEEP_SEND; /* don't send */
+ if(data->state.expect100header)
+ k->exp100 = EXP100_FAILED;
+ }
+ 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 */
diff --git a/lib/transfer.c b/lib/transfer.c
index 94cd6d6f9..1c2afc4a2 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1043,6 +1043,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(result || *done)
return result;
}
+ else if(k->keepon & KEEP_RECV) {
+ DEBUGF(infof(data, "additional stuff not fine %s:%d: %d %d\n",
+ __FILE__, __LINE__,
+ select_res & CURL_CSELECT_IN,
+ conn->bits.stream_was_rewound));
+ }
/* If we still have writing to do, we check if we have a writable socket. */
if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {