(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).
+switch back to GET for when doing a custom POST (a POST transfer using a
+modified method), 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.
Pass a bitmask to control how libcurl acts on redirects after POSTs that get a
301, 302 or 303 response back. A parameter with bit 0 set (value
-**CURL_REDIR_POST_301**) tells the library to respect RFC 7231 (section
-6.4.2 to 6.4.4) and not convert POST requests into GET requests when following
-a 301 redirection. Setting bit 1 (value **CURL_REDIR_POST_302**) makes
-libcurl maintain the request method after a 302 redirect whilst setting bit 2
-(value **CURL_REDIR_POST_303**) makes libcurl maintain the request method
-after a 303 redirect. The value **CURL_REDIR_POST_ALL** is a convenience
-define that sets all three bits.
+**CURL_REDIR_POST_301**) tells the library to not convert POST requests into
+GET requests when following a 301 redirection. Setting bit 1 (value
+**CURL_REDIR_POST_302**) makes libcurl maintain the request method after a 302
+redirect whilst setting bit 2 (value **CURL_REDIR_POST_303**) makes libcurl
+maintain the request method after a 303 redirect. The value
+**CURL_REDIR_POST_ALL** is a convenience define that sets all three bits.
The non-RFC behavior is ubiquitous in web browsers, so the library does the
conversion by default to maintain consistency. A server may require a POST to
remain a POST after such a redirection. This option is meaningful only when
setting CURLOPT_FOLLOWLOCATION(3).
+This option affects transfers where libcurl has been told to use HTTP POST
+using for example CURLOPT_POST(3) or CURLOPT_MIMEPOST(3) and not if the
+method has merely been modified with CURLOPT_CUSTOMREQUEST(3).
+
# DEFAULT
0
Curl_creader_set_rewind(data, FALSE);
}
+#define HTTPREQ_IS_POST(data) \
+ ((data)->state.httpreq == HTTPREQ_POST || \
+ (data)->state.httpreq == HTTPREQ_POST_FORM || \
+ (data)->state.httpreq == HTTPREQ_POST_MIME)
+
CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
followtype type)
{
* This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
- if((data->state.httpreq == HTTPREQ_POST ||
- data->state.httpreq == HTTPREQ_POST_FORM ||
- data->state.httpreq == HTTPREQ_POST_MIME) &&
- !data->set.post301) {
+ if(HTTPREQ_IS_POST(data) && !data->set.post301) {
http_switch_to_get(data, 301);
switch_to_get = TRUE;
}
* This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
- if((data->state.httpreq == HTTPREQ_POST ||
- data->state.httpreq == HTTPREQ_POST_FORM ||
- data->state.httpreq == HTTPREQ_POST_MIME) &&
- !data->set.post302) {
+ if(HTTPREQ_IS_POST(data) && !data->set.post302) {
http_switch_to_get(data, 302);
switch_to_get = TRUE;
}
/* 'See Other' location is not the resource but a substitute for the
* resource. In this case we switch the method to GET/HEAD, unless the
* method is POST and the user specified to keep it as POST.
- * https://github.com/curl/curl/issues/5237#issuecomment-614641049
*/
- if(data->state.httpreq != HTTPREQ_GET &&
- ((data->state.httpreq != HTTPREQ_POST &&
- data->state.httpreq != HTTPREQ_POST_FORM &&
- data->state.httpreq != HTTPREQ_POST_MIME) ||
- !data->set.post303)) {
+ if(!HTTPREQ_IS_POST(data) || !data->set.post303) {
http_switch_to_get(data, 303);
switch_to_get = TRUE;
}
test1955 test1956 test1957 test1958 test1959 test1960 test1964 test1965 \
\
test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 \
-test1978 test1979 test1980 test1981 test1982 \
+test1978 test1979 test1980 test1981 test1982 test1983 test1984 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 \
--- /dev/null
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+
+<info>
+<keywords>
+HTTP
+HTTP DELETE
+followlocation
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+HTTP/1.1 303 OK swsclose
+Location: moo.html%AMPtestcase=/%TESTNUMBER0002
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+</data>
+<data2>
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</data2>
+<datacheck>
+HTTP/1.1 303 OK swsclose
+Location: moo.html%AMPtestcase=/%TESTNUMBER0002
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP DELETE with --follow and 303 redirect
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER --follow -X DELETE
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+DELETE /blah/%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /blah/moo.html%AMPtestcase=/%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
--- /dev/null
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+
+<info>
+<keywords>
+HTTP
+HTTP PUT
+followlocation
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+HTTP/1.1 303 OK swsclose
+Location: moo.html%AMPtestcase=/%TESTNUMBER0002
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+</data>
+<data2>
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</data2>
+<datacheck>
+HTTP/1.1 303 OK swsclose
+Location: moo.html%AMPtestcase=/%TESTNUMBER0002
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+HTTP/1.1 200 OK swsclose
+Location: this should be ignored
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+
+body
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP PUT with 303 redirect and --follow
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER --follow -T %LOGDIR/upload
+</command>
+<file name="%LOGDIR/upload">
+Except for responses to a HEAD request, the representation of a 303 response ought to contain a short hypertext note with a hyperlink to the same URI reference provided in the Location header field.
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="headers">
+PUT /blah/%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 199
+
+Except for responses to a HEAD request, the representation of a 303 response ought to contain a short hypertext note with a hyperlink to the same URI reference provided in the Location header field.
+GET /blah/moo.html%AMPtestcase=/%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>