やりたかったこと
AWS AmplifyでホストするNext.jsのWebアプリがあります。
SORACOM SIMを挿したデバイスのブラウザでこのWebアプリを起動し、SORACOM Funkのエントリポイントを叩いてLambdaに接続したかったです。ちなみにHTTP通信には、Axiosというライブラリを使いました。
問題
エラーに直面しました!
そして最終的にこのエントリポイントは叩けませんでした。
- [blocked] The page at https://foo.bar.amplifyapp.com/hoge was not allowed to display insecure content from http://funk.soracom.io/. (675-73bf76adf43e6dc1.js, line 5)
- Not allowed to request resource
- XMLHttpRequest cannot load http://funk.soracom.io/ due to access control checks.
- Error occurred: – B {stack: "B@https://foo.bar.amplifyapp.com/…ext/static/chunks/675-73bf76adf43e6dc1.js:5:82357", message: "Network Error", name: "AxiosError", …}`
GPTくんに聞きました。
- 最初のエラーは、HTTPSで提供されるページが、HTTPプロトコルを使用して外部リソースにアクセスしようとしているため、ブラウザにブロックされたことを示しています。
- XMLHttpRequest cannot load http://funk.soracom.io/ due to access control checks.というエラーは、CORSポリシーにより、クロスオリジンリクエストがブロックされたことを示しています。CORSポリシーは、ウェブページが他のドメインのリソースに安全にアクセスできるようにブラウザに指示するものです。
HTTPとHTTPSが混在していること、CORSの2点が問題のようです。
試みたこと
1. HTTPとHTTPSの混在対策
Webアプリは要件的にどうしてもHTTPSの必要がありました。セキュリティ要件があったのと、カメラにアクセスするにはHTTPSが必須のようです。一方ソラコムのエントリポイントはhttpのみです。
上のエラーではErrorではなく、Warningだったので、問題ないかもと思ったのですが、PCブラウザではErrorになっていました。(SORACOM SIM挿してないのでそもそもうまくいきませんが)
つまり、今振り返って考えると、後述のCORSを見るまでもなく、この時点で既に詰んでいたとも言えます(笑)
2. CORS対策
2-1. メタデータサービスを使ってみる
ドキュメントはこちら。
[許可するオリジン]にアプリのオリジンのURLを入れてみましたが解決に至りませんでした。
2-2. Amplifyのカスタムヘッダーを設定
次はAmplify側をいじってみます。
カスタムヘッダーを設定してみました。
結果がこちら。これもダメでした。
2-3. リクエストのヘッダーにAccess-Control-Allow-Originを入れる。
CORSを許可するには、レスポンス側の設定をしてあげないといけないのは、過去に経験からわかってはいたものの、藁をも掴む思いで試してみました。案の定何の解決にもなりませんでした
過去の経験↓
import axios from "axios";
const postToSoracom = async (val: string) => {
interface Payload {
val: string;
}
const payload: Payload = {
val,
};
const url = "http://funk.soracom.io";
const headers = {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*", // これを入れてみた
};
const response = await axios.post(url, payload, {
headers: headers,
});
return response;
};
2-4. サーバーサイドからAPIを叩く
フロントのブラウザから叩くのが問題なら、Next.jsだしサーバーサイドから叩けばあるいは...という話もありましたが、うまくいかず。
ただ、ここはあまり深掘りできなったので、完全にダメだったとは言い切れないです。
サーバーサイドから叩こうとして参照したサイトはこの辺。
最後に
今回の失敗から色々学ぶことができました。
また、余談ですがスマホでのデバッグで、コンソールを見たい時にこちらの方法でうまく行きました。
iPhoneとMacをUSBで物理的に接続するのをお忘れなく。