こんにちは。開発会社で自社サービス開発に携わっているもけです。
そのサービスで外部APIから提供される市町村データを使用していましたが、
その置き換え対応でつまづいたところがありました。
備忘録を兼ねてどのような対応をとったかを記します。
経緯
作っているwebアプリケーションで市町村情報を取得するのに使っていたAPI(RESAS API)が提供終了するので代替のAPI(国土交通DPF利用者API)に置き換えようとした。
手順
- 国土交通DPF利用者APIの利用方法をもとに、アカウント登録をする
- RESAS APIを使っているところを国土交通DPF利用者API(以降「代替API」と表記)に置き換える
- 登録時に発行される接続情報などをアプリ側に登録していく
- 代替APIに合わせてリクエスト時に投げる情報とレスポンスで受け取る情報の形式を見直す
詰まったところ
手順3のところでクライアント側から直接代替APIにPOST送信でリクエストを投げたところ、CORSエラーが発生してしまった。
CORSって?
- CORS(クロスオリジンリソース共有)はアプリケーションを統合するためのメカニズム
- 特定のドメインにロードされたクライアントウェブアプリケーションが異なるドメイン内のリソースと通信する方法を定義する仕組みのこと。 ※1
- CORSを使用すると、ウェブサーバーはリソースへのクロスオリジンアクセスを許可するか、明示的に選択することができ、他の許可外のリクエストを拒否することができるようになる
CORSエラー
- 許可外のドメインにアクセスしようとした場合、または上記CORSの構成が正しくされていない場合、CORSセキュリティルールに違反したとして、CORSエラーが発生する
- この正しく構成されていないというのは、必ずしも設定をミスしてしまっているわけではなく、ユーザー意図的にリクエストを拒否している場合もあるので、意図的に許可外にしていないか、ウェブシステムの構成の背景を踏まえて改善する必要がある
※2※3
状況
今回の原因は代替API側でCORSによるアクセスを許可されていないからではないかと考えられる
- 作っているwebアプリケーション側の設定を確認すると、axiosのwithCredentialsをtrueに設定している
- このオプションがtrueになっている場合、APIにアクセスするときは、CORSの仕組みを利用して対象にアクセスしようとする
- この場合代替API側でもCORSによるアクセスを許可されていないといけないが、おそらく今回は許可されておらず、それによりエラーが発生すると考えた
そのため、アクセスする際にCORSを使わないリクエストを送る方法があればできるのではと考えた。
解決法
解決するためのアイデアは以下の2つである。
案1:クライアント側でaxiosのCORSを使わないリクエストを送るようにする
メリット
- レスポンスが速い
- サーバーへの負荷が少ない
デメリット
- CORS制限を受けやすい
- 今回対応する部分だけ、axiosのwithCredentialというオプションを外す必要があり、個別の対応になるため、将来的なメンテナンス性が下がる原因になる
- 案2に比べるとセキュリティ面で不安がある
案2:サーバー側のすでにCORSでクロスドメインアクセス許可済みのAPIを経由して代替APIを呼び出すようにし、アクセス時にCORSを使わなくていいようにする。
メリット
- CORS制限を受けにくい
- 他実装部分と対応を変える必要がないため、メンテナンスがしやすい
- 重要情報の管理など、セキュリティが高い
デメリット
- レスポンスが遅い可能性あり
- サーバーへの負荷が多い
いずれの策も取ること自体は可能であったが、メリットデメリットを考慮した結果、
今回は案2を選択した。
この対策により、代替APIへのアクセスが可能になった。
終わりに
今回の対応ではレスポンス面での課題が残ったが、これは作っているwebアプリケーション内における情報取得の仕方やその情報の保持方法で改善が見込めそうだったので、今後改善に取り組む。
参考
※1
https://aws.amazon.com/jp/what-is/cross-origin-resource-sharing/
※2
https://developer.mozilla.org/en-US/docs/Glossary/CORS
※3
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors