Edited at

ローカルのHTMLファイルでfetchを試す & CORSとその回避策


やりたいこと


  • 気軽にfetchを試したい


    • 今後いろんなコードを試す為



  • いちいち仮想マシンとかAPIサーバーとかフロントのサーバー立てたくない

  • ローカルのHTMLファイルに素のJavaScriptを書いて試したい

  • 気軽に叩ける公開APIが欲しい


気軽に叩ける公開API

今回はzipcloudで試す。NHKも良い感じ


出来たコード


  • fetchメソッドの戻り値はpromise

  • レスポンス.json()メソッドの戻り値はpromiseなので同期的に処理したい場合はawaitする

  • ハンドリングとか何もしていない


test.html

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<input type="button" value="取得" onclick="apiRequest()" />
<div id="export"></div>
<script>
async function apiRequest() {
const downloadUrl =
"http://zipcloud.ibsnet.co.jp/api/search?zipcode=1620825";
const response = await fetch(downloadUrl);
const json = await response.json();
const string = JSON.stringify(json);
const exportTarget = document.getElementById("export");
exportTarget.innerHTML = string;
}
</script>
</body>
</html>


CORSでハマったので調べた


  • オリジン間リソース共有

  • Cross Origin Resource Sharing の略

  • Originというのはプロトコル、ドメイン、ポートの組み合わせ

  • リクエスト元のオリジンとリクエスト先のオリジンが異なることをクロスオリジンという

  • 異なるオリジン間でリソースを共有できるということをCORSという

  • ChromeなどのWebブラウザはクロスオリジンでAjax通信を行った場合、CORSの条件を満たしていないとデータをくれない

  • fetch APIの勉強をしているAさんがいると仮定して例えると(まあ私なんですが)


    • AさんがPC上にHTMLファイルを作成し、その中にhttp://hoge.com:80へAjaxのリクエストを行うコードを書いてChromeを使って実行する

    • 仮にAさんのPCに割り当てられたグローバルアドレスがhttp://10.1.2.3:3000だった場合、Aさんのグローバルアドレスとhoge.comのアドレスのオリジン(プロトコル、ドメイン、ポートの組み合わせ)が異なる為、クロスオリジンとなる

    • クロスオリジンである場合Chromeはリクエストを行なったのち、レスポンスヘッダーにAccess-Control-Allow-Originキーとそのバリューとしてhttp://10.1.2.3:3000(もしくはワイルドカードの*など)が存在するかを確認し存在しない場合はCORS出来ないとしてエラーを起こしデータを教えてくれない

    • その他にもJSONPとかいうのを使った回避策もあるらしいけど調べていない(古いし覚える必要なさそう)



  • CORSして良いかどうかの判定を行なっているのは基本はCORSの仕様に準拠したWebブラウザ

  • CORSの仕様に準拠していないWebブラウザだったり、そもそもWebブラウザ以外の何かしらからリクエストを送った場合はそのままデータを得られる

  • Chromeの拡張機能でCORS回避することが出来るものがある



  • ちゃんとした開発であればCORSのことを考えて実装するべきだが、今回のような場合は回避したいだけなので拡張機能を使う

CORSの実現はリクエスト元やリクエスト先のやりとりで行われているものと思っていましたが、実際にはもう一人Webブラウザという登場人物が存在し間を取り持っていて、重要な検証の部分を担っているということでした。

実際の開発の観点では、ブラウザを介さずに回避する方法はあるので、やろうと思えば他サイトのリソースを無理矢理共有することも出来そうで、CORS機能(とその検証機能)はあんまり意味無さそうに思えた。