[javascript] 모드에서 페치 및 전달 사용 : no-cors

http://catfacts-api.appspot.com/api/facts?number=99Postman을 통해이 끝점을 칠 수 있습니다.JSON

또한 create-react-app를 사용하고 있으며 서버 구성을 설정하지 않으려 고합니다.

내 클라이언트 코드 fetch에서 동일한 작업을 수행 하려고 하지만 오류가 발생합니다.

요청 된 리소스에 ‘Access-Control-Allow-Origin’헤더가 없습니다. 따라서 원본 ‘ http : // localhost : 3000 ‘은 액세스 할 수 없습니다. 불투명 한 응답이 사용자의 요구를 충족시키는 경우 요청 모드를 ‘no-cors’로 설정하여 CORS가 비활성화 된 상태에서 리소스를 가져옵니다.

그래서 객체를 CORS를 비활성화하는 Fetch로 전달하려고합니다.

fetch('http://catfacts-api.appspot.com/api/facts?number=99', { mode: 'no-cors'})
  .then(blob => blob.json())
  .then(data => {
    console.table(data);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });

흥미롭게도 내가 얻는 오류는 실제로이 함수의 구문 오류입니다. fetch{mode : ‘no-cors’} 객체를 제거하고 다른 URL을 제공하면 제대로 작동하기 때문에 실제 고장이 확실하지 않습니다 .

또한 객체를 전달하려고했지만 { mode: 'opaque'}위의 원래 오류를 반환합니다.

CORS를 사용하지 않도록 설정하기 만하면됩니다. 무엇을 놓치고 있습니까?



답변

mode: 'no-cors'마술처럼 작동하지 않습니다. 사실, 브라우저에 “프론트 엔드 JavaScript 코드가 모든 상황에서 응답 본문과 헤더의 내용을 보지 못하도록 차단” 하는 효과가 있기 때문에 상황이 악화 됩니다. 물론 당신은 거의 그것을 원하지 않습니다.

프론트 엔드 JavaScript의 출처 간 요청에서 발생하는 일은 기본적으로 브라우저가 프론트 엔드 코드가 자원 간 출처에 액세스하는 것을 차단한다는 것입니다. Access-Control-Allow-Origin응답에 있으면 브라우저는 해당 차단을 완화하고 코드가 응답에 액세스 할 수 있도록합니다.

그러나 사이트 Access-Control-Allow-Origin가 응답을 보내지 않으면 프런트 엔드 코드는 해당 사이트의 응답에 직접 액세스 할 수 없습니다. 특히, 지정하여 문제를 해결할 수 없습니다 mode: 'no-cors'(것 사실 확인 응답 내용을 액세스 할 수 없습니다 귀하의 프론트 엔드 코드).

그러나 한 가지 효과 있습니다. CORS 프록시를 통해 요청을 보내면 다음 과 같이됩니다.

var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
    targetUrl = 'http://catfacts-api.appspot.com/api/facts?number=99'
fetch(proxyUrl + targetUrl)
  .then(blob => blob.json())
  .then(data => {
    console.table(data);
    document.querySelector("pre").innerHTML = JSON.stringify(data, null, 2);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });
<pre></pre>

참고 : https://cors-anywhere.herokuapp.com을 사용하려고 할 때 다운 된 경우 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 .


http://catfacts-api.appspot.com/api/facts?number=99Postman을 통해이 엔드 포인트에 도달 할 수 있습니다

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 는 Postman으로 응답에 액세스 할 수 있지만 브라우저가 프런트 엔드에서 응답 교차 출처에 액세스 할 수없는 이유를 설명합니다. 응답에 Access-Control-Allow-Origin응답 헤더가 포함되어 있지 않으면 웹앱에서 실행되는 JavaScript 코드 입니다.

http://catfacts-api.appspot.com/api/facts?number=99 에는 Access-Control-Allow-Origin응답 헤더 가 없으므로 프런트 엔드 코드가 응답 교차 출처에 액세스 할 수있는 방법이 없습니다.

브라우저가 응답을 잘 얻을 수 있으며 Postman 및 브라우저 devtools에서도 볼 수 있지만 브라우저가 코드에 노출되는 것은 아닙니다. Access-Control-Allow-Origin응답 헤더 가 없기 때문에 그렇지 않습니다 . 따라서 대신 프록시를 사용해야합니다.

프록시는 해당 사이트에 요청을하고 응답을 받고 Access-Control-Allow-Origin응답 헤더와 필요한 다른 CORS 헤더를 추가 한 다음 요청 코드로 다시 전달합니다. Access-Control-Allow-Origin헤더가 추가 된 응답 은 브라우저에 표시되므로 브라우저는 프론트 엔드 코드가 실제로 응답에 액세스 할 수 있도록합니다.


CORS를 비활성화하는 Fetch에 객체를 전달하려고합니다.

당신은 그렇게하고 싶지 않습니다. 분명히, CORS를 비활성화하고 싶다고 말하면 실제로 동일한 출처 정책 을 비활성화하려는 것 같습니다 . CORS 자체는 실제로이를 수행하는 방법입니다. CORS는 동일 출처 정책을 제한하는 방법이 아닌 완화하는 방법입니다.

그러나 어쨌든 로컬 환경에서만 브라우저 런타임 플래그를 지정하여 보안을 비활성화하고 안전하지 않게 실행하는 것과 같은 작업을 수행하거나 로컬에서 브라우저 확장을 설치하여 동일한 출처 정책을 해결할 수는 있지만 당신만을 위해 상황을 바꾸는 것입니다.

로컬로 무엇을 변경하더라도 앱을 사용하려는 다른 사람은 여전히 ​​동일한 출처 정책을 실행할 수 있으며 다른 앱 사용자를 위해이를 비활성화 할 수있는 방법이 없습니다.

당신 mode: 'no-cors'은 거의 제한된 경우를 제외하고는 실제로 사용하고 싶지 않을 것입니다. 심지어 당신이하고있는 일과 그 효과가 무엇인지 정확히 알고있는 경우에만 가능합니다. mode: 'no-cors'브라우저에서 실제로 설정 하는 내용은 “모든 상황에서 프론트 엔드 JavaScript 코드가 응답 본문 및 헤더의 내용을 보지 못하도록 차단하기”때문입니다. 대부분의 경우 그것은 분명히 당신이 원하는 것이 아닙니다.


지금까지의 경우처럼 당신이 경우 것이다 사용을 고려할 mode: 'no-cors'의 대답을 참조하십시오 제한이 불투명 한 응답에 적용 어떻게? 자세한 내용은. 요점은 다음과 같습니다.

  • 당신이에 다른 원점에서 컨텐츠를 넣어 자바 스크립트를 사용하고 제한된 경우 <script>, <link rel=stylesheet>, <img>, <video>, <audio>, <object>, <embed>, 또는 <iframe>하지만 어떤 이유로 당신이 ‘돈 – (자원의 내장 출처 간 그 허용되기 때문에 작동) 요소 t이 원하는하거나 문서 사용의 마크 업을 자원은 AS URL함으로써 그렇게 할 수 없습니다 href또는 src요소의 속성을.

  • 리소스로 수행하려는 유일한 작업은 리소스를 캐시하는 것입니다. 답변에서 언급했듯이 불투명 한 응답 에는 어떤 제한이 적용됩니까? 실제로 적용되는 시나리오는 서비스 워커를 사용하는 경우입니다.이 경우 관련 API캐시 스토리지 API 입니다.

그러나 이러한 제한된 경우에도 알아야 할 몇 가지 중요한 문제가 있습니다. 불투명 한 응답어떤 제한이 적용됩니까? 의 답변을 참조하십시오 . 자세한 내용은.


나는 또한 물건을 전달하려고했습니다. { mode: 'opaque'}

mode: 'opaque'요청 모드 는 없습니다. opaque대신 응답 의 속성 일 뿐이며 브라우저는 해당 no-cors모드 와 함께 전송 된 요청의 응답에 대해 불투명 한 속성을 설정 합니다.

그러나 우연히 opaque 라는 단어 는 응답의 본질에 대한 명백한 신호입니다.“opaque”는 볼 수 없다는 의미입니다.


답변

Laravel API에서 데이터를 가져 와서 Vue 프론트 엔드에서 사용하려고하는 localhost에서 웹 사이트를 개발하고 있다면이 문제를 보는 방법은 다음과 같습니다.

  1. Laravel 프로젝트에서 command를 실행하십시오. php artisan make:middleware Cors . 이것은 app/Http/Middleware/Cors.php당신 을 위해 만들 것입니다.
  2. handles함수 안에 다음 코드를 추가하십시오 Cors.php.

    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  3. 에서 app/Http/kernel.php, 다음 항목 추가 $routeMiddleware배열을 :

    cors => \App\Http\Middleware\Cors::class

    (같은 배열의 다른 항목이있을 것입니다 auth, guest또한 당신이이 일을했는지 확인 등 app/Http/kernel.php다른 있기 때문에kernel.php 너무 Laravel에서)

  4. 다음과 같이 액세스를 허용하려는 모든 경로에 대해 경로 등록시이 미들웨어를 추가하십시오.

    Route::group(['middleware' => 'cors'], function () {
        Route::get('getData', 'v1\MyController@getData');
        Route::get('getData2', 'v1\MyController@getData2');
    });
  5. Vue 프론트 엔드에서이 API를 호출 mounted()하지 말고 함수로 호출하십시오 data(). 또한 통화 에서 http://또는 https://URL을 사용하십시오 fetch().

Pete Houston의 블로그 기사에 대한 전체 크레딧 .


답변

간단한 해결책 : 데이터를 요청하는 PHP 파일의 맨 위에 다음을 추가하십시오.

header("Access-Control-Allow-Origin: *");


답변

나를위한 해결책은 서버 측에서만하는 것이 었습니다

C # WebClient라이브러리를 사용하여 데이터 (내 경우에는 이미지 데이터)를 가져 와서 클라이언트로 다시 보냈습니다. 선택한 서버 측 언어와 매우 유사한 것이있을 수 있습니다.

//Server side, api controller

[Route("api/ItemImage/GetItemImageFromURL")]
public IActionResult GetItemImageFromURL([FromQuery] string url)
{
    ItemImage image = new ItemImage();

    using(WebClient client = new WebClient()){

        image.Bytes = client.DownloadData(url);

        return Ok(image);
    }
}

자신의 유스 케이스에 관계없이 조정할 수 있습니다. 요점은 client.DownloadData()CORS 오류없이 작동합니다. 일반적으로 CORS 문제는 웹 사이트간에 만 발생하므로 서버에서 ‘사이트 간’요청을해도됩니다.

그런 다음 React 페치 호출은 다음과 같이 간단합니다.

//React component

fetch(`api/ItemImage/GetItemImageFromURL?url=${imageURL}`, {
        method: 'GET',
    })
    .then(resp => resp.json() as Promise<ItemImage>)
    .then(imgResponse => {

       // Do more stuff....
    )}


답변

매우 쉬운 솔루션 (구성에 2 분)은 로컬 SSL 프록시 패키지를 사용하는 것입니다.npm

사용법은 매우 간단합니다.

1. 패키지를 설치합니다 :
npm install -g local-ssl-proxy
2. local-server마스크를 사용 하여 마스크를 실행하는 동안local-ssl-proxy --source 9001 --target 9000

추신 : 교체 --target 9000-- "number of your port"--source 9001함께--source "number of your port +1"


답변