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 1581 verify.

Closes #16473
This commit is contained in:
Daniel Stenberg 2025-03-03 11:35:48 +01:00
parent 294136b754
commit fb13923dd6
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
23 changed files with 1328 additions and 34 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

@ -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