diff --git a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md
index 307d7a5582..d8a1153ead 100644
--- a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md
+++ b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md
@@ -94,8 +94,9 @@ change PUT etc - and therefore also not when libcurl issues a custom PUT. A
(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.
diff --git a/docs/libcurl/opts/CURLOPT_POSTREDIR.md b/docs/libcurl/opts/CURLOPT_POSTREDIR.md
index bf69af6f34..521d770a5e 100644
--- a/docs/libcurl/opts/CURLOPT_POSTREDIR.md
+++ b/docs/libcurl/opts/CURLOPT_POSTREDIR.md
@@ -32,19 +32,22 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTREDIR,
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
diff --git a/lib/http.c b/lib/http.c
index 12fb428728..908b27d72f 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1115,6 +1115,11 @@ static void http_switch_to_get(struct Curl_easy *data, int code)
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)
{
@@ -1323,10 +1328,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
* 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;
}
@@ -1348,10 +1350,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
* 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;
}
@@ -1361,13 +1360,8 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
/* '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;
}
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 1a41afc956..05c9aad580 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -241,7 +241,7 @@ test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \
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 \
diff --git a/tests/data/test1983 b/tests/data/test1983
new file mode 100644
index 0000000000..66e0de4e09
--- /dev/null
+++ b/tests/data/test1983
@@ -0,0 +1,71 @@
+
+
+
+
+
+HTTP
+HTTP DELETE
+followlocation
+
+
+# Server-side
+
+
+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
+
+
+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
+
+
+
+# Client-side
+
+
+http
+
+
+HTTP DELETE with --follow and 303 redirect
+
+
+http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER --follow -X DELETE
+
+
+
+# Verify data after the test has been "shot"
+
+
+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: */*
+
+
+
+
diff --git a/tests/data/test1984 b/tests/data/test1984
new file mode 100644
index 0000000000..1513eb64f5
--- /dev/null
+++ b/tests/data/test1984
@@ -0,0 +1,76 @@
+
+
+
+
+
+HTTP
+HTTP PUT
+followlocation
+
+
+# Server-side
+
+
+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
+
+
+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
+
+
+
+# Client-side
+
+
+http
+
+
+HTTP PUT with 303 redirect and --follow
+
+
+http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER --follow -T %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.
+
+
+
+# Verify data after the test has been "shot"
+
+
+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: */*
+
+
+
+