CORS, Preflight 요청 및 OPTIONS 방법

전제



이 게시물은 최소한의 컨텍스트를 제공하고 종종 불투명하다고 간주되는 주제에 대한 호기심을 심어주기 위한 목적으로 가볍게 읽을 수 있도록 작성되었습니다. CORS는 모든 웹 개발자가 쉽게 이해할 수 있는 간단한 HTTP 헤더 메커니즘입니다.


먼저 Same-origin Policy 에 대해 알아야 합니다. 한 원본의 스크립트가 다른 원본의 리소스와 상호 작용하는 방식을 제한하는 브라우저 내장 메커니즘입니다.

동일 출처 🏠🏠



가장 간단한 경우부터 시작하겠습니다. 리소스를 보유하고 있는 서버와 리소스를 요청하는 클라이언트는 모두 동일한 origin ( <scheme>://<hostname><port> ) 아래에 있습니다.

서버는 http://localhost:3000에 노출되고 HTML 파일을 반환하여 HTTP GET /에 응답합니다.

For the sake of brevity, the code examples only show what I want to focus on. If something is not clear, use the various Accompanying source code (same-origin) you'll find.




server.js


server.get("/", (_, reply) => {
  reply.sendFile("index.html");
});

server.get("/me", (_, reply) => {
  reply.status(200).send({ nickname: "didof" });
});


클라이언트에 도착한 HTML은 경로와 연결된 리소스/me에 대해 동일한 출처의 서버에 요청하고 화면에 닉네임을 표시합니다.


index.html


<p>Nickname: <output></output></p>

<script>
    // This runs on http://localhost:3000
    fetch("/me") // fetch("http://localhost:3000/me")
    .then((res) => res.json())
    .then((res) => {
        document.querySelector("output").textContent = res.nickname;
    });
</script>


동일 출처 정책이 준수되면 페이로드에 액세스할 수 있습니다. CORS가 필요 없고 프리플라이트 요청이 필요하지 않습니다.


교차 출처 🏠🏭



이제 클라이언트는 http://localhost:8000에 노출되고 리소스가 있는 서버는 http://localhost:3000에 노출됩니다. 구성표와 호스트 이름이 같더라도 포트가 다르므로 서로 다른 출처입니다.

In the real world, the following concept is found when the client on https://mywebsite.com requires a resource to http://api.foo.it/bar



Accompanying source code (cross-origin)




index.html


<script>
// This runs on http://localhost:8000
const request = new Request("http://localhost:3000/me", {
  method: "GET",
});

fetch(request)
.then((res) => res.json())
.then((res) => { ... })
</script>


짐작할 수 있듯이 CORS 오류가 있습니다.



콘솔의 오류는 문제를 명확하게 설명합니다. 수정합시다. 서버에서 우리는 CORS를 관리합니다.


server.js


server.register(fastifyCors, {
  origin: "http://localhost:8000",
});


I use fastify here, but any framework offers its own way of managing CORS. It's just headers added to the response, nothing more - you can of course append them manually.



이제 응답에 access-control-allow-origin가 포함되고 값은 http://localhost:8000가 됩니다.



서버는 기본적으로 응답을 펼치기 위해 요청을 발행한 브라우저에 권한을 부여합니다.


사전 요청 🏠✉️🏭



CORS 요청에는 두 가지 유형이 있습니다.
  • 간단한 요청
  • 실행 전 요청

  • 사용되는 것은 브라우저에 의해 결정됩니다. 지금까지 클라이언트는 criteria에 맞기 때문에 간단한 요청을 수행했습니다.

    이 게시물의 목적을 위해 브라우저에서 프리플라이트 요청을 강제하려면 요청에 사용자 정의 헤더를 추가하기만 하면 된다는 점만 알면 됩니다.

    Accompanying source code (cross-origin-preflight)




    index.html


    <script>
    const headers = new Headers();
    headers.append("X-CUSTOM-HEADER", "foo");
    
    // This runs on http://localhost:8000
    const request = new Request("http://localhost:3000/me", {
      method: "GET",
      headers,
    });
    
    fetch(request)
      .then((res) => res.json())
      .then((res) => { ... })
    


    그리고 브라우저가 하나가 아닌 두 개의 요청을 실행하기에 충분합니다.



    사용된 방법은 OPTIONS 이며 서버에서 정의된 request url 에 대한 정보에 대한 쿼리로 해석됩니다.

    브라우저는 실행 전 요청에 일부 헤더도 추가합니다. Access-Control-Request-HeadersAccess-Control-Request-Method를 상대 값으로 표시합니다.


    브라우저는 다양한 헤더 중 특정GET을 포함하는 X-CUSTOM-HEADER 요청을 만들기 위해 서버에 권한을 요청하고 있습니다.

    매우 관대하도록 구성된 이 특정 서버는 값이 요청된 값을 미러링하는 access-control-allow-headers 및 모든 메서드가 허용됨을 알리는 access-control-allow-methods로 응답합니다.



    엄지척👍 입니다. 그런 다음 브라우저는 원하는 요청을 수행할 수 있습니다.

    분명히 어떤 이유로 서버가 사용자 지정 헤더의 존재를 허용하지 않도록 지시받은 경우 오류가 발생합니다.




    언급했듯이 이것은 단순한 채팅입니다. 관심이 있는 경우 아래에 추가로 참조할 수 있는 몇 가지 참고 자료가 있습니다. I 💖 HTML의 H!

    리소스 🕳️🐇


  • CORS Tutorial: A Guide to Cross-Origin Resource Sharing
  • Same-origin policy
  • CORS
  • Fetch API
  • Accompanying GitHub source code

  • 연락하기



  • 🐙 GitHub

  • 좋은 웹페이지 즐겨찾기