Yritän hakea tietoja HP Almin REST API:sta. Se toimii melko hyvin pienellä curl-skriptillä - saan tietoni.
Nyt JavaScriptin, fetchin ja ES6:n (enemmän tai vähemmän) käyttö näyttää olevan suurempi ongelma. Saan jatkuvasti tämän virheilmoituksen:
Fetch API cannot load
. Vastaus esivalmistelupyyntöön ei't. läpäise pääsynvalvontatarkastusta: Ei 'Access-Control-Allow-Origin' -otsikkoa on ei ole pyydetyssä resurssissa. Origin 'http://127.0.0.1:3000' on ei siis ole sallittu pääsy. Vastauksen HTTP-tilakoodi oli 501. Jos läpinäkymätön vastaus palvelee tarpeitasi, aseta pyynnön tilaksi's mode. 'no-cors' noutaaksesi resurssin, jonka CORS on poistettu käytöstä.
Ymmärtääkseni tämä johtuu siitä, että yritän noutaa kyseistä tietoa localhostista ja ratkaisun pitäisi käyttää CORSia. Nyt luulin, että olen itse asiassa tehnyt sen, mutta jotenkin se joko jättää huomiotta sen, mitä kirjoitan otsikkoon, tai ongelma on jotain muuta?
Onko kyse siis toteutuksesta? Teenkö sen väärin? En valitettavasti voi tarkistaa palvelimen lokitietoja. Olen todella vähän jumissa tässä.
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));
}
Käytän Chromea. Yritin myös käyttää tuota Chrome CORS Pluginia, mutta sitten saan toisen virheilmoituksen:
Vastauksessa olevan 'Access-Control-Allow-Origin' -otsakkeen arvo ei saa olla jokerimerkki '*' kun pyynnön'valtuustietojen tila on 'include'. Origin 'http://127.0.0.1:3000' ei siis ole sallittu. pääsy. Valtakirjojen tila pyynnöissä, jotka on käynnistetty komennolla XMLHttpRequest -pyyntöä ohjataan withCredentials -attribuutilla.
Vastaus kattaa paljon asioita, joten se on jaettu kolmeen osaan:
Kuinka käyttää CORS-välityspalvelinta "Access-Control-Allow-Origin -otsikkoa ei sallita " ongelmien kiertämiseen**.
Jos et hallitse palvelinta, jolle etusivun JavaScript-koodisi lähettää pyynnön, ja palvelimen vastauksen ongelma on vain tarvittavan Access-Control-Allow-Origin
-otsikon puuttuminen, voit silti saada asiat toimimaan tekemällä pyynnön CORS-välityspalvelimen kautta. Näyttääksemme, miten se toimii, tässä on ensin koodia, joka ei käytä CORS-välityspalvelinta:
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?"))
Syy, miksi catch
-lohko osuu sinne, on se, että selain estää koodia pääsemästä käsiksi vastaukseen, joka tulee takaisin https://example.com
. Syy siihen on se, että vastauksesta puuttuu Access-Control-Allow-Origin
-vastausotsikko.
Tässä on täsmälleen sama esimerkki, mutta siihen on lisätty CORS-välityspalvelin:
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?"))
Huomautus: Jos https
https://example.com
.Access-Control-Allow-Origin
-otsikon.Access-Control-Allow-Origin
-vastausotsikko.
Voit helposti käyttää omaa välityspalvelinta käyttäen 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
, laitetaan sen sijaan oman instanssisi URL-osoite, esim. https://cryptic-headland-94862.herokuapp.com/https://example.com.
Jos siis kun yrität käyttää httpsMiten vältetään CORS-esivalo
Kysymyksessä oleva koodi käynnistää CORS-esivalvonnan, koska se lähettää Authorization
-otsikon.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Ilman sitäkin Content-Type: application/json
-otsake aiheuttaisi esivalmistuksen.
Mitä "preflight" tarkoittaa: ennen kuin selain yrittää kysymyksessä olevan koodin POST
-ohjelmaa, se lähettää ensin palvelimelle OPTIONS
-pyynnön selvittääkseen, suostuuko palvelin vastaanottamaan cross-origin POST
-ohjelmaa, joka sisältää Authorization
- ja Content-Type: application/json
-otsikot.
Se toimii melko hyvin pienellä curl-skriptillä - saan tietoni. Jotta voit testata
curl
:lla kunnolla, sinun on jäljiteltävä selaimen lähettämää esivalmistelupyyntöäOPTIONS
:
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"
...jossa https://the.sign_in.url
on korvattu todellisella URL-osoitteellasi, joka on sign_in
.
Vastauksen, jonka selaimen on nähtävä tuosta OPTIONS
-pyynnöstä, on sisällettävä tämän kaltaisia otsikoita:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Jos OPTIONS
-vastaus ei sisällä näitä otsikoita, selain pysähtyy siihen eikä edes yritä lähettää POST
-pyyntöä. Lisäksi vastauksen HTTP-tilakoodin on oltava 2xx - tyypillisesti 200 tai 204. Jos se on jokin muu tilakoodi, selain pysähtyy heti.
Kyseinen palvelin vastaa "OPTIONS"-pyyntöön tilakoodilla 501, mikä ilmeisesti tarkoittaa, että se yrittää osoittaa, ettei se tue "OPTIONS"-pyyntöjä. Muut palvelimet vastaavat tässä tapauksessa yleensä tilakoodilla 405 "Method not allowed".
Et siis koskaan pysty tekemään POST
-pyyntöjä suoraan kyseiselle palvelimelle etusivun JavaScript-koodistasi, jos palvelin vastaa OPTIONS
-pyyntöön 405- tai 501-statuksella tai muulla kuin 200- tai 204-statuksella tai jos se ei vastaa tarvittavilla vastausotsikoilla.
Tapa välttää preflightin käynnistäminen kysymyksessä mainitussa tapauksessa olisi seuraava:
Authorization
-pyyntöotsikkoa, vaan sen sijaan (esimerkiksi) luottaisi POST
-pyynnön runkoon tai kyselyparametriin upotettuihin todennustietoihin.POST
-rungossa olisi mediatyyppi Content-Type: application/json
, vaan sen sijaan hyväksyisi POST
-rungon muodossa application/x-www-form-urlencoded
, jossa on parametri nimeltä json
(tai mikä tahansa muu), jonka arvona on JSON-tieto.Miten korjata "Access-Control-Allow-Origin -otsikko ei saa olla jokerimerkki " -ongelmat**.
Saan toisen virheilmoituksen:
Vastauksessa olevan 'Access-Control-Allow-Origin' -otsikon arvo ei saa olla jokerimerkki '' kun pyynnön'valtuustietojen tila on 'include'. Alkuperä 'http://127.0.0.1:3000' ei siis ole sallittu. pääsy. Valtakirjojen tila pyynnöissä, jotka on käynnistetty komennolla XMLHttpRequest -pyyntöä ohjataan withCredentials -attribuutilla. Selaimet eivät anna etusivun JavaScript-koodin käyttää vastausta, jos
Access-Control-Allow-Origin
-vastausotsikon arvo on `. Sen sijaan arvon on tässä tapauksessa täsmälleen vastattava frontend-koodisi alkuperää,
http://127.0.0.1:3000. Katso [*Credentialed requests and wildcards*][1] MDN:n HTTP:n pääsynvalvonta (CORS) -artikkelissa. Jos hallitset palvelinta, jolle lähetät pyynnön, yleinen tapa käsitellä tätä tapausta on määrittää palvelin ottamaan
Origin-pyyntöotsikon arvo ja kaiku/heijastamaan se takaisin
Access-Control-Allow-Origin`-vastausotsikon arvoon. Esimerkiksi nginxin kanssa:
add_header Access-Control-Allow-Origin $http_origin
Käytän Chromea. Yritin myös käyttää tuota Chrome CORS Pluginia. Tuo Chrome CORS -lisäosa ilmeisesti vain yksinkertaisesti pistää
Access-Control-Allow-Origin: *
-otsikon selaimen näkemään vastaukseen. Jos lisäosa olisi fiksumpi, se asettaisi tuon väärennetynAccess-Control-Allow-Origin
-vastausotsikon arvoksi etusivun JavaScript-koodin todellisen alkuperän,http://127.0.0.1:3000
. Vältä siis kyseisen laajennuksen käyttöä edes testauksessa. Se on vain häiriötekijä. Jos haluat testata, mitä vastauksia saat palvelimelta ilman selaimen suodatusta, sinun on parempi käyttääcurl -H
kuten edellä.Mitä tulee kysymyksessä esitetyn
fetch(...)
-pyynnön etusivun JavaScript-koodiin:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Poista nämä rivit. Access-Control-Allow-*
-otsikot ovat vastauksen otsikoita. Et koskaan halua lähettää niitä pyynnössä. Ainoa vaikutus, joka sillä on, on se, että se käynnistää selaimen tekemään preflightin.
Tämä virhe ilmenee, kun asiakkaan URL-osoite ja palvelimen URL-osoite eivät täsmää, porttinumero mukaan lukien. Tässä tapauksessa sinun on otettava palvelussasi käyttöön CORS eli cross origin resource sharing.
Jos isännöit Spring REST -palvelua, löydät sen blogikirjoituksesta CORS-tuki Spring Frameworkissa.
Jos isännöit palvelua Node.js-palvelimella, niin sitten
Pysäytä Node.js-palvelin.
npm install cors --save
.
Lisää seuraavat rivit server.js-tiedostoon
var cors = require('cors')
app.use(cors()) // Käytä tätä muuttujan ilmoittamisen jälkeen