http: have CURLOPT_FAILONERROR fail after all headers
... so that Retry-After and other meta-content can still be used. Added 1634 to verify. Adjusted test 194 and 281 since --fail now also includes the header-terminating CRLF in the output before it exits. Fixes #6408 Closes #6409
This commit is contained in:
Родитель
9d7281ff17
Коммит
ab525c059e
49
lib/http.c
49
lib/http.c
|
@ -96,7 +96,7 @@
|
||||||
|
|
||||||
static int http_getsock_do(struct connectdata *conn,
|
static int http_getsock_do(struct connectdata *conn,
|
||||||
curl_socket_t *socks);
|
curl_socket_t *socks);
|
||||||
static int http_should_fail(struct connectdata *conn);
|
static bool http_should_fail(struct connectdata *conn);
|
||||||
|
|
||||||
#ifndef CURL_DISABLE_PROXY
|
#ifndef CURL_DISABLE_PROXY
|
||||||
static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
|
static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
|
||||||
|
@ -1046,11 +1046,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||||
*
|
*
|
||||||
* @param conn all information about the current connection
|
* @param conn all information about the current connection
|
||||||
*
|
*
|
||||||
* @retval 0 communications should continue
|
* @retval FALSE communications should continue
|
||||||
*
|
*
|
||||||
* @retval 1 communications should not continue
|
* @retval TRUE communications should not continue
|
||||||
*/
|
*/
|
||||||
static int http_should_fail(struct connectdata *conn)
|
static bool http_should_fail(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
struct Curl_easy *data;
|
struct Curl_easy *data;
|
||||||
int httpcode;
|
int httpcode;
|
||||||
|
@ -1066,20 +1066,20 @@ static int http_should_fail(struct connectdata *conn)
|
||||||
** don't fail.
|
** don't fail.
|
||||||
*/
|
*/
|
||||||
if(!data->set.http_fail_on_error)
|
if(!data->set.http_fail_on_error)
|
||||||
return 0;
|
return FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Any code < 400 is never terminal.
|
** Any code < 400 is never terminal.
|
||||||
*/
|
*/
|
||||||
if(httpcode < 400)
|
if(httpcode < 400)
|
||||||
return 0;
|
return FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Any code >= 400 that's not 401 or 407 is always
|
** Any code >= 400 that's not 401 or 407 is always
|
||||||
** a terminal error
|
** a terminal error
|
||||||
*/
|
*/
|
||||||
if((httpcode != 401) && (httpcode != 407))
|
if((httpcode != 401) && (httpcode != 407))
|
||||||
return 1;
|
return TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** All we have left to deal with is 401 and 407
|
** All we have left to deal with is 401 and 407
|
||||||
|
@ -3309,12 +3309,6 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
|
||||||
return checkhttpprefix(data, s, len);
|
return checkhttpprefix(data, s, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_http_error(struct Curl_easy *data)
|
|
||||||
{
|
|
||||||
struct SingleRequest *k = &data->req;
|
|
||||||
failf(data, "The requested URL returned error: %d", k->httpcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_http_header() parses a single response header.
|
* Curl_http_header() parses a single response header.
|
||||||
*/
|
*/
|
||||||
|
@ -3646,16 +3640,6 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
|
||||||
pretend this is no error */
|
pretend this is no error */
|
||||||
k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
|
k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
|
||||||
}
|
}
|
||||||
else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
|
|
||||||
((k->httpcode != 401) || !conn->bits.user_passwd)
|
|
||||||
#ifndef CURL_DISABLE_PROXY
|
|
||||||
&& ((k->httpcode != 407) || !conn->bits.proxy_user_passwd)
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
/* serious error, go home! */
|
|
||||||
print_http_error(data);
|
|
||||||
return CURLE_HTTP_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(conn->httpversion == 10) {
|
if(conn->httpversion == 10) {
|
||||||
/* Default action for HTTP/1.0 must be to close, unless
|
/* Default action for HTTP/1.0 must be to close, unless
|
||||||
|
@ -3928,15 +3912,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||||
conn->proxy_negotiate_state = GSS_AUTHSUCC;
|
conn->proxy_negotiate_state = GSS_AUTHSUCC;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
* When all the headers have been parsed, see if we should give
|
|
||||||
* up and return an error.
|
|
||||||
*/
|
|
||||||
if(http_should_fail(conn)) {
|
|
||||||
failf(data, "The requested URL returned error: %d",
|
|
||||||
k->httpcode);
|
|
||||||
return CURLE_HTTP_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now, only output this if the header AND body are requested:
|
/* now, only output this if the header AND body are requested:
|
||||||
*/
|
*/
|
||||||
|
@ -3954,6 +3929,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||||
data->info.header_size += (long)headerlen;
|
data->info.header_size += (long)headerlen;
|
||||||
data->req.headerbytecount += (long)headerlen;
|
data->req.headerbytecount += (long)headerlen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When all the headers have been parsed, see if we should give
|
||||||
|
* up and return an error.
|
||||||
|
*/
|
||||||
|
if(http_should_fail(conn)) {
|
||||||
|
failf(data, "The requested URL returned error: %d",
|
||||||
|
k->httpcode);
|
||||||
|
return CURLE_HTTP_RETURNED_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
data->req.deductheadercount =
|
data->req.deductheadercount =
|
||||||
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
|
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ test1608 test1609 test1610 test1611 test1612 \
|
||||||
\
|
\
|
||||||
test1620 test1621 \
|
test1620 test1621 \
|
||||||
\
|
\
|
||||||
test1630 test1631 test1632 test1633 \
|
test1630 test1631 test1632 test1633 test1634 \
|
||||||
\
|
\
|
||||||
test1650 test1651 test1652 test1653 test1654 test1655 \
|
test1650 test1651 test1652 test1653 test1654 test1655 \
|
||||||
test1660 \
|
test1660 \
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
HTTP
|
||||||
|
HTTP GET
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
HTTP/1.1 429 too many requests swsbounce
|
||||||
|
Retry-After: 1
|
||||||
|
Content-Length: 4
|
||||||
|
|
||||||
|
moo
|
||||||
|
</data>
|
||||||
|
<data1>
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Length: 4
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
hey
|
||||||
|
</data1>
|
||||||
|
|
||||||
|
<datacheck>
|
||||||
|
HTTP/1.1 429 too many requests swsbounce
|
||||||
|
Retry-After: 1
|
||||||
|
Content-Length: 4
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Length: 4
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
hey
|
||||||
|
</datacheck>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
--retry with a 429 response and Retry-After: and --fail
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
http://%HOSTIP:%HTTPPORT/1634 --retry 1 --fail
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
GET /1634 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
User-Agent: curl/%VERSION
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
GET /1634 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
User-Agent: curl/%VERSION
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
|
@ -36,6 +36,7 @@ Content-Length: 4
|
||||||
Content-Range: bytes */87
|
Content-Range: bytes */87
|
||||||
Content-Type: image/gif
|
Content-Type: image/gif
|
||||||
Connection: close
|
Connection: close
|
||||||
|
|
||||||
</datacheck>
|
</datacheck>
|
||||||
|
|
||||||
</reply>
|
</reply>
|
||||||
|
|
|
@ -14,11 +14,8 @@ HTTP/1.1 401 Bad Auth swsclose
|
||||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
WWW-Authenticate: Basic Realm=authenticate
|
WWW-Authenticate: Basic Realm=authenticate
|
||||||
Server: test-server/fake
|
Server: test-server/fake
|
||||||
</data>
|
|
||||||
<datacheck>
|
|
||||||
HTTP/1.1 100 Continue
|
|
||||||
|
|
||||||
</datacheck>
|
</data>
|
||||||
|
|
||||||
</reply>
|
</reply>
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче