mirror of
https://github.com/curl/curl.git
synced 2026-06-07 05:14:15 +03:00
curl: add --follow
Makes curl follow redirects an act on the response code and change a
custom method accordingly, contrary to --location.
Potential future command line to send QUERY and following a redirect
according to the status code:
curl -d "request-body" -X QUERY --follow https://example.com
add test 794,796,797
Assisted-by: Daniel Böhmer <post@daniel-boehmer.de>
Closes #16543
This commit is contained in:
parent
4d025fd912
commit
39543b7fdc
16 changed files with 340 additions and 10 deletions
|
|
@ -101,6 +101,7 @@ DPAGES = \
|
|||
fail-with-body.md \
|
||||
fail.md \
|
||||
false-start.md \
|
||||
follow.md \
|
||||
form-escape.md \
|
||||
form-string.md \
|
||||
form.md \
|
||||
|
|
|
|||
25
docs/cmdline-opts/follow.md
Normal file
25
docs/cmdline-opts/follow.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
SPDX-License-Identifier: curl
|
||||
Long: follow
|
||||
Help: Follow redirects per spec
|
||||
Category: http
|
||||
Added: 8.16.0
|
||||
Multi: boolean
|
||||
See-also:
|
||||
- request
|
||||
- location
|
||||
Example:
|
||||
- -X POST --follow $URL
|
||||
---
|
||||
|
||||
# `--follow`
|
||||
|
||||
Instructs curl to follow HTTP redirects and to do the custom request method
|
||||
set with --request when following redirects as the HTTP specification says.
|
||||
|
||||
The method string set with --request is used in subsequent requests for the
|
||||
status codes 307 or 308, but may be reset to GET for 301, 302 and 303.
|
||||
|
||||
This is subtly different than --location, as that option always set the custom
|
||||
method in all subsequent requests independent of response code.
|
||||
|
|
@ -9,6 +9,7 @@ Added: 7.10.4
|
|||
Multi: boolean
|
||||
See-also:
|
||||
- user
|
||||
- follow
|
||||
Example:
|
||||
- --location-trusted -u user:password $URL
|
||||
- --location-trusted -H "Cookie: session=abc" $URL
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Multi: boolean
|
|||
See-also:
|
||||
- resolve
|
||||
- alt-svc
|
||||
- follow
|
||||
Example:
|
||||
- -L $URL
|
||||
---
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@
|
|||
--range (-r) 4.0
|
||||
--rate 7.84.0
|
||||
--raw 7.16.2
|
||||
--follow 8.16.0
|
||||
--referer (-e) 4.0
|
||||
--remote-header-name (-J) 7.20.0
|
||||
--remote-name (-O) 4.0
|
||||
|
|
|
|||
|
|
@ -512,8 +512,7 @@ static CURLcode http_setopts(struct OperationConfig *config,
|
|||
{
|
||||
long postRedir = 0;
|
||||
|
||||
my_setopt_long(curl, CURLOPT_FOLLOWLOCATION,
|
||||
config->followlocation);
|
||||
my_setopt_long(curl, CURLOPT_FOLLOWLOCATION, config->followlocation);
|
||||
my_setopt_long(curl, CURLOPT_UNRESTRICTED_AUTH,
|
||||
config->unrestricted_auth);
|
||||
my_setopt_str(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4);
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ struct OperationConfig {
|
|||
long happy_eyeballs_timeout_ms; /* happy eyeballs timeout in milliseconds.
|
||||
0 is valid. default: CURL_HET_DEFAULT. */
|
||||
unsigned long timecond;
|
||||
long followlocation; /* follow http redirects mode */
|
||||
HttpReq httpreq;
|
||||
long proxyver; /* set to CURLPROXY_HTTP* define */
|
||||
long ftp_ssl_ccc_mode;
|
||||
|
|
@ -264,7 +265,6 @@ struct OperationConfig {
|
|||
BIT(show_headers); /* show headers to data output */
|
||||
BIT(no_body); /* do not get the body */
|
||||
BIT(dirlistonly); /* only get the FTP dir list */
|
||||
BIT(followlocation); /* follow http redirects */
|
||||
BIT(unrestricted_auth); /* Continue to send authentication (user+password)
|
||||
when following redirects, even when hostname
|
||||
changed */
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ static const struct LongShort aliases[]= {
|
|||
{"fail-early", ARG_BOOL, ' ', C_FAIL_EARLY},
|
||||
{"fail-with-body", ARG_BOOL, ' ', C_FAIL_WITH_BODY},
|
||||
{"false-start", ARG_BOOL, ' ', C_FALSE_START},
|
||||
{"follow", ARG_BOOL, ' ', C_FOLLOW},
|
||||
{"form", ARG_STRG, 'F', C_FORM},
|
||||
{"form-escape", ARG_BOOL, ' ', C_FORM_ESCAPE},
|
||||
{"form-string", ARG_STRG, ' ', C_FORM_STRING},
|
||||
|
|
@ -2097,12 +2098,6 @@ static ParameterError opt_bool(struct OperationConfig *config,
|
|||
case C_LIST_ONLY: /* --list-only */
|
||||
config->dirlistonly = toggle; /* only list the names of the FTP dir */
|
||||
break;
|
||||
case C_LOCATION_TRUSTED: /* --location-trusted */
|
||||
config->unrestricted_auth = toggle;
|
||||
FALLTHROUGH();
|
||||
case C_LOCATION: /* --location */
|
||||
config->followlocation = toggle; /* Follow Location: HTTP headers */
|
||||
break;
|
||||
case C_MANUAL: /* --manual */
|
||||
if(toggle) /* --no-manual shows no manual... */
|
||||
return PARAM_MANUAL_REQUESTED;
|
||||
|
|
@ -2165,6 +2160,19 @@ static ParameterError opt_bool(struct OperationConfig *config,
|
|||
case C_MPTCP: /* --mptcp */
|
||||
config->mptcp = toggle;
|
||||
break;
|
||||
case C_LOCATION_TRUSTED: /* --location-trusted */
|
||||
config->unrestricted_auth = toggle;
|
||||
FALLTHROUGH();
|
||||
case C_LOCATION: /* --location */
|
||||
if(config->followlocation == CURLFOLLOW_OBEYCODE)
|
||||
warnf(global, "--location overrides --follow");
|
||||
config->followlocation = toggle ? CURLFOLLOW_ALL : 0;
|
||||
break;
|
||||
case C_FOLLOW: /* --follow */
|
||||
if(config->followlocation == CURLFOLLOW_ALL)
|
||||
warnf(global, "--follow overrides --location");
|
||||
config->followlocation = toggle ? CURLFOLLOW_OBEYCODE : 0;
|
||||
break;
|
||||
default:
|
||||
return PARAM_OPTION_UNKNOWN;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ typedef enum {
|
|||
C_FAIL_EARLY,
|
||||
C_FAIL_WITH_BODY,
|
||||
C_FALSE_START,
|
||||
C_FOLLOW,
|
||||
C_FORM,
|
||||
C_FORM_ESCAPE,
|
||||
C_FORM_STRING,
|
||||
|
|
|
|||
|
|
@ -201,6 +201,9 @@ const struct helptxt helptext[] = {
|
|||
{" --false-start",
|
||||
"Enable TLS False Start",
|
||||
CURLHELP_DEPRECATED},
|
||||
{" --follow",
|
||||
"Follow redirects per spec",
|
||||
CURLHELP_HTTP},
|
||||
{"-F, --form <name=content>",
|
||||
"Specify multipart MIME data",
|
||||
CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST | CURLHELP_IMAP |
|
||||
|
|
|
|||
|
|
@ -150,6 +150,14 @@ const struct NameValue setopt_nv_CURL_NETRC[] = {
|
|||
NVEND,
|
||||
};
|
||||
|
||||
const struct NameValue setopt_nv_CURLOPT_FOLLOWLOCATION[] = {
|
||||
NV(0L),
|
||||
NV(CURLFOLLOW_ALL),
|
||||
NV(CURLFOLLOW_OBEYCODE),
|
||||
NV(CURLFOLLOW_FIRSTONLY),
|
||||
NVEND,
|
||||
};
|
||||
|
||||
/* These options have non-zero default values. */
|
||||
static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
|
||||
NV1(CURLOPT_SSL_VERIFYPEER, 1),
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ extern const struct NameValue setopt_nv_CURLFTPSSL_CCC[];
|
|||
extern const struct NameValue setopt_nv_CURLUSESSL[];
|
||||
extern const struct NameValueUnsigned setopt_nv_CURLSSLOPT[];
|
||||
extern const struct NameValue setopt_nv_CURL_NETRC[];
|
||||
extern const struct NameValue setopt_nv_CURLOPT_FOLLOWLOCATION[];
|
||||
extern const struct NameValueUnsigned setopt_nv_CURLAUTH[];
|
||||
extern const struct NameValueUnsigned setopt_nv_CURLHSTS[];
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ test736 test737 test738 test739 test740 test741 test742 test743 test744 \
|
|||
test745 test746 test747 test748 test749 test750 test751 test752 test753 \
|
||||
test754 test755 test756 test757 \
|
||||
test780 test781 test782 test783 test784 test785 test786 test787 test788 \
|
||||
test789 test790 test791 test792 test793 \
|
||||
test789 test790 test791 test792 test793 test794 test796 test797 \
|
||||
\
|
||||
test799 test800 test801 test802 test803 test804 test805 test806 test807 \
|
||||
test808 test809 test810 test811 test812 test813 test814 test815 test816 \
|
||||
|
|
|
|||
95
tests/data/test794
Normal file
95
tests/data/test794
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
--follow
|
||||
--location
|
||||
</keywords>
|
||||
</info>
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<data crlf="yes">
|
||||
HTTP/1.1 302 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Location: %TESTNUMBER0001
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
|
||||
-foo-
|
||||
</data>
|
||||
<data1 crlf="yes">
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-bar-
|
||||
</data1>
|
||||
<datacheck crlf="yes">
|
||||
HTTP/1.1 302 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Location: %TESTNUMBER0001
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-bar-
|
||||
</datacheck>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<features>
|
||||
http
|
||||
</features>
|
||||
|
||||
<name>
|
||||
--follow + --location with custom POST method, 302 => GET
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HTTPPORT/%TESTNUMBER --no-progress-meter -X IGLOO -d moo --location --follow
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol nonewline="yes" crlf="yes">
|
||||
IGLOO /%TESTNUMBER HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
Content-Length: 3
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mooGET /%TESTNUMBER0001 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
|
||||
</protocol>
|
||||
<stderr mode="text">
|
||||
Warning: --follow overrides --location
|
||||
</stderr>
|
||||
</verify>
|
||||
</testcase>
|
||||
92
tests/data/test796
Normal file
92
tests/data/test796
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
--follow
|
||||
--location
|
||||
</keywords>
|
||||
</info>
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<data crlf="yes">
|
||||
HTTP/1.1 302 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Location: %TESTNUMBER0001
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
|
||||
-foo-
|
||||
</data>
|
||||
<data1 crlf="yes">
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-bar-
|
||||
</data1>
|
||||
<datacheck crlf="yes">
|
||||
HTTP/1.1 302 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Location: %TESTNUMBER0001
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-bar-
|
||||
</datacheck>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<features>
|
||||
http
|
||||
</features>
|
||||
|
||||
<name>
|
||||
--follow with custom POST method, 302 => GET
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -X IGLOO -d moo --follow
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol nonewline="yes" crlf="yes">
|
||||
IGLOO /%TESTNUMBER HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
Content-Length: 3
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mooGET /%TESTNUMBER0001 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
||||
94
tests/data/test797
Normal file
94
tests/data/test797
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
--follow
|
||||
--location
|
||||
</keywords>
|
||||
</info>
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<data crlf="yes">
|
||||
HTTP/1.1 308 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Location: %TESTNUMBER0001
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
|
||||
-foo-
|
||||
</data>
|
||||
<data1 crlf="yes">
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-bar-
|
||||
</data1>
|
||||
<datacheck crlf="yes">
|
||||
HTTP/1.1 308 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Location: %TESTNUMBER0001
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-bar-
|
||||
</datacheck>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<features>
|
||||
http
|
||||
</features>
|
||||
|
||||
<name>
|
||||
--follow with custom POST method, 308 => custom
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -X IGLOO -d moo --follow
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol nonewline="yes" crlf="yes">
|
||||
IGLOO /%TESTNUMBER HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
Content-Length: 3
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mooIGLOO /%TESTNUMBER0001 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
Content-Length: 3
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
moo
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
||||
Loading…
Add table
Add a link
Reference in a new issue