이 답변은 많은 근거를 다루므로 세 부분으로 나뉩니다.
- CORS 프록시를 사용하여 “No Access-Control-Allow-Origin header” 문제를 해결하는 방법
- CORS 프리 플라이트를 피하는 방법
- 어떻게 해결하는 "액세스 제어 - 허용 - 원산지 헤더는 와일드 카드가 아니어야합니다" 문제
CORS 프록시를 사용하여 “No Access-Control-Allow-Origin header” 문제를 해결하는 방법
프론트 엔드 JavaScript 코드가 요청을 보내는 서버를 제어하지 않고 해당 서버의 응답 문제가 필요한 Access-Control-Allow-Origin
헤더 가 부족한 경우 에도 요청을 통해 작업을 수행 할 수 있습니다. CORS 프록시. 작동 방식을 보여주기 위해 먼저 CORS 프록시를 사용하지 않는 코드가 있습니다.
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?"))
catch
블록에 도달 하는 이유는 브라우저가 해당 코드가에서 오는 응답에 액세스하지 못하게하는 것입니다 https://example.com
. 그리고 브라우저가 그렇게하는 이유는 Access-Control-Allow-Origin
응답 헤더에 응답이 없기 때문 입니다.
이제 정확히 동일한 예이지만 CORS 프록시가 추가 된 것입니다.
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?"))
참고 : https://cors-anywhere.herokuapp.com을 다운로드 할 때 다운되었거나 사용할 수없는 경우 2-3 분만에 Heroku에 자체 CORS Anywhere 서버를 배포하는 방법은 아래를 참조하십시오.
위의 두 번째 코드 스 니펫은 요청 URL을 가져 와서 프록시 URL을 접두사로 사용 하여 https://cors-anywhere.herokuapp.com/https://example.com으로 변경하기 때문에 응답에 성공적으로 액세스 할 수 있습니다 . 해당 프록시를 통해 요청하면 다음과 같습니다.
- 에 요청을 전달합니다
https://example.com
.
- 에서 응답을받습니다
https://example.com
.
Access-Control-Allow-Origin
응답에 헤더를 추가합니다 .
- 추가 된 헤더와 함께 해당 응답을 요청 프론트 엔드 코드로 다시 전달합니다.
그런 다음 브라우저는 프론트 엔드 코드가 응답에 액세스 할 수있게합니다. Access-Control-Allow-Origin
응답 헤더가 있는 응답이 브라우저에 표시 되기 때문입니다 .
https://github.com/Rob--W/cors-anywhere/의 코드를 사용하여 자신의 프록시를 쉽게 실행할 수 있습니다 .
5 개의 명령으로 말 그대로 2-3 분만에 Heroku에 자신의 프록시를 쉽게 배포 할 수 있습니다.
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
해당 명령을 실행하면 https://cryptic-headland-94862.herokuapp.com/ 과 같은 자체 CORS Anywhere 서버가 실행됩니다 . 따라서 요청 URL 앞에 접두사를 붙이지 https://cors-anywhere.herokuapp.com
말고 대신 자신의 인스턴스 URL로 접두사를 붙이십시오 . 예를 들어, https://cryptic-headland-94862.herokuapp.com/https://example.com .
따라서 https://cors-anywhere.herokuapp.com을 사용하려고 할 때 다운되어 있음을 발견 한 경우 (아직 사용하지 않는 경우) Heroku 계정을 가져 와서 2를 가져 오는 것을 고려하십시오. 또는 3 분 동안 위 단계를 수행하여 Heroku에 자신의 CORS Anywhere 서버를 배포하십시오.
자체적으로 실행하든 https://cors-anywhere.herokuapp.com 또는 기타 개방형 프록시를 사용하든 상관없이이 솔루션은 브라우저가 CORS 프리 플라이트 OPTIONS
요청 을 수행하도록 브라우저를 트리거 하는 경우에도 작동합니다. 또한 프록시는 프리 플라이트를 성공적으로 수행하는 데 필요한 Access-Control-Allow-Headers
및 Access-Control-Allow-Methods
헤더를 다시 보냅니다 .
CORS 프리 플라이트를 피하는 방법
문제의 코드는 Authorization
헤더를 전송하기 때문에 CORS 프리 플라이트를 트리거합니다 .
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
그것 없이도 Content-Type: application/json
헤더는 프리 플라이트를 트리거합니다.
무엇 "프리 플라이트"수단 : 브라우저가를 시도하기 전에 POST
문제의 코드에서, 그것은 먼저 보내드립니다 OPTIONS
서버에 요청을 - 크로스 기원 수신에 서버가 사용 중단 된 경우 결정 POST
포함 Authorization
하고 Content-Type: application/json
헤더를.
작은 curl 스크립트와 잘 작동합니다. 데이터를 얻습니다.
로 올바르게 테스트하려면 브라우저가 전송 curl
하는 프리 플라이트 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"
… https://the.sign_in.url
실제 sign_in
URL이 무엇이든 대체됩니다 .
브라우저가 해당 OPTIONS
요청 에서 확인해야하는 응답 에는 다음과 같은 헤더가 포함되어야합니다.
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
경우 OPTIONS
응답이 그 헤더를 포함하지 않는, 브라우저는 바로 거기 중지, 심지어 보내하지 마십시오 POST
요청을. 또한 응답의 HTTP 상태 코드는 2xx (일반적으로 200 또는 204) 여야합니다. 다른 상태 코드 인 경우 브라우저가 바로 중지됩니다.
문제의 서버 OPTIONS
가 501 상태 코드로 요청에 응답하고 있습니다. 이는 요청에 대한 지원을 구현하지 않음을 나타내는 것을 의미 OPTIONS
합니다. 이 경우 다른 서버는 일반적으로 405 "Method not allowed"상태 코드로 응답합니다.
따라서 POST
서버 OPTIONS
가 405 또는 501 또는 200 또는 204 이외의 다른 요청으로 해당 요청에 응답 하거나 필요한 응답으로 응답하지 않으면 프런트 엔드 JavaScript 코드에서 해당 서버로 직접 요청 을 할 수 없습니다. 응답 헤더.
문제의 사례에 대한 프리 플라이트를 유발하지 않는 방법은 다음과 같습니다.
- 서버가
Authorization
요청 헤더를 요구하지 않고 대신 POST
요청 본문에 내장 된 인증 데이터 또는 쿼리 매개 변수에 의존 하는 경우
- 서버에
POST
본문에 Content-Type: application/json
미디어 유형 이 필요하지 않지만 대신 JSON 데이터 값 을 갖는 매개 변수 (또는 기타)를 사용 하여 POST
본문을 수락 한 경우application/x-www-form-urlencoded
json
어떻게 해결하는 "액세스 제어 - 허용 - 원산지 헤더는 와일드 카드가 아니어야합니다" 문제
다른 오류 메시지가 나타납니다.
요청의 자격 증명 모드가 'include'인 경우 응답의 'Access-Control-Allow-Origin'헤더 값이 와일드 카드 '*'가 아니어야합니다. 따라서 원본 ' http://127.0.0.1:3000 '은 액세스 할 수 없습니다. XMLHttpRequest에 의해 시작된 요청의 자격 증명 모드는 withCredentials 속성에 의해 제어됩니다.
자격 증명이 포함 된 요청의 경우 Access-Control-Allow-Origin
응답 헤더 값이 인 경우 브라우저에서 프런트 엔드 JavaScript 코드가 응답에 액세스 할 수 없습니다 *
. 대신이 경우의 값은 프론트 엔드 코드의 원점과 정확히 일치해야합니다 http://127.0.0.1:3000
.
참조 자격있는 요청과 와일드 카드 MDN이 HTTP 액세스 제어 (CORS) 기사를.
요청을 보내는 서버를 제어하는 경우이 경우를 처리하는 일반적인 방법은 Origin
요청 헤더 의 값을 가져 와서 Access-Control-Allow-Origin
응답 헤더 의 값으로 에코 / 반영하는 서버를 구성하는 것 입니다. 예를 들어, nginx의 경우 :
add_header Access-Control-Allow-Origin $http_origin
그러나 이것은 하나의 예일뿐입니다. 다른 (웹) 서버 시스템은 원점 값을 반향하는 유사한 방법을 제공합니다.
Chrome을 사용하고 있습니다. 또한 그 Chrome CORS 플러그인을 사용해 보았습니다.
Chrome CORS 플러그인 Access-Control-Allow-Origin: *
은 브라우저가 보는 응답에 헤더를 간단하게 삽입합니다 . 플러그인이 더 똑똑하다면, 가짜 Access-Control-Allow-Origin
응답 헤더 의 값을 프론트 엔드 JavaScript 코드의 실제 원점으로 설정하면 http://127.0.0.1:3000
됩니다.
따라서 테스트에도 플러그인을 사용하지 마십시오. 산만입니다. 브라우저에서 응답을 필터링하지 않고 서버에서 어떤 응답을 얻는 지 테스트하려면 curl -H
위와 같이 사용하는 것이 좋습니다 .
fetch(…)
질문 의 요청에 대한 프론트 엔드 JavaScript 코드까지 :
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
그 줄을 제거하십시오. Access-Control-Allow-*
헤더는 응답 헤더. 당신은 요청에 그들을 보내고 싶지 않습니다. 필요한 유일한 효과는 프리 플라이트를 수행하도록 브라우저를 트리거하는 것입니다.