Compare commits

..

3 Commits

Author SHA1 Message Date
Daniel Stenberg
1cddf7e20b
fixup add test 1581 to verify OBEYCODE + CURL_REDIR_POST_301 2025-02-28 22:51:22 +01:00
Daniel Stenberg
8d3f947df6
fixup extend docs 2025-02-28 22:51:22 +01:00
Daniel Stenberg
a968b2ecdc
lib: add CURLFOLLOW_OBEYCODE and CURLFOLLOW_FIRSTONLY
With this change, the argument passed to the CURLOPT_FOLLOWLOCATION
option is now instead a "mode" instead of just a boolean. Documentation
is extended to describe the two new modes.

Test 1571 to 1580 verify.

Closes #16473
2025-02-28 22:51:22 +01:00
29 changed files with 1359 additions and 72 deletions

View File

@ -602,7 +602,7 @@ problems may have been fixed or changed somewhat since this was written.
16.3 aws-sigv4 has problems with particular URLs
https://github.com/curl/curl/issues/13058
https://github.com/curl/curl/issues/13085
16.6 aws-sigv4 does not behave well with AWS VPC Lattice

View File

@ -247,11 +247,11 @@ local system or network, the bar is raised. If a local user wrongfully has
elevated rights on your system enough to attack curl, they can probably
already do much worse harm and the problem is not really in curl.
## Debug & Experiments
## Experiments
Vulnerabilities in features which are off by default (in the build) and
documented as experimental, or exist only in debug mode, are not eligible for a
reward and we do not consider them security problems.
documented as experimental, are not eligible for a reward and we do not
consider them security problems.
## URL inconsistencies

View File

@ -418,22 +418,22 @@ static int init_fifo(GlobalInfo *g)
struct epoll_event epev;
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
if(lstat(fifo, &st) == 0) {
if(lstat (fifo, &st) == 0) {
if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST;
perror("lstat");
return 1;
exit(1);
}
}
unlink(fifo);
if(mkfifo(fifo, 0600) == -1) {
if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo");
return 1;
exit(1);
}
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) {
perror("open");
return 1;
exit(1);
}
g->fifofd = sockfd;
@ -449,9 +449,9 @@ static int init_fifo(GlobalInfo *g)
static void clean_fifo(GlobalInfo *g)
{
epoll_ctl(g->epfd, EPOLL_CTL_DEL, g->fifofd, NULL);
fclose(g->input);
unlink(fifo);
epoll_ctl(g->epfd, EPOLL_CTL_DEL, g->fifofd, NULL);
fclose(g->input);
unlink(fifo);
}
@ -478,13 +478,13 @@ int main(int argc, char **argv)
g.epfd = epoll_create1(EPOLL_CLOEXEC);
if(g.epfd == -1) {
perror("epoll_create1 failed");
return 1;
exit(1);
}
g.tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if(g.tfd == -1) {
perror("timerfd_create failed");
return 1;
exit(1);
}
memset(&its, 0, sizeof(struct itimerspec));
@ -496,8 +496,7 @@ int main(int argc, char **argv)
ev.data.fd = g.tfd;
epoll_ctl(g.epfd, EPOLL_CTL_ADD, g.tfd, &ev);
if(init_fifo(&g))
return 1;
init_fifo(&g);
g.multi = curl_multi_init();
/* setup the generic multi interface options we want */
@ -522,7 +521,7 @@ int main(int argc, char **argv)
}
else {
perror("epoll_wait");
return 1;
exit(1);
}
}

View File

@ -402,22 +402,22 @@ static int init_fifo(GlobalInfo *g)
curl_socket_t sockfd;
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
if(lstat(fifo, &st) == 0) {
if(lstat (fifo, &st) == 0) {
if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST;
perror("lstat");
return 1;
exit(1);
}
}
unlink(fifo);
if(mkfifo(fifo, 0600) == -1) {
if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo");
return 1;
exit(1);
}
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) {
perror("open");
return 1;
exit(1);
}
g->input = fdopen(sockfd, "r");
@ -436,8 +436,7 @@ int main(int argc, char **argv)
memset(&g, 0, sizeof(GlobalInfo));
g.loop = ev_default_loop(0);
if(init_fifo(&g))
return 1;
init_fifo(&g);
g.multi = curl_multi_init();
ev_timer_init(&g.timer_event, timer_cb, 0., 0.);

View File

@ -392,21 +392,21 @@ int init_fifo(void)
if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST;
perror("lstat");
return CURL_SOCKET_BAD;
exit(1);
}
}
unlink(fifo);
if(mkfifo(fifo, 0600) == -1) {
if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo");
return CURL_SOCKET_BAD;
exit(1);
}
socket = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(socket == CURL_SOCKET_BAD) {
if(socket == -1) {
perror("open");
return socket;
exit(1);
}
MSG_OUT("Now, pipe some URL's into > %s\n", fifo);
@ -421,8 +421,6 @@ int main(void)
GIOChannel* ch;
fd = init_fifo();
if(fd == CURL_SOCKET_BAD)
return 1;
ch = g_io_channel_unix_new(fd);
g_io_add_watch(ch, G_IO_IN, fifo_cb, g);
gmain = g_main_loop_new(NULL, FALSE);

View File

@ -399,22 +399,22 @@ static int init_fifo(GlobalInfo *g)
curl_socket_t sockfd;
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
if(lstat(fifo, &st) == 0) {
if(lstat (fifo, &st) == 0) {
if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST;
perror("lstat");
return 1;
exit(1);
}
}
unlink(fifo);
if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo");
return 1;
exit(1);
}
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) {
perror("open");
return 1;
exit(1);
}
g->input = fdopen(sockfd, "r");
@ -440,8 +440,7 @@ int main(int argc, char **argv)
memset(&g, 0, sizeof(GlobalInfo));
g.evbase = event_base_new();
if(init_fifo(&g))
return 1;
init_fifo(&g);
g.multi = curl_multi_init();
evtimer_assign(&g.timer_event, g.evbase, timer_cb, &g);

View File

@ -66,9 +66,15 @@ Many people have wrongly used this option to replace the entire request with
their own, including multiple headers and POST contents. While that might work
in many cases, it might cause libcurl to send invalid requests and it could
possibly confuse the remote server badly. Use CURLOPT_POST(3) and
CURLOPT_POSTFIELDS(3) to set POST data. Use CURLOPT_HTTPHEADER(3)
to replace or extend the set of headers sent by libcurl. Use
CURLOPT_HTTP_VERSION(3) to change HTTP version.
CURLOPT_POSTFIELDS(3) to set POST data. Use CURLOPT_HTTPHEADER(3) to replace
or extend the set of headers sent by libcurl. Use CURLOPT_HTTP_VERSION(3) to
change the HTTP version.
When this option is used together with CURLOPT_FOLLOWLOCATION(3), the custom
set method overrides the method libcurl could otherwise change to for the
subsequent requests. You can fine-tune that decision by using the
CURLFOLLOW_OBEYCODE bit to CURLOPT_FOLLOWLOCATION(3) to make redirects adhere
to the redirect response code as the protocol instructs.
## FTP

View File

@ -25,19 +25,23 @@ CURLOPT_FOLLOWLOCATION - follow HTTP 3xx redirects
~~~c
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long enable);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long mode);
~~~
# DESCRIPTION
A long parameter set to 1 tells the library to follow any Location: header
redirects that an HTTP server sends in a 30x response. The Location: header
can specify a relative or an absolute URL to follow.
This option tells the library to follow `Location:` header redirects that an
HTTP server sends in a 30x response. The `Location:` header can specify a
relative or an absolute URL to follow. The long parameter *mode* instructs how
libcurl should act on subsequent requests.
libcurl issues another request for the new URL and follows subsequent new
`Location:` redirects all the way until no more such headers are returned or
the maximum limit is reached. CURLOPT_MAXREDIRS(3) is used to limit the number
of redirects libcurl follows.
*mode* only had a single value (1L) for a long time that enables redirect
following. Since 8.13.0, two additional modes are also supported. See below.
When following redirects, libcurl issues another request for the new URL and
follows subsequent new `Location:` redirects all the way until no more such
headers are returned or the maximum limit is reached. CURLOPT_MAXREDIRS(3) is
used to limit the number of redirects libcurl follows.
libcurl restricts what protocols it automatically follow redirects to. The
accepted target protocols are set with CURLOPT_REDIR_PROTOCOLS_STR(3). By
@ -64,6 +68,45 @@ client may not want to pass on to other servers than the initially intended
host and for all other headers than the two mentioned above, there is no
protection from this happening when libcurl is told to follow redirects.
Pick one of the following modes:
## CURLFOLLOW_ALL (1)
Before 8.13.0 this bit had no name and 1L was just the value to enable this
option. This makes a set custom method be used in all HTTP requests, even
after redirects.
## CURLFOLLOW_OBEYCODE (2)
When there is a custom request method set with CURLOPT_CUSTOMREQUEST(3), that
set method replaces what libcurl would otherwise use. If a 301/302/303
response code is returned to signal a redirect, the method is changed from
POST to `GET`. For 307/308, the custom method remains set and used.
Note that only POST (or a custom post) is changed to GET on 301/302, its not
change PUT etc - and therefore also not when libcurl issues a custom PUT. A
303 response makes it switch to GET independently of the original method
(except for HEAD).
To control for which of the 301/302/303 status codes libcurl should *not*
switch back to GET for when doing a custom POST, and instead keep the custom
method, use CURLOPT_POSTREDIR(3).
If you prefer a custom POST method to be reset to exactly the method `POST`,
use CURLFOLLOW_FIRSTONLY instead.
## CURLFOLLOW_FIRSTONLY (3)
When there is a custom request method set with CURLOPT_CUSTOMREQUEST(3), that
set method replaces what libcurl would otherwise use in the first outgoing
request only. The second request is then done according to the redirect
response code.
If you prefer your custom method to remain in use after a 307/308 redirect,
use CURLFOLLOW_OBEYCODE instead.
##
# NOTE
Since libcurl changes method or not based on the specific HTTP response code,
@ -72,6 +115,10 @@ libcurl would otherwise do and if not that carefully may even make it
misbehave since CURLOPT_CUSTOMREQUEST(3) overrides the method libcurl would
otherwise select internally.
Setting the CURLFOLLOW_OBEYCODE bit makes libcurl *not* use the custom set
method after redirects for 301, 302 and 303 responses. Unless the
CURLOPT_POSTREDIR(3) bits are set for those status codes.
# DEFAULT
0, disabled

View File

@ -337,11 +337,11 @@ CURLE_UNRECOVERABLE_POLL 7.84.0
CURLE_UNSUPPORTED_PROTOCOL 7.1
CURLE_UPLOAD_FAILED 7.16.3
CURLE_URL_MALFORMAT 7.1
CURLE_ECH_REQUIRED 8.8.0
CURLE_URL_MALFORMAT_USER 7.1 7.17.0
CURLE_USE_SSL_FAILED 7.17.0
CURLE_WEIRD_SERVER_REPLY 7.51.0
CURLE_WRITE_ERROR 7.1
CURLE_ECH_REQUIRED 8.8.0
CURLFILETYPE_DEVICE_BLOCK 7.21.0
CURLFILETYPE_DEVICE_CHAR 7.21.0
CURLFILETYPE_DIRECTORY 7.21.0
@ -359,6 +359,9 @@ CURLFINFOFLAG_KNOWN_PERM 7.21.0
CURLFINFOFLAG_KNOWN_SIZE 7.21.0
CURLFINFOFLAG_KNOWN_TIME 7.21.0
CURLFINFOFLAG_KNOWN_UID 7.21.0
CURLFOLLOW_ALL 8.13.0
CURLFOLLOW_OBEYCODE 8.13.0
CURLFOLLOW_FIRSTONLY 8.13.0
CURLFORM_ARRAY 7.9.1 7.56.0
CURLFORM_ARRAY_END 7.9.1 7.9.5 7.9.6
CURLFORM_ARRAY_START 7.9.1 7.9.5 7.9.6

View File

@ -175,6 +175,16 @@ typedef enum {
#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
/* bits for the CURLOPT_FOLLOWLOCATION option */
#define CURLFOLLOW_ALL 1L /* generic follow redirects */
/* Do not use the custom method in the follow-up request if the HTTP code
instructs so (301, 302, 303). */
#define CURLFOLLOW_OBEYCODE 2L
/* Only use the custom method in the first request, always reset in the next */
#define CURLFOLLOW_FIRSTONLY 3L
struct curl_httppost {
struct curl_httppost *next; /* next entry in the list */
char *name; /* pointer to allocated name */

View File

@ -1155,6 +1155,21 @@ static bool http_should_fail(struct Curl_easy *data, int httpcode)
return data->state.authproblem;
}
static void http_switch_to_get(struct Curl_easy *data, int code)
{
const char *req = data->set.str[STRING_CUSTOMREQUEST];
if((req || data->state.httpreq != HTTPREQ_GET) &&
(data->set.http_follow_mode == CURLFOLLOW_OBEYCODE)) {
infof(data, "Switch to GET because of %d response", code);
data->state.http_ignorecustom = TRUE;
}
else if(req && (data->set.http_follow_mode != CURLFOLLOW_FIRSTONLY))
infof(data, "Stick to %s instead of GET", req);
data->state.httpreq = HTTPREQ_GET;
Curl_creader_set_rewind(data, FALSE);
}
CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
followtype type)
{
@ -1321,6 +1336,12 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
data->state.url_alloc = TRUE;
Curl_req_soft_reset(&data->req, data);
infof(data, "Issue another request to this URL: '%s'", data->state.url);
if((data->set.http_follow_mode == CURLFOLLOW_FIRSTONLY) &&
data->set.str[STRING_CUSTOMREQUEST] &&
!data->state.http_ignorecustom) {
data->state.http_ignorecustom = TRUE;
infof(data, "Drop custom request method for next request");
}
/*
* We get here when the HTTP code is 300-399 (and 401). We need to perform
@ -1362,11 +1383,8 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
if((data->state.httpreq == HTTPREQ_POST
|| data->state.httpreq == HTTPREQ_POST_FORM
|| data->state.httpreq == HTTPREQ_POST_MIME)
&& !(data->set.keep_post & CURL_REDIR_POST_301)) {
infof(data, "Switch from POST to GET");
data->state.httpreq = HTTPREQ_GET;
Curl_creader_set_rewind(data, FALSE);
}
&& !(data->set.keep_post & CURL_REDIR_POST_301))
http_switch_to_get(data, 301);
break;
case 302: /* Found */
/* (quote from RFC7231, section 6.4.3)
@ -1388,11 +1406,8 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
if((data->state.httpreq == HTTPREQ_POST
|| data->state.httpreq == HTTPREQ_POST_FORM
|| data->state.httpreq == HTTPREQ_POST_MIME)
&& !(data->set.keep_post & CURL_REDIR_POST_302)) {
infof(data, "Switch from POST to GET");
data->state.httpreq = HTTPREQ_GET;
Curl_creader_set_rewind(data, FALSE);
}
&& !(data->set.keep_post & CURL_REDIR_POST_302))
http_switch_to_get(data, 302);
break;
case 303: /* See Other */
@ -1405,11 +1420,8 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
((data->state.httpreq != HTTPREQ_POST &&
data->state.httpreq != HTTPREQ_POST_FORM &&
data->state.httpreq != HTTPREQ_POST_MIME) ||
!(data->set.keep_post & CURL_REDIR_POST_303))) {
data->state.httpreq = HTTPREQ_GET;
infof(data, "Switch to %s",
data->req.no_body ? "HEAD" : "GET");
}
!(data->set.keep_post & CURL_REDIR_POST_303)))
http_switch_to_get(data, 303);
break;
case 304: /* Not Modified */
/* 304 means we did a conditional request and it was "Not modified".
@ -1803,8 +1815,10 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
httpreq = HTTPREQ_PUT;
/* Now set the 'request' pointer to the proper request string */
if(data->set.str[STRING_CUSTOMREQUEST])
if(data->set.str[STRING_CUSTOMREQUEST] &&
!data->state.http_ignorecustom) {
request = data->set.str[STRING_CUSTOMREQUEST];
}
else {
if(data->req.no_body)
request = "HEAD";
@ -3138,7 +3152,7 @@ static CURLcode http_header(struct Curl_easy *data,
else {
data->req.location = location;
if(data->set.http_follow_location) {
if(data->set.http_follow_mode) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->req.location); /* clone */
if(!data->req.newurl)

View File

@ -525,7 +525,9 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
/*
* Follow Location: header hints on an HTTP-server.
*/
data->set.http_follow_location = enabled;
if(uarg > 3)
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.http_follow_mode = (unsigned char)uarg;
break;
case CURLOPT_UNRESTRICTED_AUTH:

View File

@ -1354,6 +1354,7 @@ struct UrlState {
BIT(internal); /* internal: true if this easy handle was created for
internal use and the user does not have ownership of the
handle. */
BIT(http_ignorecustom); /* ignore custom method from now */
};
/*
@ -1723,6 +1724,7 @@ struct UserDefined {
CURLOPT_GSSAPI_DELEGATION */
unsigned char gssapi_delegation;
#endif
unsigned char http_follow_mode; /* follow HTTP redirects */
BIT(connect_only); /* make connection/request, then let application use the
socket */
BIT(connect_only_ws); /* special websocket connect-only level */
@ -1774,7 +1776,6 @@ struct UserDefined {
BIT(hide_progress); /* do not use the progress meter */
BIT(http_fail_on_error); /* fail on HTTP error codes >= 400 */
BIT(http_keep_sending_on_error); /* for HTTP status codes >= 300 */
BIT(http_follow_location); /* follow HTTP redirects */
BIT(http_transfer_encoding); /* request compressed HTTP transfer-encoding */
BIT(allow_auth_to_other_hosts);
BIT(include_header); /* include received protocol headers in data output */

View File

@ -207,7 +207,8 @@ test1540 test1541 test1542 test1543 test1544 test1545 test1546 \
\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 test1567 test1568 test1569 test1570 \
test1566 test1567 test1568 test1569 test1570 test1571 test1572 test1573 \
test1574 test1575 test1576 test1577 test1578 test1579 test1580 test1581 \
\
test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \
test1598 \

95
tests/data/test1571 Normal file
View File

@ -0,0 +1,95 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_OBEYCODE
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib%TESTNUMBER
</tool>
<name>
CURLFOLLOW_OBEYCODE with custom POST method, 302 => GET
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1571
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
IGLOO /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
mooGET /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
</verify>
</testcase>

97
tests/data/test1572 Normal file
View File

@ -0,0 +1,97 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_OBEYCODE
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1571
</tool>
<name>
CURLFOLLOW_OBEYCODE with custom POST method, 308 => custom
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1571
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
IGLOO /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
mooIGLOO /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
moo
</protocol>
</verify>
</testcase>

92
tests/data/test1573 Normal file
View File

@ -0,0 +1,92 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_OBEYCODE
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1571
</tool>
<name>
CURLFOLLOW_OBEYCODE with custom GET method, 301 => custom
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1573
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol crlf="yes">
IGLOO /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
IGLOO /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
</verify>
</testcase>

92
tests/data/test1574 Normal file
View File

@ -0,0 +1,92 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_FIRSTONLY
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1571
</tool>
<name>
CURLFOLLOW_FIRSTONLY with custom GET method, 301 => GET
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1574
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol crlf="yes">
IGLOO /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
GET /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
</verify>
</testcase>

97
tests/data/test1575 Normal file
View File

@ -0,0 +1,97 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_FIRSTONLY
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1571
</tool>
<name>
CURLFOLLOW_FIRSTONLY with custom POST method, 308 => POST
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1575
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
IGLOO /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
mooPOST /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
moo
</protocol>
</verify>
</testcase>

95
tests/data/test1576 Normal file
View File

@ -0,0 +1,95 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_OBEYCODE
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib%TESTNUMBER
</tool>
<name>
CURLFOLLOW_OBEYCODE with custom PUT method, 302 => custom
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1576
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
CURL /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which madeCURL /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which made
</protocol>
</verify>
</testcase>

95
tests/data/test1577 Normal file
View File

@ -0,0 +1,95 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_OBEYCODE
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1576
</tool>
<name>
CURLFOLLOW_OBEYCODE with custom PUT method, 308 => custom
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER %TESTNUMBER
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
CURL /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which madeCURL /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which made
</protocol>
</verify>
</testcase>

95
tests/data/test1578 Normal file
View File

@ -0,0 +1,95 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_FIRSTONLY
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 302 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1576
</tool>
<name>
CURLFOLLOW_FIRSTONLY with custom PUT method, 302 => PUT
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER %TESTNUMBER
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
CURL /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which madePUT /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which made
</protocol>
</verify>
</testcase>

93
tests/data/test1579 Normal file
View File

@ -0,0 +1,93 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_OBEYCODE
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 303 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 303 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1576
</tool>
<name>
CURLFOLLOW_OBEYCODE with custom PUT method, 303 => GET
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER %TESTNUMBER
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol crlf="yes">
CURL /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which madeGET /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
</verify>
</testcase>

95
tests/data/test1580 Normal file
View File

@ -0,0 +1,95 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_FIRSTONLY
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 308 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1576
</tool>
<name>
CURLFOLLOW_FIRSTONLY with custom PUT method, 308 => PUT
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1578
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
CURL /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which madePUT /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 45
request indicates that the client, which made
</protocol>
</verify>
</testcase>

97
tests/data/test1581 Normal file
View File

@ -0,0 +1,97 @@
<testcase>
<info>
<keywords>
CURLFOLLOW_OBEYCODE
CURLOPT_FOLLOWLOCATION
</keywords>
</info>
#
# Server-side
<reply>
<data crlf="yes">
HTTP/1.1 301 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<data1 crlf="yes">
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</data>
<datacheck crlf="yes">
HTTP/1.1 301 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Location: %TESTNUMBER0001
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
Content-Type: text/html
-bar-
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1571
</tool>
<name>
CURLFOLLOW_OBEYCODE with custom POST301 method, 301 => custom
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER 1581
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol nonewline="yes" crlf="yes">
IGLOO /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
mooIGLOO /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
moo
</protocol>
</verify>
</testcase>

View File

@ -60,7 +60,8 @@ LIBTESTPROGS = libauthretry libntlmconnect libprereq \
lib1534 lib1535 lib1536 lib1537 lib1538 lib1539 \
lib1540 lib1541 lib1542 lib1543 lib1545 \
lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 \
lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 lib1571 \
lib1576 lib1578 \
lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 lib1598 \
\
lib1662 \
@ -523,6 +524,14 @@ lib1568_SOURCES = lib1568.c $(SUPPORTFILES)
lib1569_SOURCES = lib1569.c $(SUPPORTFILES)
lib1571_SOURCES = lib1571.c $(SUPPORTFILES)
lib1571_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1571
lib1576_SOURCES = lib1576.c $(SUPPORTFILES)
lib1578_SOURCES = lib1576.c $(SUPPORTFILES)
lib1578_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1578
lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1591_LDADD = $(TESTUTIL_LIBS)

72
tests/libtest/lib1571.c Normal file
View File

@ -0,0 +1,72 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "test.h"
#include "memdebug.h"
CURLcode test(char *URL)
{
CURLcode res;
CURL *curl;
int testno = atoi(libtest_arg2);
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
curl = curl_easy_init();
if(!curl) {
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(curl, CURLOPT_HEADER, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_URL, URL);
if((testno == 1571) || (testno == 1575) || (testno == 1581)) {
test_setopt(curl, CURLOPT_POSTFIELDS, "moo");
}
if(testno == 1581) {
test_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_301);
}
test_setopt(curl, CURLOPT_CUSTOMREQUEST, "IGLOO");
if((testno == 1574) || (testno == 1575)) {
test_setopt(curl, CURLOPT_FOLLOWLOCATION, CURLFOLLOW_FIRSTONLY);
}
else {
test_setopt(curl, CURLOPT_FOLLOWLOCATION, CURLFOLLOW_OBEYCODE);
}
res = curl_easy_perform(curl);
test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();
return res;
}

86
tests/libtest/lib1576.c Normal file
View File

@ -0,0 +1,86 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "test.h"
#include "memdebug.h"
static char testdata[] = "request indicates that the client, which made";
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
size_t amount = nmemb * size; /* Total bytes curl wants */
if(amount < strlen(testdata)) {
return strlen(testdata);
}
(void)stream;
memcpy(ptr, testdata, strlen(testdata));
return strlen(testdata);
}
CURLcode test(char *URL)
{
CURLcode res;
CURL *curl;
struct curl_slist *pHeaderList = NULL;
int testno = atoi(libtest_arg2);
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
curl = curl_easy_init();
if(!curl) {
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
test_setopt(curl, CURLOPT_HEADER, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_UPLOAD, 1L);
test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
test_setopt(curl, CURLOPT_INFILESIZE, (long)strlen(testdata));
test_setopt(curl, CURLOPT_CUSTOMREQUEST, "CURL");
if(testno == 1578) {
test_setopt(curl, CURLOPT_FOLLOWLOCATION, CURLFOLLOW_FIRSTONLY);
}
else {
test_setopt(curl, CURLOPT_FOLLOWLOCATION, CURLFOLLOW_OBEYCODE);
}
/* Remove "Expect: 100-continue" */
pHeaderList = curl_slist_append(pHeaderList, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pHeaderList);
res = curl_easy_perform(curl);
test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();
curl_slist_free_all(pHeaderList);
return res;
}

View File

@ -58,11 +58,9 @@ CFGSET=true
!ENDIF
!INCLUDE "../lib/Makefile.inc"
CSOURCES=$(CSOURCES: = )
LIBCURL_OBJS=$(CSOURCES:.c=.obj)
!INCLUDE "../src/Makefile.inc"
CURL_CFILES=$(CURL_CFILES: = )
CURL_OBJS=$(CURL_CFILES:.c=.obj)