Why does CURL PUT complete authentication before loading the payload, but only after XHR PUT?

I work with a rest API with token authentication, where some users have permissions to download the file, and some do not.

The problem is that some users without permission to download the file try to download (say a 1GB file), I get an error response only after all 1GB has been downloaded.

If I copy the request as a curl from the Chrome developer tools and send it through the terminal, it will work immediately.

I checked the curl command with a token from a user who has download permissions, it works as expected.

So, how is curl different from XHR?

Curl is synchronous, and XHR is not the default. I tried to make XHR synchronous, but it still needs to download the whole file before it gets a response.

function upload(file, url) {
    var xhr = new XMLHttpRequest();
    xhr.upload.key = xhr.key = file.key
    xhr.upload.addEventListener("progress", updateProgress);
    xhr.addEventListener("error", transferFailed);
    xhr.addEventListener("abort", transferCanceled);
    xhr.open("PUT", url);
    xhr.setRequestHeader("Content-Type", "application/octet-stream");
    xhr.setRequestHeader("X-Auth-Token", service.token.token);


    xhr.addEventListener("readystatechange", function (e) {
      if (this.readyState === 4 && this.status >= 200 && this.status < 300) {
        transferComplete(e)
      }
      if (this.readyState === 4 && this.status === 0) {
        transferFailed(e)
      }
      if (this.status >= 400) {
        transferFailed(e)
      }

    });


    xhr.send(file);
}

Here is the exact curl command, formatted for readability:

curl 'https://my-website.com/54321/my-filename.jpg' 
  -X PUT   
  -H 'Pragma: no-cache' 
  -H 'Origin: https://my-website.com' 
  -H 'Accept-Encoding: gzip, deflate, sdch, br' 
  -H 'Accept-Language: en-US,en;q=0.8' 
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36' 
  -H 'Content-Type: application/octet-stream' 
  -H 'Accept: */*' 
  -H 'Cache-Control: no-cache' 
  -H 'X-Auth-Token: fsadgsdgs' 
  -H 'Referer: https://some-allowed-origin-referrer.com/' 
  -H 'Connection: keep-alive' 
  -H 'Content-Length: 86815' 
  -F "data=@/Users/satish/abc.jpg" --compressed --insecure 

// Headers are split except for the token

  curl 'https://my-website.com/54321/my-filename.jpg' 
    -X PUT  
    -H 'X-Auth-Token: fsadsdsdaf' 
    -F "data=@/Users/satish/abc.jpg" 
    --compressed --insecure 

--- Update 02/21/2017 ---

To rule out any behavior on a particular API endpoint, I wrote a crude PHP script to test this observation, and this is still the case. Below is the PHP script I was trying to download.

<?php
/**
 * If I comment out the below lines, then curl is failing immediately.
 * But XHR doesn't
 **/

// http_response_code(400);
// return;

/* PUT data comes in on the stdin stream */
$putdata = fopen( "php://input", "r" );

/* Open a file for writing */
$file = fopen( "/Users/satish/Work/Development/htdocs/put-test/wow.jpg", "w" );

/* Read the data 1 KB at a time
   and write to the file */
while ( $data = fread( $putdata, 1024 ) ) {
    fwrite( $file, $data );
}

/* Close the streams */
fclose( $file );
fclose( $putdata );
?>
+6
source share
2 answers

curl PUT , "" , .

, , , Curl_http() lib/http.c.

( , curl 7.53.0 (2017-02-22, , ), Content‑Length ( ) Content‑Length: 0.)

XHR .

+5

-H "Expect:" curl.

, , :

  • XHR: -
  • rot: Expect: 100-continue
+1

Source: https://habr.com/ru/post/1015111/


All Articles