Bandau gauti tam tikrus duomenis iš "HP Alm" REST API. Tai veikia gana gerai su nedideliu curl scenarijumi - gaunu duomenis.
Dabar tai daryti su "JavaScript", fetch ir ES6 (daugiau ar mažiau) atrodo didesnė problema. Nuolat gaunu šį klaidos pranešimą:
Fetch API negali įkelti
nepraėjo prieigos kontrolės patikrinimo: Nėra 'Access-Control-Allow-Origin' antraštės. yra prašomame išteklyje. Kilmė 'http://127.0.0.1:3000' yra todėl prieiga neleidžiama. Atsakymas turėjo HTTP būsenos kodą 501. Jei jūsų poreikiams tinka neskaidrus atsakymas, nustatykite užklausos' režimą į 'no-cors', kad gautumėte išteklių su išjungtu CORS.
Suprantu, kad taip yra dėl to, kad bandau gauti tuos duomenis iš savo vietinio prieglobsčio (localhost), o sprendimas turėtų būti naudojant CORS. Dabar maniau, kad iš tikrųjų tai padariau, bet kažkodėl jis arba ignoruoja tai, ką rašau antraštėje, arba problema yra kažkokia kita?
Taigi, ar yra įgyvendinimo problema? Ar aš tai darau neteisingai? Deja, negaliu patikrinti serverio žurnalų. Aš tikrai šiek tiek įstrigau.
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('GET', 'POST', 'OPTIONS');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(sign_in, {
//mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
Aš naudoju Chrome. Taip pat bandžiau naudoti tą "Chrome CORS" įskiepį, bet tada gaunu kitą klaidos pranešimą:
Atsakymo antraštės 'Access-Control-Allow-Origin' vertė neturi būti pakaitinis simbolis '*', kai užklausos'įgaliojimų režimas yra 'include'. Todėl kilmė 'http://127.0.0.1:3000' neleidžiama prieiga. Įgaliojimų režimas užklausose, inicijuotose XMLHttpRequest, kontroliuojamas atributu withCredentials.
Šis atsakymas apima daug temų, todėl jis suskirstytas į tris dalis:
Kaip naudoti CORS tarpinį serverį, kad išvengtumėte "Access-Control-Allow-Origin" antraštės nebuvimo problemų
Jei nekontroliuojate serverio, į kurį siunčiama jūsų "JavaScript" kodo užklausa, ir iš to serverio gaunamo atsakymo problema yra ta, kad nėra būtinos Access-Control-Allow-Origin
antraštės, vis tiek galite pasiekti, kad viskas veiktų, - užklausą pateikite per CORS tarpinį serverį. Kad parodytumėte, kaip tai veikia, pirmiausia pateikiame kodą, kuriame nenaudojamas CORS tarpinis serveris:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Priežastis, dėl kurios čia patenka catch
blokas, yra ta, kad naršyklė neleidžia šiam kodui pasiekti atsakymo, kuris grįžta iš https://example.com
. Taip naršyklė daro todėl, kad atsakyme nėra atsakymo antraštės Access-Control-Allow-Origin
.
Dabar pateikiame lygiai tokį patį pavyzdį, tik su pridėtu CORS tarpininku:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Pastaba: Jei https
https://example.com
.https://example.com
.Access-Control-Allow-Origin
.Access-Control-Allow-Origin
atsakymo antrašte.
Galite lengvai paleisti savo tarpinį serverį naudodami kodą iš https://github.com/Rob--W/cors-anywhere/.git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
https://cors-anywhere.herokuapp.com
, vietoj jo įrašykite savo egzemplioriaus URL, pvz., https://cryptic-headland-94862.herokuapp.com/https://example.com.
Taigi, jei bandydami naudoti httpsOPTIONS
užklausą, nes tokiu atveju tarpinis serveris taip pat siunčia atgal Access-Control-Allow-Headers
ir Access-Control-Allow-Methods
antraštes, reikalingas, kad išankstinė užklausa būtų sėkminga.Kaip išvengti CORS išankstinės patikros
Klausime pateiktas kodas sukelia CORS išankstinį patikrinimą, nes siunčia Authorization
antraštę.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Net ir be jos Content-Type: application/json
antraštė taip pat sukeltų išankstinį patikrinimą.
Ką reiškia "preflight": prieš naršyklei bandant klausime pateikto kodo POST
, ji pirmiausia išsiunčia OPTIONS
užklausą serveriui, kad nustatytų, ar serveris sutinka priimti cross-origin POST
, kuriame yra Authorization
ir Content-Type: application/json
antraštės.
Tai veikia gana gerai su nedideliu curl scenarijumi - gaunu savo duomenis. Norint tinkamai išbandyti su
curl
, reikia imituoti išankstinęOPTIONS
užklausą, kurią siunčia naršyklė:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
...su https://the.sign_in.url
pakeistu bet kokiu jūsų tikruoju sign_in
URL.
Atsakyme, kurį naršyklė turi matyti iš šios OPTIONS
užklausos, turi būti tokios antraštės:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Jei OPTIONS
atsakyme nėra šių antraščių, naršyklė sustos ir net nebandys siųsti POST
užklausos. Be to, atsakymo HTTP būsenos kodas turi būti 2xx - paprastai 200 arba 204. Jei tai bet koks kitas būsenos kodas, naršyklė iškart sustos.
Į OPTIONS
užklausą serveris atsako 501 būsenos kodu, o tai reiškia, kad jis bando nurodyti, jog nepalaiko OPTIONS
užklausų. Kiti serveriai šiuo atveju paprastai atsako 405 būsenos kodu "Metodas neleidžiamas".
Taigi niekada negalėsite tiesiogiai iš savo "JavaScript" kodo pateikti POST
užklausų tam serveriui, jei serveris į šią OPTIONS
užklausą atsakys kodu 405 arba 501, arba bet kokiu kitu kodu, išskyrus 200 arba 204, arba jei neatsakys šiomis būtinomis atsakymo antraštėmis.
Klausime nurodytu atveju būtų galima išvengti išankstinio patikrinimo paleidimo:
Authorization
užklausos antraštės, bet vietoj to (pvz.,) remiasi autentifikavimo duomenimis, įterptais į POST
užklausos kūną arba kaip užklausos parametras.POST
užklausos kūne būtų Content-Type: application/json
medijos tipas, bet vietoj to priėmė POST
užklausos kūną kaip application/x-www-form-urlencoded
su parametru, pavadintu json
(ar kaip nors kitaip), kurio reikšmė yra JSON duomenysKaip išspręsti "Access-Control-Allow-Origin antraštė neturi būti pakaitinis simbolis " problemas
gaunu kitą klaidos pranešimą:
Atsakymo antraštės 'Access-Control-Allow-Origin' reikšmė neturi būti pakaitinis simbolis '', kai užklausos'įgaliojimų režimas yra 'include'. Todėl kilmė 'http://127.0.0.1:3000' neleidžiama prieiga. Įgaliojimų režimas užklausų, inicijuotų XMLHttpRequest, kontroliuojamas atributu withCredentials. Užklausos, į kurią įtraukti įgaliojimai, atveju naršyklės neleis jūsų priekiniam "JavaScript" kodui pasiekti atsakymo, jei atsakymo antraštės
Access-Control-Allow-Origin
reikšmė yra `. Vietoj to šiuo atveju vertė turi tiksliai atitikti jūsų priekinio kodo kilmę, t. y.
http://127.0.0.1:3000. Žr. skyrių [*Atsakomosios užklausos ir pakaitiniai ženklai*][1] MDN straipsnyje HTTP prieigos kontrolė (CORS). Jei kontroliuojate serverį, į kurį siunčiate užklausą, įprastas šio atvejo sprendimo būdas yra sukonfigūruoti serverį taip, kad jis paimtų
Originužklausos antraštės reikšmę ir atkartotų ją atgal į
Access-Control-Allow-Origin` atsakymo antraštės reikšmę. Pavyzdžiui, naudojant "nginx": kalba: lang-none -->
add_header Access-Control-Allow-Origin $http_origin
Naudoju Chrome. Taip pat bandžiau naudoti šį "Chrome CORS" įskiepį Tas "Chrome CORS" įskiepis, matyt, paprasčiausiai įveda
Access-Control-Allow-Origin: *
antraštę į atsakymą, kurį mato naršyklė. Jei įskiepis būtų protingesnis, jis būtų nustatęs netikrosAccess-Control-Allow-Origin
atsakymo antraštės reikšmę į tikrąją jūsų "JavaScript" kodo kilmę -http://127.0.0.1:3000
. Todėl venkite naudoti šį įskiepį net bandymams. Jis tik blaško dėmesį. Jei norite išbandyti, kokius atsakymus gaunate iš serverio, kai naršyklė jų nefiltruoja, geriau naudokitecurl -H
, kaip nurodyta pirmiau.Dėl klausime pateikto "JavaScript" kodo, skirto
fetch(...)
užklausai:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Pašalinkite šias eilutes. `Access-Control-Allow-`` antraštės yra atsakymo* antraštės. Jų niekada nenorite siųsti užklausoje. Vienintelis poveikis, kurį tai turės, tai paskatinti naršyklę atlikti išankstinį patikrinimą.
Ši klaida įvyksta, kai kliento URL ir serverio URL nesutampa, įskaitant prievado numerį. Tokiu atveju turite įjungti savo paslaugos CORS, t. y. kryžminio kilmės išteklių dalijimosi, funkciją.
Jei talpinate "Spring REST" paslaugą, tai galite rasti tinklaraščio įraše CORS palaikymas "Spring Framework" sistemoje.
Jei paslaugą talpinate naudodami Node.js serverį, tuomet
Sustabdykite "Node.js" serverį.
npm install cors --save
Į savo server.js įrašykite šias eilutes
var cors = require('cors')
app.use(cors()) // Naudokite tai po kintamojo deklaracijos