aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES13
-rw-r--r--RELEASE-NOTES5
-rw-r--r--include/curl/curl.h3
-rw-r--r--lib/transfer.c9
-rw-r--r--lib/url.c7
-rw-r--r--lib/urldata.h1
-rw-r--r--packages/OS400/curl.inc.in2
-rw-r--r--src/main.c37
-rw-r--r--tests/data/Makefile.am2
-rw-r--r--tests/data/test101176
-rw-r--r--tests/data/test101279
11 files changed, 214 insertions, 20 deletions
diff --git a/CHANGES b/CHANGES
index 730f9cdd6..c6f7bc9a3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,19 @@
Changelog
Daniel S (26 September 2007)
+- Philip Langdale provided the new CURLOPT_POST301 option for
+ curl_easy_setopt() that alters how libcurl functions when following
+ redirects. It makes libcurl obey the RFC2616 when a 301 response is received
+ after a non-GET request is made. Default libcurl behaviour is to change
+ method to GET in the subsequent request (like it does for response code 302
+ - because that's what many/most browsers do), but with this CURLOPT_POST301
+ option enabled it will do what the spec says and do the next request using
+ the same method again. I.e keep POST after 301.
+
+ The curl tool got this option as --post301
+
+ Test case 1011 and 1012 were added to verify.
+
- Max Katsev reported that when doing a libcurl FTP request with
CURLOPT_NOBODY enabled but not CURLOPT_HEADER, libcurl wouldn't do TYPE
before it does SIZE which makes it less useful. I walked over the code and
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 75676d519..207849ba6 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -2,7 +2,7 @@ Curl and libcurl 7.17.1
Public curl release number: 102
Releases counted from the very beginning: 128
- Available command line options: 119
+ Available command line options: 120
Available curl_easy_setopt() options: 143
Number of public functions in libcurl: 55
Amount of public web site mirrors: 42
@@ -14,6 +14,7 @@ This release includes the following changes:
o automatically append ";type=<a|i>" when using HTTP proxies for FTP urls
o improved NSS support
o added --proxy-negotiate
+ o added --post301 and CURLOPT_POST301
This release includes the following bugfixes:
@@ -42,6 +43,6 @@ This release would not have looked like this without help, code, reports and
advice from friends like these:
Dan Fandrich, Michal Marek, Günter Knauf, Rob Crittenden, Immanuel Gregoire,
- Mark Davies, Max Katsev
+ Mark Davies, Max Katsev, Philip Langdale
Thanks! (and sorry if I forgot to mention someone)
diff --git a/include/curl/curl.h b/include/curl/curl.h
index e7f5ec59c..0df943344 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1124,6 +1124,9 @@ typedef enum {
CINIT(NEW_FILE_PERMS, LONG, 159),
CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+ /* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a 301 */
+ CINIT(POST301, LONG, 161),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
diff --git a/lib/transfer.c b/lib/transfer.c
index d16d29268..29e53690b 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -2257,10 +2257,13 @@ CURLcode Curl_follow(struct SessionHandle *data,
* violation, many webservers expect this misbehavior. So these servers
* often answers to a POST request with an error page. To be sure that
* libcurl gets the page that most user agents would get, libcurl has to
- * force GET:
+ * force GET.
+ *
+ * This behaviour can be overriden with CURLOPT_POST301.
*/
- if( data->set.httpreq == HTTPREQ_POST
- || data->set.httpreq == HTTPREQ_POST_FORM) {
+ if( (data->set.httpreq == HTTPREQ_POST
+ || data->set.httpreq == HTTPREQ_POST_FORM)
+ && !data->set.post301) {
infof(data,
"Violate RFC 2616/10.3.2 and switch from POST to GET\n");
data->set.httpreq = HTTPREQ_GET;
diff --git a/lib/url.c b/lib/url.c
index 9a7b22a94..6735b0179 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -924,6 +924,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.maxredirs = va_arg(param, long);
break;
+ case CURLOPT_POST301:
+ /*
+ * Obey RFC 2616/10.3.2 and resubmit a POST as a POST after a 301.
+ */
+ data->set.post301 = (bool)(0 != va_arg(param, long));
+ break;
+
case CURLOPT_POST:
/* Does this option serve a purpose anymore? Yes it does, when
CURLOPT_POSTFIELDS isn't used and the POST data is read off the
diff --git a/lib/urldata.h b/lib/urldata.h
index 435693ee0..b1de21ac5 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1306,6 +1306,7 @@ struct UserDefined {
long followlocation; /* as in HTTP Location: */
long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
for infinity */
+ bool post301; /* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a 301 */
bool free_referer; /* set TRUE if 'referer' points to a string we
allocated */
curl_off_t postfieldsize; /* if POST, this might have a size to use instead
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index 01b7c3759..2fc531211 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -723,6 +723,8 @@
d c 00159
d CURLOPT_NEW_DIRECTORY_PERMS...
d c 00160
+ d CURLOPT_POST301...
+ d c 00161
*
d CURLFORMcode s 10i 0 based(######ptr######) Enum
d CURL_FORMADD_OK...
diff --git a/src/main.c b/src/main.c
index 1fffb9695..cf68e845b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -478,6 +478,7 @@ struct Configurable {
char *libcurl; /* output libcurl code to this file name */
bool raw;
+ bool post301;
struct OutStruct *outs;
};
@@ -687,6 +688,7 @@ static void help(void)
" --no-sessionid Disable SSL session-ID reusing (SSL)",
" -o/--output <file> Write output to <file> instead of stdout",
" -O/--remote-name Write output to a file named as the remote file",
+ " --post301 Do not switch to GET after following a 301 redirect (H)",
" -p/--proxytunnel Operate through a HTTP proxy tunnel (using CONNECT)",
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
" --proxy-basic Use Basic authentication on the proxy (H)",
@@ -1511,6 +1513,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$j", "ftp-ssl-ccc-mode", TRUE},
{"$z", "libcurl", TRUE},
{"$#", "raw", FALSE},
+ {"$0", "post301", FALSE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
@@ -1962,6 +1965,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case '#': /* --raw */
config->raw ^= TRUE;
break;
+ case '0': /* --post301 */
+ config->post301 ^= TRUE;
+ break;
}
break;
case '#': /* --progress-bar */
@@ -2046,7 +2052,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
if(curlx_strequal("-", nextarg)) {
file = stdin;
- if(subletter == 'b') /* forced binary */
+ if(subletter == 'b') /* forced data-binary */
SET_BINMODE(stdin);
}
else {
@@ -3801,7 +3807,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
clean_getout(config);
break;
}
- }
+ }
infiles = urlnode->infile;
@@ -4022,17 +4028,17 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
/* Free the list of remaining URLs and globbed upload files
* to force curl to exit immediately
*/
- if(urls) {
- glob_cleanup(urls);
- urls = NULL;
- }
- if(inglob) {
- glob_cleanup(inglob);
- inglob = NULL;
- }
-
- res = CURLE_READ_ERROR;
- goto quit_urls;
+ if(urls) {
+ glob_cleanup(urls);
+ urls = NULL;
+ }
+ if(inglob) {
+ glob_cleanup(inglob);
+ inglob = NULL;
+ }
+
+ res = CURLE_READ_ERROR;
+ goto quit_urls;
}
infdfopen=TRUE;
uploadfilesize=fileinfo.st_size;
@@ -4196,7 +4202,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
my_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type);
my_setopt(curl, CURLOPT_KEYPASSWD, config->key_passwd);
- /* SSH private key uses the same command-line option as SSL private key */
+ /* SSH private key uses the same command-line option as SSL private key */
my_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
my_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
@@ -4386,6 +4392,9 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, FALSE);
}
+ /* curl 7.17.1 */
+ my_setopt(curl, CURLOPT_POST301, config->post301);
+
retry_numretries = config->req_retry;
retrystart = cutil_tvnow();
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 260d17b27..22ddb7f2c 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -44,4 +44,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test409 test613 test614 test700 test701 test702 test704 test705 test703 \
test706 test707 test350 test351 test352 test353 test289 test540 test354 \
test231 test1000 test1001 test1002 test1003 test1004 test1005 test1006 \
- test615 test1007 test541 test1010
+ test615 test1007 test541 test1010 test1011 test1012
diff --git a/tests/data/test1011 b/tests/data/test1011
new file mode 100644
index 000000000..62ba074a1
--- /dev/null
+++ b/tests/data/test1011
@@ -0,0 +1,76 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+followlocation
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 OK swsclose
+Location: moo.html&testcase=/10110002
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+</data>
+<data2>
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</data2>
+<datacheck>
+HTTP/1.1 301 OK swsclose
+Location: moo.html&testcase=/10110002
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP POST with 301 redirect
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/blah/1011 -L -d "moo"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+POST /blah/1011 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+mooGET /blah/moo.html&testcase=/10110002 HTTP/1.1
+User-Agent: curl/7.10 (i686-pc-linux-gnu) libcurl/7.10 OpenSSL/0.9.6c ipv6 zlib/1.1.3
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1012 b/tests/data/test1012
new file mode 100644
index 000000000..6aa17156d
--- /dev/null
+++ b/tests/data/test1012
@@ -0,0 +1,79 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+followlocation
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 OK swsclose
+Location: moo.html&testcase=/10120002
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+</data>
+<data2>
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</data2>
+<datacheck>
+HTTP/1.1 301 OK swsclose
+Location: moo.html&testcase=/10120002
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP POST with 301 redirect and --post301
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/blah/1012 -L -d "moo" --post301
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol nonewline="yes">
+POST /blah/1012 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+mooPOST /blah/moo.html&testcase=/10120002 HTTP/1.1
+User-Agent: curl/7.10 (i686-pc-linux-gnu) libcurl/7.10 OpenSSL/0.9.6c ipv6 zlib/1.1.3
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+moo
+</protocol>
+</verify>
+</testcase>