curl: named globs in output file name for upload glob references
No binary (build failed)
—
(log yok)
| @@ -23,10 +23,10 @@ Example: | |
| # `--output` | |
| - | Write output to the given file instead of stdout. If you are using globbing to |
| - | fetch multiple documents, you should quote the URL and you can use `#` |
| - | followed by a number in the filename. That variable is then replaced with the |
| - | current string for the URL being fetched. Like in: |
| + | Write output to the given file instead of stdout. If you are using globbing in |
| + | the URL to fetch multiple documents, you should quote the URL and you can use |
| + | `#` followed by a number in the filename. That variable gets replaced with the |
| + | current glob text. Like in: |
| curl "http://{one,two}.example.com" -o "file_#1.txt" | |
| @@ -70,9 +70,9 @@ override curl's internal binary output in terminal prevention: | |
| Note that the binary output may be caused by the response being compressed, in | |
| which case you may want to use the --compressed option. | |
| - | Starting in curl 8.21.0, the separate globbing parts can be named and |
| - | referenced by their names. The case sensitive alphanumeric name is set |
| - | enclosed within angle brackets after the opening character. Examples: |
| + | Since curl 8.21.0, the separate globbing parts can be named and referenced by |
| + | their names. The case sensitive alphanumeric name is set enclosed within angle |
| + | brackets after the opening character. Examples: |
| curl "https://fun.example/{<num>one,two}.jpg" -o "save-#<num>" | |
| @@ -80,3 +80,11 @@ enclosed within angle brackets after the opening character. Examples: | |
| -o "save-#<range>.txt" | |
| Referencing a named glob that is not set, causes an error. | |
| + | |
| + | Since curl 8.21.0, you can use parts of the upload filename when it uses |
| + | globbing by setting a glob name and referencing it the same way you reference |
| + | named URL globs. For example, if you upload three files to a single fixed HTTP |
| + | URL and want to save the corresponding responses in separate files: |
| + | |
| + | curl -T 'file{<num>1,2,3}' \ |
| + | https://upload.example/ -o 'response-#<num>' |
| @@ -26,13 +26,13 @@ Upload the specified local file to the remote URL. | |
| If there is no file part in the specified URL, curl appends the local file | |
| name to the end of the URL before the operation starts. You must use a | |
| - | trailing slash (/) on the last directory to prove to curl that there is no |
| + | trailing slash (`/`) on the last directory to prove to curl that there is no |
| filename or curl thinks that your last directory name is the remote filename | |
| to use. | |
| When putting the local filename at the end of the URL, curl ignores what is on | |
| - | the left side of any slash (/) or backslash (\\) used in the filename and only |
| - | appends what is on the right side of the rightmost such character. |
| + | the left side of any slash (`/`) or backslash (`\\`) used in the filename and |
| + | only appends what is on the right side of the rightmost such character. |
| Use the filename `-` (a single dash) to use stdin instead of a given file. | |
| Alternately, the filename `.` (a single period) may be specified instead of | |
| @@ -45,9 +45,19 @@ You can specify one --upload-file for each URL on the command line. Each | |
| --upload-file + URL pair specifies what to upload and to where. curl also | |
| supports globbing of the --upload-file argument, meaning that you can upload | |
| multiple files to a single URL by using the same URL globbing style supported | |
| - | in the URL. |
| + | in the URL. Example: |
| - | When uploading to an SMTP server: the uploaded data is assumed to be RFC 5322 |
| - | formatted. It has to feature the necessary set of headers and mail body |
| - | formatted correctly by the user as curl does not transcode nor encode it |
| - | further in any way. |
| + | curl --upload-file 'file{1,2,3}' ftp://ftp.example/ |
| + | |
| + | Since curl 8.21.0, you can use parts of the upload filename when it uses |
| + | globbing by setting a glob name and referencing that in the same way you |
| + | reference named URL globs. For example, if you upload three files to a single |
| + | fixed HTTP URL and want to save the corresponding responses in separate files: |
| + | |
| + | curl -T 'file{<num>1,2,3}' \ |
| + | https://upload.example/ -o 'response-#<num>' |
| + | |
| + | When uploading to an SMTP server (aka "sending email"): the uploaded data is |
| + | assumed to be RFC 5322 formatted. It has to feature the necessary set of |
| + | headers and mail body formatted correctly by the user as curl does not |
| + | transcode nor encode it further in any way. |
| @@ -1052,11 +1052,13 @@ static CURLcode setup_outfile(struct OperationConfig *config, | |
| return result; | |
| } | |
| } | |
| - | else if(glob_inuse(&state->urlglob)) { |
| - | /* fill '#1' ... '#9' terms from URL pattern */ |
| + | else if(glob_inuse(&state->urlglob) || glob_inuse(&state->inglob)) { |
| + | /* expand '#1' ... '#9' references from URL pattern and named references |
| + | from the upload file glob */ |
| SANITIZEcode sc; | |
| CURLcode result = | |
| - | glob_match_url(&per->outfile, u->outfile, &state->urlglob, &sc); |
| + | glob_match_url(&per->outfile, u->outfile, &state->urlglob, |
| + | glob_inuse(&state->inglob) ? &state->inglob : NULL, &sc); |
| if(sc) { | |
| if(sc == SANITIZE_ERR_OUT_OF_MEMORY) | |
| @@ -703,7 +703,8 @@ CURLcode glob_next_url(char **globbed, struct URLGlob *glob) | |
| #define MAX_OUTPUT_GLOB_LENGTH (1024 * 1024) | |
| CURLcode glob_match_url(char **output, const char *filename, | |
| - | struct URLGlob *glob, SANITIZEcode *sc) |
| + | struct URLGlob *glob, struct URLGlob *glob2, |
| + | SANITIZEcode *sc) |
| { | |
| struct dynbuf dyn; | |
| const char *ifilename = filename; | |
| @@ -741,7 +742,11 @@ CURLcode glob_match_url(char **output, const char *filename, | |
| if(!curlx_str_until(&filename, &name, MAX_GLOBNAME_LEN, '>') && | |
| !curlx_str_single(&filename, '>')) { | |
| /* find the correct glob entry */ | |
| - | pat = glob_find_name(glob, &name); |
| + | if(glob_inuse(glob)) |
| + | pat = glob_find_name(glob, &name); |
| + | if(!pat && glob2 && glob_inuse(glob2)) |
| + | /* scan the second glob list if there is one */ |
| + | pat = glob_find_name(glob2, &name); |
| if(!pat) { | |
| /* when the name is given correctly, it needs to be an existing glob | |
| name, which makes this an error */ | |
| @@ -79,7 +79,8 @@ CURLcode glob_url(struct URLGlob *glob, const char *url, curl_off_t *urlnum, | |
| FILE *error); | |
| CURLcode glob_next_url(char **globbed, struct URLGlob *glob); | |
| CURLcode glob_match_url(char **output, const char *filename, | |
| - | struct URLGlob *glob, SANITIZEcode *sc); |
| + | struct URLGlob *glob, struct URLGlob *glob2, |
| + | SANITIZEcode *sc); |
| void glob_cleanup(struct URLGlob *glob); | |
| bool glob_inuse(struct URLGlob *glob); | |
| @@ -245,7 +245,7 @@ test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 \ | |
| test1978 test1979 test1980 test1981 test1982 test1983 test1984 \ | |
| \ | |
| test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ | |
| - | test2008 test2009 test2010 test2011 test2012 test2013 \ |
| + | test2008 test2009 test2010 test2011 test2012 test2013 test2014 \ |
| \ | |
| test2023 \ | |
| test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \ | |
| @@ -0,0 +1,97 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP PUT |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="headers" nocheck="yes"> |
| + | HTTP/1.1 200 OK swsbounce |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Accept-Ranges: bytes |
| + | Content-Length: 6 |
| + | Content-Type: text/html |
| + | |
| + | -foo- |
| + | </data> |
| + | <data1 crlf="headers" nocheck="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Content-Length: 20 |
| + | Content-Type: text/html |
| + | |
| + | the second response |
| + | </data1> |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | upload with glob, output name based on upload glob |
| + | </name> |
| + | <command option="no-output"> |
| + | -T '%LOGDIR/upload{%LThej%GT1,2}' http://%HOSTIP:%HTTPPORT/%TESTNUMBER --silent '--output=%LOGDIR/out-#%LThej%GT' |
| + | </command> |
| + | |
| + | <file name="%LOGDIR/upload1"> |
| + | first! |
| + | </file> |
| + | |
| + | <file2 name="%LOGDIR/upload2"> |
| + | second |
| + | </file2> |
| + | |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="headers"> |
| + | PUT /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | Content-Length: 7 |
| + | |
| + | first! |
| + | PUT /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | Content-Length: 7 |
| + | |
| + | second |
| + | </protocol> |
| + | <stdout> |
| + | %EMPTY |
| + | </stdout> |
| + | |
| + | <file name="%LOGDIR/out-1" crlf="headers"> |
| + | HTTP/1.1 200 OK swsbounce |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Accept-Ranges: bytes |
| + | Content-Length: 6 |
| + | Content-Type: text/html |
| + | |
| + | -foo- |
| + | </file> |
| + | |
| + | <file2 name="%LOGDIR/out-2" crlf="headers"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Content-Length: 20 |
| + | Content-Type: text/html |
| + | |
| + | the second response |
| + | </file2> |
| + | |
| + | </verify> |
| + | </testcase> |