diff options
-rw-r--r-- | CHANGES | 13 | ||||
-rw-r--r-- | RELEASE-NOTES | 5 | ||||
-rw-r--r-- | include/curl/curl.h | 3 | ||||
-rw-r--r-- | lib/transfer.c | 9 | ||||
-rw-r--r-- | lib/url.c | 7 | ||||
-rw-r--r-- | lib/urldata.h | 1 | ||||
-rw-r--r-- | packages/OS400/curl.inc.in | 2 | ||||
-rw-r--r-- | src/main.c | 37 | ||||
-rw-r--r-- | tests/data/Makefile.am | 2 | ||||
-rw-r--r-- | tests/data/test1011 | 76 | ||||
-rw-r--r-- | tests/data/test1012 | 79 |
11 files changed, 214 insertions, 20 deletions
@@ -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; @@ -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> |