http: reject resumed uploads
No binary (build failed)
—
(log yok)
| @@ -339,8 +339,8 @@ files. | |
| ## How do I tell curl to resume a transfer? | |
| - | curl supports resumed transfers both ways on both FTP and HTTP. Try the `-C` |
| - | option. |
| + | curl supports resumed HTTP, FTP and SFTP downloads as well as resumed FTP and |
| + | SFTP uploads. Try the `-C` option. |
| ## Why does my posting using -F not work? | |
| @@ -25,10 +25,8 @@ the FTP server command SIZE is not used by curl. | |
| Use "-C -" to instruct curl to automatically find out where/how to resume the | |
| transfer. It then uses the given output/input files to figure that out. | |
| - | When using this option for HTTP uploads using POST or PUT, functionality is |
| - | not guaranteed. The HTTP protocol has no standard interoperable resume upload |
| - | and curl uses a set of headers for this purpose that once proved working for |
| - | some servers and have been left for those who find that useful. |
| + | HTTP uploads using POST or PUT cannot be resumed. curl returns an error when |
| + | you combine this option with such an upload. |
| This command line option is mutually exclusive with --range: you can only use | |
| one of them for a single transfer. | |
| @@ -37,6 +37,10 @@ When doing uploads with FTP, the resume position is where in the local/source | |
| file libcurl should try to resume the upload from and it then appends the | |
| source file to the remote target file. | |
| + | HTTP uploads using POST or PUT cannot be resumed. curl_easy_perform(3) returns |
| + | CURLE_BAD_FUNCTION_ARGUMENT when this option is set to a non-zero value for |
| + | such an upload. |
| + | |
| If you need to resume a transfer beyond the 2GB limit, use | |
| CURLOPT_RESUME_FROM_LARGE(3) instead. | |
| @@ -38,6 +38,10 @@ When doing uploads with FTP, the resume position is where in the local/source | |
| file libcurl should try to resume the upload from and it appends the source | |
| file to the remote target file. | |
| + | HTTP uploads using POST or PUT cannot be resumed. curl_easy_perform(3) returns |
| + | CURLE_BAD_FUNCTION_ARGUMENT when this option is set to a non-zero value for |
| + | such an upload. |
| + | |
| # DEFAULT | |
| 0, not used | |
| @@ -2378,35 +2378,11 @@ static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq) | |
| static CURLcode http_resume(struct Curl_easy *data, Curl_HttpReq httpreq) | |
| { | |
| - | if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) && |
| + | if((HTTPREQ_POST == httpreq || HTTPREQ_POST_FORM == httpreq || |
| + | HTTPREQ_POST_MIME == httpreq || HTTPREQ_PUT == httpreq) && |
| data->state.resume_from) { | |
| - | /********************************************************************** |
| - | * Resuming upload in HTTP means that we PUT or POST and that we have |
| - | * got a resume_from value set. The resume value has already created |
| - | * a Range: header that will be passed along. We need to "fast forward" |
| - | * the file the given number of bytes and decrease the assume upload |
| - | * file size before we continue this venture in the dark lands of HTTP. |
| - | * Resuming mime/form posting at an offset > 0 has no sense and is ignored. |
| - | *********************************************************************/ |
| - | |
| - | if(data->state.resume_from < 0) { |
| - | /* |
| - | * This is meant to get the size of the present remote-file by itself. |
| - | * We do not support this now. Bail out! |
| - | */ |
| - | data->state.resume_from = 0; |
| - | } |
| - | |
| - | if(data->state.resume_from && !data->req.authneg) { |
| - | /* only act on the first request */ |
| - | CURLcode result; |
| - | result = Curl_creader_resume_from(data, data->state.resume_from); |
| - | if(result) { |
| - | failf(data, "Unable to resume from offset %" FMT_OFF_T, |
| - | data->state.resume_from); |
| - | return result; |
| - | } |
| - | } |
| + | failf(data, "HTTP upload cannot be resumed"); |
| + | return CURLE_BAD_FUNCTION_ARGUMENT; |
| } | |
| return CURLE_OK; | |
| } | |
| @@ -873,16 +873,25 @@ static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl) | |
| return result; | |
| } | |
| + | static CURLcode check_post_resume(struct OperationConfig *config) |
| + | { |
| + | if(config->use_resume && |
| + | (config->resume_from || config->resume_from_current)) { |
| + | errorf("(%d) HTTP upload cannot be resumed", |
| + | CURLE_BAD_FUNCTION_ARGUMENT); |
| + | config->synthetic_error = TRUE; |
| + | return CURLE_BAD_FUNCTION_ARGUMENT; |
| + | } |
| + | return CURLE_OK; |
| + | } |
| + | |
| static CURLcode setopt_post(struct OperationConfig *config, CURL *curl) | |
| { | |
| CURLcode result = CURLE_OK; | |
| switch(config->httpreq) { | |
| case TOOL_HTTPREQ_SIMPLEPOST: | |
| - | if(config->resume_from) { |
| - | errorf("cannot mix --continue-at with --data"); |
| - | result = CURLE_FAILED_INIT; |
| - | } |
| - | else { |
| + | result = check_post_resume(config); |
| + | if(!result) { |
| MY_SETOPT_STR(curl, CURLOPT_POSTFIELDS, | |
| curlx_dyn_ptr(&config->postdata)); | |
| my_setopt_offt(curl, CURLOPT_POSTFIELDSIZE_LARGE, | |
| @@ -893,11 +902,8 @@ static CURLcode setopt_post(struct OperationConfig *config, CURL *curl) | |
| /* free previous remainders */ | |
| curl_mime_free(config->mimepost); | |
| config->mimepost = NULL; | |
| - | if(config->resume_from) { |
| - | errorf("cannot mix --continue-at with --form"); |
| - | result = CURLE_FAILED_INIT; |
| - | } |
| - | else { |
| + | result = check_post_resume(config); |
| + | if(!result) { |
| result = tool2curlmime(curl, config->mimeroot, &config->mimepost); | |
| if(!result) | |
| result = my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost); | |
| @@ -1930,6 +1930,10 @@ TESTCASES = \ | |
| test2207 \ | |
| test2208 \ | |
| \ | |
| + | test2270 \ |
| + | test2271 \ |
| + | test2272 \ |
| + | \ |
| test2300 \ | |
| test2301 \ | |
| test2302 \ | |
| @@ -6,7 +6,7 @@ HTTP | |
| HTTP PUT | |
| HTTP proxy | |
| HTTP Digest auth | |
| - | Resume |
| + | Range |
| Content-Range | |
| CUSTOMREQUEST | |
| </keywords> | |
| @@ -70,10 +70,10 @@ proxy | |
| digest | |
| </features> | |
| <name> | |
| - | HTTP POST --digest with PUT and resumed upload and modified method |
| + | HTTP Digest range upload with a modified method |
| </name> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT --range 0-4 -X GET |
| </command> | |
| <file name="%LOGDIR/%TESTNUMBER"> | |
| test | |
| @@ -85,7 +85,7 @@ test | |
| <protocol crlf="headers"> | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| - | Content-Range: bytes 2-4/5 |
| + | Content-Range: bytes 0-4/0 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| @@ -94,13 +94,13 @@ Content-Length: 0 | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", uri="/%TESTNUMBER", response="6af4d89c952f4dd4cc215a6878dc499d" | |
| - | Content-Range: bytes 2-4/5 |
| + | Content-Range: bytes 0-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| - | Content-Length: 3 |
| + | Content-Length: 5 |
| - | st |
| + | test |
| </protocol> | |
| </verify> | |
| </testcase> | |
| @@ -7,7 +7,6 @@ HTTP PUT | |
| HTTP proxy | |
| HTTP Digest auth | |
| Resume | |
| - | Content-Range |
| CUSTOMREQUEST | |
| </keywords> | |
| </info> | |
| @@ -69,10 +68,10 @@ proxy | |
| digest | |
| </features> | |
| <name> | |
| - | HTTP PUT with Digest auth, resumed upload and modified method, twice |
| + | HTTP Digest uploads with zero resume offset and custom method |
| </name> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 -T %LOGDIR/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload2 -T %LOGDIR/%TESTNUMBER -u auser:apasswd --digest -x http://%HOSTIP:%HTTPPORT -C 2 -X GET |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 -T %LOGDIR/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload2 -T %LOGDIR/%TESTNUMBER -u auser:apasswd --digest -x http://%HOSTIP:%HTTPPORT -C 0 -X GET |
| </command> | |
| <file name="%LOGDIR/%TESTNUMBER"> | |
| test | |
| @@ -84,7 +83,6 @@ test | |
| <protocol crlf="headers"> | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| @@ -93,16 +91,14 @@ Content-Length: 0 | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", uri="/%TESTNUMBER.upload1", response="198aa9b6acb4b0c71d02a197a5e41f54" | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| - | Content-Length: 3 |
| + | Content-Length: 5 |
| - | st |
| + | test |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload2 HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| @@ -111,13 +107,12 @@ Content-Length: 0 | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload2 HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", uri="/%TESTNUMBER.upload2", response="d711f0d2042786d930de635ba0d1a1d0" | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| - | Content-Length: 3 |
| + | Content-Length: 5 |
| - | st |
| + | test |
| </protocol> | |
| </verify> | |
| </testcase> | |
| @@ -6,13 +6,12 @@ | |
| HTTP | |
| HTTP PUT | |
| Resume | |
| - | Content-Range |
| </keywords> | |
| </info> | |
| # Server-side | |
| <reply> | |
| - | <data crlf="headers"> |
| + | <data crlf="headers" nocheck="yes"> |
| HTTP/1.1 200 OK swsclose | |
| Date: Tue, 09 Nov 2010 14:49:00 GMT | |
| Server: test-server/fake | |
| @@ -30,7 +29,7 @@ Content-Type: text/html | |
| http | |
| </server> | |
| <name> | |
| - | HTTP PUT with resume from end of already-uploaded file |
| + | HTTP PUT rejects automatic upload resume |
| </name> | |
| <file name="%LOGDIR/test%TESTNUMBER.txt"> | |
| 012345678 | |
| @@ -45,32 +44,20 @@ HTTP PUT with resume from end of already-uploaded file | |
| 012345678 | |
| </file> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T%LOGDIR/test%TESTNUMBER.txt -C - |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T%LOGDIR/test%TESTNUMBER.txt -C - --no-progress-meter |
| </command> | |
| </client> | |
| # Verify data after the test has been "shot" | |
| <verify> | |
| - | # curl does not do a HEAD request on the remote file so it has no idea whether |
| - | # it can skip part of the file or not. Instead, it sends the entire file. |
| - | <protocol crlf="headers"> |
| - | PUT /%TESTNUMBER HTTP/1.1 |
| - | Host: %HOSTIP:%HTTPPORT |
| - | Content-Range: bytes 0-99/100 |
| - | User-Agent: curl/%VERSION |
| - | Accept: */* |
| - | Content-Length: 100 |
| + | <errorcode> |
| + | 43 |
| + | </errorcode> |
| + | <stderr mode="text"> |
| + | curl: (43) HTTP upload cannot be resumed |
| + | </stderr> |
| + | <protocol nonewline="yes"> |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| </protocol> | |
| </verify> | |
| </testcase> | |
| @@ -4,6 +4,7 @@ | |
| <keywords> | |
| HTTP | |
| HTTP POST | |
| + | Resume |
| </keywords> | |
| </info> | |
| @@ -25,10 +26,10 @@ Mime | |
| http | |
| </server> | |
| <name> | |
| - | HTTP multipart formpost with only a 100 reply |
| + | HTTP multipart formpost with zero resume offset and only a 100 reply |
| </name> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -F name=daniel |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -F name=daniel -C 0 |
| </command> | |
| </client> | |
| @@ -6,8 +6,6 @@ HTTP | |
| HTTP PUT | |
| HTTP proxy | |
| HTTP Digest auth | |
| - | Resume |
| - | Content-Range |
| CUSTOMREQUEST | |
| </keywords> | |
| </info> | |
| @@ -70,10 +68,10 @@ proxy | |
| digest | |
| </features> | |
| <name> | |
| - | HTTP Digest with PUT, resumed upload, modified method and SHA-256 |
| + | HTTP Digest upload with a modified method and SHA-256 |
| </name> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -X GET |
| </command> | |
| <file name="%LOGDIR/%TESTNUMBER"> | |
| test | |
| @@ -85,7 +83,6 @@ test | |
| <protocol crlf="headers"> | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| @@ -94,13 +91,12 @@ Content-Length: 0 | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", uri="/%TESTNUMBER", response="fbed69f9f3fd304c8f1acb1a43eb32688b933c0e28055c16b926cbcec070aeed", algorithm=SHA-256 | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| - | Content-Length: 3 |
| + | Content-Length: 5 |
| - | st |
| + | test |
| </protocol> | |
| </verify> | |
| </testcase> | |
| @@ -6,8 +6,6 @@ HTTP | |
| HTTP PUT | |
| HTTP proxy | |
| HTTP Digest auth | |
| - | Resume |
| - | Content-Range |
| CUSTOMREQUEST | |
| </keywords> | |
| </info> | |
| @@ -70,10 +68,10 @@ proxy | |
| digest | |
| </features> | |
| <name> | |
| - | HTTP Digest PUT, resumed upload, modified method, SHA-256 and userhash |
| + | HTTP Digest upload with a modified method, SHA-256 and userhash |
| </name> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -X GET |
| </command> | |
| <file name="%LOGDIR/%TESTNUMBER"> | |
| test | |
| @@ -85,7 +83,6 @@ test | |
| <protocol crlf="headers"> | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| @@ -94,13 +91,12 @@ Content-Length: 0 | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| Authorization: Digest username="fddc3bc7b753b73ab0848fd83cb20cbbca971258eb8d20c941dd5e0b010d66be", realm="testrealm", nonce="1053604144", uri="/%TESTNUMBER", response="22d200df1fd02a9d3a7269ef5bbb5bf8f16f184a74907df9b64a3755489c0b42", algorithm=SHA-256, userhash=true | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| - | Content-Length: 3 |
| + | Content-Length: 5 |
| - | st |
| + | test |
| </protocol> | |
| </verify> | |
| </testcase> | |
| @@ -6,8 +6,6 @@ HTTP | |
| HTTP PUT | |
| HTTP proxy | |
| HTTP Digest auth | |
| - | Resume |
| - | Content-Range |
| CUSTOMREQUEST | |
| </keywords> | |
| </info> | |
| @@ -70,10 +68,10 @@ proxy | |
| sha512-256 | |
| </features> | |
| <name> | |
| - | HTTP Digest with PUT, resumed upload, SHA-512-256, userhash |
| + | HTTP Digest upload with a modified method and SHA-512-256 |
| </name> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -X GET |
| </command> | |
| <file name="%LOGDIR/%TESTNUMBER"> | |
| test | |
| @@ -85,7 +83,6 @@ test | |
| <protocol crlf="headers"> | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| @@ -94,13 +91,12 @@ Content-Length: 0 | |
| GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER HTTP/1.1 | |
| Host: %HOSTIP:%HTTPPORT | |
| Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", uri="/%TESTNUMBER", response="691867f4a06c79fd0a175c1857e3df7015f6fff3ce8676497d2f1f805b5a8eca", algorithm=SHA-512-256 | |
| - | Content-Range: bytes 2-4/5 |
| User-Agent: curl/%VERSION | |
| Accept: */* | |
| Proxy-Connection: Keep-Alive | |
| - | Content-Length: 3 |
| + | Content-Length: 5 |
| - | st |
| + | test |
| </protocol> | |
| </verify> | |
| </testcase> | |
| @@ -0,0 +1,46 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP POST |
| + | HTTP MIME |
| + | Resume |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | <data nocheck="yes"> |
| + | HTTP/1.1 200 OK swsclose |
| + | |
| + | </data> |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <features> |
| + | Mime |
| + | form-api |
| + | </features> |
| + | <server> |
| + | http |
| + | </server> |
| + | <tool> |
| + | lib%TESTNUMBER |
| + | </tool> |
| + | <name> |
| + | reject HTTP form and MIME upload resume |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol nonewline="yes"> |
| + | |
| + | </protocol> |
| + | </verify> |
| + | </testcase> |
| @@ -0,0 +1,38 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP POST |
| + | Resume |
| + | error detection |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | reject automatic HTTP data upload resume |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -d foobar -C - |
| + | </command> |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <errorcode> |
| + | 43 |
| + | </errorcode> |
| + | <stderr mode="text"> |
| + | curl: (43) HTTP upload cannot be resumed |
| + | </stderr> |
| + | </verify> |
| + | </testcase> |
| @@ -0,0 +1,42 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP POST |
| + | HTTP MIME |
| + | Resume |
| + | error detection |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <features> |
| + | Mime |
| + | </features> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | reject automatic HTTP form upload resume |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -F name=value -C - |
| + | </command> |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <errorcode> |
| + | 43 |
| + | </errorcode> |
| + | <stderr mode="text"> |
| + | curl: (43) HTTP upload cannot be resumed |
| + | </stderr> |
| + | </verify> |
| + | </testcase> |
| @@ -5,12 +5,11 @@ | |
| HTTP | |
| HTTP PUT | |
| Resume | |
| - | Content-Range |
| </keywords> | |
| </info> | |
| # Server-side | |
| <reply> | |
| - | <data> |
| + | <data nocheck="yes"> |
| HTTP/1.1 200 OK swsclose | |
| </data> | |
| @@ -22,7 +21,7 @@ HTTP/1.1 200 OK swsclose | |
| http | |
| </server> | |
| <name> | |
| - | HTTP PUT with resume |
| + | HTTP PUT rejects upload resume |
| </name> | |
| <file name="%LOGDIR/test%TESTNUMBER.txt"> | |
| 012345678 | |
| @@ -37,25 +36,20 @@ HTTP PUT with resume | |
| 012345678 | |
| </file> | |
| <command> | |
| - | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T%LOGDIR/test%TESTNUMBER.txt -C 50 |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T%LOGDIR/test%TESTNUMBER.txt -C 50 --no-progress-meter |
| </command> | |
| </client> | |
| # Verify data after the test has been "shot" | |
| <verify> | |
| - | <protocol crlf="headers"> |
| - | PUT /%TESTNUMBER HTTP/1.1 |
| - | Host: %HOSTIP:%HTTPPORT |
| - | Content-Range: bytes 50-99/100 |
| - | User-Agent: curl/%VERSION |
| - | Accept: */* |
| - | Content-Length: 50 |
| + | <errorcode> |
| + | 43 |
| + | </errorcode> |
| + | <stderr mode="text"> |
| + | curl: (43) HTTP upload cannot be resumed |
| + | </stderr> |
| + | <protocol nonewline="yes"> |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| - | 012345678 |
| </protocol> | |
| </verify> | |
| </testcase> | |
| @@ -27,7 +27,10 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER -d foobar -C 3 | |
| # Verify data after the test has been "shot" | |
| <verify> | |
| <errorcode> | |
| - | 2 |
| + | 43 |
| </errorcode> | |
| + | <stderr mode="text"> |
| + | curl: (43) HTTP upload cannot be resumed |
| + | </stderr> |
| </verify> | |
| </testcase> | |
| @@ -294,6 +294,7 @@ TESTS_C = \ | |
| lib2032.c \ | |
| lib2082.c \ | |
| lib2118.c \ | |
| + | lib2270.c \ |
| lib2301.c \ | |
| lib2302.c \ | |
| lib2304.c \ | |
| @@ -0,0 +1,104 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * This software is licensed as described in the file COPYING, which |
| + | * you should have received as part of this distribution. The terms |
| + | * are also available at https://curl.se/docs/copyright.html. |
| + | * |
| + | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| + | * copies of the Software, and permit persons to whom the Software is |
| + | * furnished to do so, under the terms of the COPYING file. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | #include "first.h" |
| + | |
| + | static CURLcode test_lib2270(const char *URL) |
| + | { |
| + | CURL *curl = NULL; |
| + | curl_mime *mime = NULL; |
| + | curl_mimepart *part; |
| + | struct curl_httppost *formpost = NULL; |
| + | struct curl_httppost *lastptr = NULL; |
| + | CURLFORMcode formrc; |
| + | CURLcode result = TEST_ERR_MAJOR_BAD; |
| + | |
| + | if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { |
| + | curl_mfprintf(stderr, "curl_global_init() failed\n"); |
| + | return TEST_ERR_MAJOR_BAD; |
| + | } |
| + | |
| + | curl = curl_easy_init(); |
| + | if(!curl) { |
| + | curl_mfprintf(stderr, "curl_easy_init() failed\n"); |
| + | goto test_cleanup; |
| + | } |
| + | |
| + | mime = curl_mime_init(curl); |
| + | if(!mime) { |
| + | curl_mfprintf(stderr, "curl_mime_init() failed\n"); |
| + | goto test_cleanup; |
| + | } |
| + | part = curl_mime_addpart(mime); |
| + | if(!part) { |
| + | curl_mfprintf(stderr, "curl_mime_addpart() failed\n"); |
| + | goto test_cleanup; |
| + | } |
| + | result = curl_mime_name(part, "field"); |
| + | if(result) |
| + | goto test_cleanup; |
| + | result = curl_mime_data(part, "value", CURL_ZERO_TERMINATED); |
| + | if(result) |
| + | goto test_cleanup; |
| + | |
| + | easy_setopt(curl, CURLOPT_URL, URL); |
| + | easy_setopt(curl, CURLOPT_MIMEPOST, mime); |
| + | easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)1); |
| + | result = curl_easy_perform(curl); |
| + | if(result != CURLE_BAD_FUNCTION_ARGUMENT) { |
| + | curl_mfprintf(stderr, "MIME resume returned %d, expected %d\n", |
| + | (int)result, CURLE_BAD_FUNCTION_ARGUMENT); |
| + | result = TEST_ERR_FAILURE; |
| + | goto test_cleanup; |
| + | } |
| + | |
| + | easy_setopt(curl, CURLOPT_MIMEPOST, NULL); |
| + | formrc = curl_formadd(&formpost, &lastptr, |
| + | CURLFORM_COPYNAME, "field", |
| + | CURLFORM_COPYCONTENTS, "value", |
| + | CURLFORM_END); |
| + | if(formrc) { |
| + | curl_mfprintf(stderr, "curl_formadd() failed with code %d\n", |
| + | (int)formrc); |
| + | result = TEST_ERR_FAILURE; |
| + | goto test_cleanup; |
| + | } |
| + | |
| + | easy_setopt(curl, CURLOPT_HTTPPOST, formpost); |
| + | easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)-1); |
| + | result = curl_easy_perform(curl); |
| + | if(result != CURLE_BAD_FUNCTION_ARGUMENT) { |
| + | curl_mfprintf(stderr, "form resume returned %d, expected %d\n", |
| + | (int)result, CURLE_BAD_FUNCTION_ARGUMENT); |
| + | result = TEST_ERR_FAILURE; |
| + | goto test_cleanup; |
| + | } |
| + | result = CURLE_OK; |
| + | |
| + | test_cleanup: |
| + | curl_easy_cleanup(curl); |
| + | curl_mime_free(mime); |
| + | curl_formfree(formpost); |
| + | curl_global_cleanup(); |
| + | return result; |
| + | } |