javascript - Miért bukik el a CURL PUT-ja a hitelesítésnél a teher felküldése előtt, míg az XHR PUT csak utána?
Egy REST API-val dolgozom token alapú hitelesítéssel, ahol egyes felhasználóknak van jogosultságuk fájl feltöltésére, míg másoknak nincs.
A probléma az, amikor egy felhasználó, akinek nincs engedélye fájl feltöltésére, megpróbál feltölteni (mondjuk egy 1 GB-os fájlt), a hibaválaszt csak azután kapom, hogy az egész 1 GB fel lett töltve.
Ha a kérést a Chrome fejlesztői eszközeiből curl-ként másolom és a terminálon keresztül küldöm, az azonnal sikertelen.
Leteszteltem a curl parancsot egy olyan felhasználó tokenjével, akinek van jogosultsága feltöltésre, és a várt módon működik.
Szóval, miben különbözik a curl az XHR-től?
A Curl szinkron, az XHR alapértelmezés szerint nem. Megpróbáltam szinkronná tenni az XHR-t, de még mindig fel kell töltenie az egész fájlt, mielőtt választ kapna.
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);
}
Itt van a pontos curl parancs, olvashatóság érdekében formázva:
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
//Fejlécek eltávolítva a token kivételével
curl 'https://my-website.com/54321/my-filename.jpg'
-X PUT
-H 'X-Auth-Token: fsadsdsdaf'
-F "data=@/Users/satish/abc.jpg"
--compressed --insecure
--- Frissítés 2017-02-21 ---
Annak kizárása érdekében, hogy bármilyen API végpont-specifikus viselkedésről van szó, írtam egy nyers PHP szkriptet ennek a megfigyelésnek a tesztelésére, és ez még mindig igaz. Lentebb látható a PHP szkript, amelyet feltöltésre próbáltam.
<?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 );
?>
Válasz #1
Amikor a curl PUT kérést küld hitelesítés szükségessége mellett, először egy tartalom nélküli „felderítő” kérést küld, hogy a szervernek lehetősége legyen megtagadni a kapcsolatot, mielőtt bármilyen adat elküldésre kerülne.
Úgy tűnik, hogy ez sehol sem dokumentált, kivéve egy megjegyzést a Curl_http() kódban a lib/http.c fájlban.
(Vegye figyelembe, hogy a curl 7.53.0 előtti verzióiban (2017‑02‑22, azaz az adott kérdésnél újabbak) volt egy hiba, amely során a felhasználó által megadott Content‑Length fejléc (vagy ha nem volt fejléc) lett elküldve a Content‑Length: 0 helyett.)
Az XHR nem valósít meg ilyen próbát, és egyszerűen elküldi az összes tartalmat a kezdeti kéréssel.
Válasz #2
Próbáld meg hozzáadni a -H "Expect:" opciót a curl parancshoz.
Lehet, hogy tévedek, de itt van a megérzésem:
- XHR: Az Expect tiltott fejlécnév
- curl: alapértelmezés szerint hozzáadja a
Expect: 100-continuekódot