2017-02-20 15 views
6

Я работаю с API-интерфейсом для отдыха с аутентификацией на токенах, где у некоторых пользователей есть разрешения на загрузку файла, а некоторые нет.Почему CURL PUT завершает проверку подлинности перед загрузкой полезной нагрузки, но XHR PUT только после?

Проблема заключается в том, что некоторые пользователи без разрешения на загрузку файла пытаются загрузить (скажем 1GB-файл), я получаю сообщение об ошибке только после того, как будет загружено все 1GB.

Если я скопирую запрос как завиток из инструментов разработчиков Chrome и отправлю его через терминал, он немедленно сработает.

Я проверил команду curl с токеном пользователя, у которого есть разрешения на загрузку, он работает так, как ожидалось.

Итак, как отличается завиток от XHR?

Curl синхронно, и XHR по умолчанию не установлен. Я попытался сделать XHR синхронным, но он все равно должен загрузить весь файл, прежде чем он получит ответ.

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); 
} 

Вот точная команда локон, отформатирован для удобства чтения:

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 "[email protected]/Users/satish/abc.jpg" --compressed --insecure 

// Заголовки раздели кроме маркера

curl 'https://my-website.com/54321/my-filename.jpg' 
    -X PUT 
    -H 'X-Auth-Token: fsadsdsdaf' 
    -F "[email protected]/Users/satish/abc.jpg" 
    --compressed --insecure 

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

Чтобы исключить какое-либо поведение конкретной конечной точки API, я написал сырую нефть PHP-скрипт для проверки этого наблюдения, и это все еще так. Ниже приведен скрипт php, который я пытался загрузить.

<?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); 
?> 
+0

Вы можете показать команду CURL, которую используете? –

+0

Обновлен вопрос командой CURL. –

+0

Я отредактировал, чтобы сделать его более читаемым. Хм, любопытно. Интересно узнать, почему это так. Не знаю достаточно о PUT, чтобы быть в состоянии рассказать себе.Если в течение 48 часов ответа нет, пингуйте меня здесь в комментарии, и я поставлю щедрость на вопрос. (Те, кому нужно 48 часов) –

ответ

5

Когда ротор имеет запрос PUT с аутентификацией он сначала отправляет «пробку» без содержимого, чтобы позволить серверу отказаться от соединения до отправки любых данных.

Это не похоже нигде, кроме комментария в коде в Curl_http() в lib/http.c.

(Обратите внимание, что в версиях curl до 7.53.0 (2017-02-22, то есть более новых, чем вопрос) было отправлено bug, в котором вместо отправленного пользователем заголовка Content‑Length (или без заголовка) Content‑Length: 0.)

XHR не использует такой зонд и просто отправляет все содержимое с первоначальным запросом.

+1

Возможно, стоит отметить, что за https://github.com/curl/curl/blob/1f8023ceb5dc6b142c51fe161e0574b4d7f14b5e/lib/http.c#L1865 скручивание делает этот «пробник» нулевой длины для запросов POST. – sideshowbarker

+0

Спасибо большое @Brian, это беспокоило меня в прошлом году. –

1

Попробуйте добавить -H "Expect:" в свою команду curl.

я мог бы быть неправильно, но вот моя догадка:

  • XHR: Ожидать это запрещено имя заголовка
  • локон: добавляет Expect: 100-continue по умолчанию

 Смежные вопросы

  • Нет связанных вопросов^_^