1 21. PUT/POST without a known auth to use (possibly no auth required): 3 4 (When explicitly set to use a multi-pass auth when doing a POST/PUT, 5 libcurl should immediately go the Content-Length: 0 bytes route to avoid 6 the first send all data phase, step 2. If told to use a single-pass auth, 7 goto step 3.) 8 9 Issue the proper PUT/POST request immediately, with the correct 10 Content-Length and Expect: headers. 11 12 If a 100 response is received or the wait for one times out, start sending 13 the request-body. 14 15 If a 401 (or 407 when talking through a proxy) is received, then: 16 17 If we have "more than just a little" data left to send, close the 18 connection. Exactly what "more than just a little" means will have to be 19 determined. Possibly the current transfer speed should be taken into 20 account as well. 21 22 NOTE: if the size of the POST data is less than MAX_INITIAL_POST_SIZE (when 23 CURLOPT_POSTFIELDS is used), libcurl will send everything in one single 24 write() (all request-headers and request-body) and thus it will 25 unconditionally send the full post data here. 26 272. PUT/POST with multi-pass auth but not yet completely negotiated: 28 29 Send a PUT/POST request, we know that it will be rejected and thus we claim 30 Content-Length zero to avoid having to send the request-body. (This seems 31 to be what IE does.) 32 333. PUT/POST as the last step in the auth negotiation, that is when we have 34 what we believe is a completed negotiation: 35 36 Send a full and proper PUT/POST request (again) with the proper 37 Content-Length and a following request-body. 38 39 NOTE: this may very well be the second (or even third) time the whole or at 40 least parts of the request body is sent to the server. Since the data may 41 be provided to libcurl with a callback, we need a way to tell the app that 42 the upload is to be restarted so that the callback will provide data from 43 the start again. This requires an API method/mechanism that libcurl 44 doesn't have today. See below. 45 46Data Rewind 47 48 It will be troublesome for some apps to deal with a rewind like this in all 49 circumstances. I'm thinking for example when using 'curl' to upload data 50 from stdin. If libcurl ends up having to rewind the reading for a request 51 to succeed, of course a lack of this callback or if it returns failure, will 52 cause the request to fail completely. 53 54 The new callback is set with CURLOPT_IOCTLFUNCTION (in an attempt to add a 55 more generic function that might be used for other IO-related controls in 56 the future): 57 58 curlioerr curl_ioctl(CURL *handle, curliocmd cmd, void *clientp); 59 60 And in the case where the read is to be rewinded, it would be called with a 61 cmd named CURLIOCMD_RESTARTREAD. The callback would then return CURLIOE_OK, 62 if things are fine, or CURLIOE_FAILRESTART if not. 63 64Backwards Compatibility 65 66 The approach used until now, that issues a HEAD on the given URL to trigger 67 the auth negotiation could still be supported and encouraged, but it would 68 be up to the app to first fetch a URL with GET/HEAD to negotiate on, since 69 then a following PUT/POST wouldn't need to negotiate authentication and 70 thus avoid double-sending data. 71 72 Optionally, we keep the current approach if some option is set 73 (CURLOPT_HEADBEFOREAUTH or similar), since it seems to work fairly well for 74 POST on most servers. 75