API Trunking PROXY와 통신할 수 없는 CORS

개시하다


CORS를 통해 API 등 외부 자원을 확보하기 위해 PROXY(서버)를 통해 대응했습니다.주요 내용은 당시 학습한 브라우저 주변의 규약과 대응 방법이다.
(이것은 메타웨더라는 일기예보 API를 이용한 비망록)
백엔드 처리가 가능한 환경이지만 이런 보도가 드물기 때문에 프록시 서버를 사용하기로 했다.

localhost에서 API에 요청


그래서 다음과 같은 오류가 발생했습니다.
Access to XMLHttpRequest at 'https://www.metaweather.com/api/location/1118108' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
"Access-Control-Collow-Origin이 요청한 http 헤더에 없기 때문에 CORS의 제한과 관련이 있습니다."오류가 발생했습니다.
같은 원시 정책의 통제 대상이라는 이유에서다.
추가 조사 결과 이번에 사용한 API는 JSONP도 CORS도 지원하지 않아 브라우저에서 호출할 수 없었다.

Same-Origin Policy

  • 동일한 원시 전략
  • SOP
  • SOP는 브라우저 수준에서 서로 다른 사냥꾼자리에 대한 방해를 방지함으로써 사용자의 안전을 확보하는 메커니즘이다.
    덕분에 XSS, CSRF 등의 취약성을 막을 수 있었다.
    이번에 제작된 일기예보 애플리케이션에 사용된 Ajax는 XMLHttpRequest(서버에서 비동기적으로 데이터를 얻는 메커니즘)로, SOP의 제약 대상이다.

    CORS(Cors)

  • 올리브 자원 공유
  • Cross Origin Resource Sharing
  • CORS는 SOP 제한에 대해'다른 올리브 가지에서 수신 데이터를 보내고 싶을 때'에 존재한다.
    CORS란 SOP를 예외적으로 무효화하고 정보를 안전하게 전달하는 브라우저 구조를 말합니다.이 메커니즘 덕분에 서로 다른 사냥꾼자리 간에도 통신이 가능하다.
    cherome와 사파리 등 일반적으로 사용하는 브라우저는 기본적으로 CORS를 지원한다.

    사냥꾼자리?


    오리온은 호스트 포트 번호를 계획하는 그룹으로 모두 같으면 같은 오리온이고 하나가 다르면 다른 오리온이다.https://www.example.com:80/login위의 URL을 예로 들면 다음과 같습니다.
    시나리오(프로토콜) = https호스트 = www.example.com포트 = 80

    견우가 달라서 다른 사냥꾼자리가 있어요.


    이번 경우 Giithub 페이지에 공개된 사이트의 URL은https://sohh85.github.io/weather-app/일기예보 APIhttps://www.metaweather.com이처럼 견우가 달라 또 다른 사냥꾼자리가 됐다.

    같은 사냥꾼자리의 구체적인 예


    MDN에서 사냥꾼자리에 대해 이렇게 설명했다.
    다음 표에서는 행의 URL이 http://store.company.com/dir/page.html와 동일한지 여부를 비교합니다.
    |URL | 결과 | 이유 |
    |:-----------------|:------------------|:------------------|
    |http://store.company.com/dir2/other.html|동일한 사냥꾼자리만 |경로가 다르다|
    |http://store.company.com/dir/inner/another.html|동일한 사냥꾼자리만 |경로가 다르다|
    |https://store.company.com/page.html| 불일치 | 서로 다른 프로토콜 |
    |http://store.company.com:81/dir/page.html| 불일치 | 포트 번호가 다름 (http://기본값은 80 포트) |
    |http://news.company.com/dir/page.html| 불일치 | 호스트가 다름 |

    개발 환경에서의 대응


    다음은 웹 패키지의 편리한 기능DevServer을 사용하는 방법과 확장 기능을 사용하는 방법 두 가지를 소개한다.

    1. 웹 팩-dev-server의 프록시 기능


    구성 파일에 다음을 추가하십시오.
    임의의 경로/api를 다른 서버https://www.metaweather.com로 프록시할 수 있습니다.전달할 URL을 target: 'ココ'에 지정합니다.
    module.exports = {
        configureWebpack: {
            devServer: {
                proxy: {
                    '/api': {
                        target: 'https://www.metaweather.com',
                    }
                }
            }
        }
    }
    
    이렇게 요청합니다.
     axios.get("/api/location/1118108")
    

    2. 기능 확장


    크롬의 확장 기능을 사용하여 개발 환경에서 API 요청을 수행할 수 있습니다.
    클릭Allow CORS, "Chrome에 추가"

    Chrome의 화면 오른쪽 상단에서 추가 확장 기능을 클릭하십시오.그림에서 보듯이 아이콘 C가 주황색으로 변하면 OK.

    이렇게 다시 통신하면 CORS에 가려지지 않고 자원을 얻을 수 있다.

    공식 환경에서 프록시 지원


    이번에 사용한 APIMetaWeather는 CORS를 지원하지 않습니다.통신을 위해서는 백엔드 프로그램의 트렁킹과 API 요청이 필요합니다.
    그래서 이번에는 허쿠 노드.js로 중계 서버를 만들어서 대응하기로 했습니다.

    프록시 서버


    에이전트는 일본어로 에이전트를 의미하며 고객과 서버 사이에서 릴레이 역할로 구성된 서버를 말한다.프록시 서버는 클라이언트가 보기에 서버이고 서버가 보기에 클라이언트이다.
    악성 프록시에 의해 ID와 비밀번호 등을 빼돌릴 수 있으므로 무료로 제공되는 공개 프록시를 이용할 때는 주의가 필요하다.그리고 프록시 서버를 끼고 있으면 통신이 느려진다는 단점도 있다.

    리소스 확보를 위한


    https://medium.com/@deepak13245/using-react-hooks-to-handle-api-calls-d6bb4ae91188
    이 기사를 참조하여 PROXY(서버)로 대응했습니다.2021년 2월까지 아래의 절차에 따라 순조롭게 완성하였다.
    1. cors-anywhereを git clone
    
    2. Herokuのスターターガイドを参照しデプロイ
    
    3. axios.getメソッド内のURLを変更
    
    4. Heroku環境変数を設定し、アクセスを許可するオリジンを指定
    

    1.cors-anywhere clone


    다음 명령을 실행하여 cors-anywhere 항목을 만듭니다.
    git clone https://github.com/Rob--W/cors-anywhere.git
    

    2. 시작 설명서를 참조하여 설계


    https://devcenter.heroku.com/ja/articles/getting-started-with-nodejs
    공식 문서를 참조하십시오.상당히 통일된 만큼 절차에 따라 진행하면 된다.
    데이터베이스 설정 등 필요하지 않은 항목을 무시하십시오.

    3. axios.get 메서드의 URL 변경


    프록시 URL + 리소스를 가져오는 URL과 같이 기술하십시오.
    이렇게 하면 도메인 이름이 이 사이트와 다른 API로 전달됩니다.https://cors-anywhere.herokuapp.com가 프록시 URL이면 이렇게 요청됩니다.
     axios.get("https://cors-anywhere.herokuapp.com/https://www.metaweather.com/api/location/1118108")
    

    4.heroku 환경 변수 설정


    다음 키워드 이름, 값을 Origin으로 지정하고 환경 변수를 heroku에 등록합니다.이렇게 하면 부당한 방문과 사용을 방지할 수 있으니 가능한 한 설정해 주십시오.
    사소한 선택 등cors-anywhere의 Read.me을 확인해 주세요.CORSANYWHERE_WHITELIST - 액세스 허용CORSANYWHERE_BLACKLIST→액세스 거부
    heroku에 설정된 환경 변수는 프록시 서버의 서버입니다.js에 기술된 다음 소스 코드로 읽습니다.
    var originBlacklist = parseEnvList(process.env.CORSANYWHERE_BLACKLIST);
    var originWhitelist = parseEnvList(process.env.CORSANYWHERE_WHITELIST);
    function parseEnvList(env) {
      if (!env) {
        return [];
      }
      return env.split(',');
    }
    
    터미널에서 heroku config 명령을 실행하여 환경 변수가 설정되었는지 확인하십시오.

    cherome 개발자 도구로 확인

    NetworkName에서 표시할 항목을 선택→Preview순으로 클릭하면 이미지처럼 AJAX 통신을 통해 API에서 얻은 값을 확인할 수 있습니다.
    이미지처럼 실질적으로 가치를 얻었다면 프록시 서버를 이용한 AJAX 통신은 성공했을 것이다.
    preview.png NetworkName에서 표시할 항목을 선택하고→Headers 순서대로 클릭하면 요청과 응답 제목을 그림처럼 확인할 수 있습니다.
    dev-tool.png
    응답 페이지Access-Control-Allow-Origin: * 에서 모든 올리브소가 접근이 허용된 것을 알 수 있다.
    다음 내용에 응답 머릿말이 부여되면
    Access-Control-Allow-Origin: http://example.com
    
    "http://example.com부터? 그럼 자원을 줄게."
    이런 판단은 서버 쪽에서 할 수 있고 CORS를 통해 안전한 통신을 할 수 있다.

    총결산


    이상입니다.
    코로나와 같은 독창적 정책 등 지금까지 이해할 수 없었던 부분을 배우면서 수출을 시도했다.
    만약 이 보도가 다른 사람을 도울 수 있다면 매우 좋겠다.

    참고 문헌

  • Using React hooks to handle API calls
  • cors-anywhere(GitHub)
  • 원래 자원 공유(CORS)
  • Heroku Star guide(Node.js)
  • DevServer | webpack
  • 좋은 웹페이지 즐겨찾기