農業用ビニールハウス自動化を進めています。
各ビニールハウスへ設置したモータをスマホから動かす為に、PCをWEBサーバにして
モータを直接動作させるESP32の情報を集約させておきます。
[PC(ブラウザ)]-[PC(http)]-[ESP32(http)]-[モーター]
※PCは同一機です。
[PC(http)]-[ESP32(http)]の接続部分構築で問題が起きました。
エラー内容と対処方法を書き残します。
エラー内容
Access to fetch at 'http://192.168.50.230/property?height=1' from origin 'http://192.168.50.217' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
なんかすごく長い。
‘Access-Control-Allow-Origin’と書いてあるけど意味がわからない。
後半CORSって強調されているけど何者(こ、コロス・・!?)
やっぱ怖いな。
そして続けてこの出力。
GET http://192.168.50.230/property?height=1 net::ERR_FAILED 200
エラーなのはわかるけど200って出てる!成功なんじゃないの!??
今回やりたい事
PC(http://192.168.50.217)からJavaScriptAPIで
サーバ(http://192.168.50.230/property?height=1)へ接続して高さ情報を取得する。
サーバ自体はArduinoの言語で動いています。
全コードまでは長いので省略しますが、/propertyへのアクセスがあった際に処理する関数のみ表示します。
レスポンスを返すESP32のコード
void slash_property(void){ String _msg; //高さの確認 if (server.hasArg("height")){ _msg = height; } server.send(200, "text/plain; charset=utf-8", _msg); }
割愛しましたが、heightはグローバル変数で既に50の値を格納してあります。
heightがGETの値の“height”と戻り値のheightで2つあるので紛らわしいです。(スミマセン)
普通にブラウザへ「http://192.168.50.230/property?height=1」を入力してみる。
想定通りheightの「50」が返ってきます。
リクエストを出すJavaScriptAPIのコード
fetch(`http://192.168.50.230/property?height=1`) .then((res)=>{ return( res.text() ); }) .then((text)=>{ console.log(text); }) .catch((error)=>{ alert("エラーが発生しました"); console.error(error); });
ここで冒頭に書いたエラーがでました。
200が返っているので応答は問題ないはず。(汗汗汗)
ここには書いていませんが、モータを動かす指示もAPIで問題なく通るので
ESP32はちゃんと受け取って、レスポンスしているんですよね。
APIのコードが悪いのかと思い複数のコード試しましたが治りません。
エラー内容に向き合いました。
対応
コマンドプロンプトでレスポンスヘッダを確認する。
curl -I
C:\Users\xxxx>curl -I http://192.168.50.230/property?height=1 HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 2 Connection: close
「Access-Control-Allow-Origin」がありません。
ESP32にレスポンスヘッダを追記する。
void slash_property(void){ String _msg; //高さの確認 if (server.hasArg("height")){ _msg = height; } //CROSエラー回避のヘッダを追加 server.sendHeader("Access-Control-Allow-Origin", "*"); server.sendHeader("Access-Control-Allow-Headers", "Content-Type"); server.send(200, "text/plain; charset=utf-8", _msg); }
「Access-Control-Allow-Headers」も追加しておきます。
コマンドプロンプトでレスポンスヘッダを確認する。
curl -I
C:\Users\xxxx>curl -I http://192.168.50.230/property?height=1 HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Content-Type Content-Length: 2 Connection: close
追加した分ヘッダが増えています。
接続成功
もう一度JavaScriptAPIで接続します。
うまくいきました。
結局、接続元ドメインが192.168.50.217で接続先が192.168.50.230だったので違うでしょっていうエラー。
接続元を判断するのがAccess-Control-Allow-Originの項目で、
この値を
なんでJavaScriptの時だけ出るんだよ。(涙)
勘弁してほしい。
JavaScriptはどうやって覚える?
プログラムのコードが読めないと、参考にしているコードの理解や自分でプログラムを書くときに時間がかかってしまいます。そんな時は基礎から学ぶと応用もできるようになり自分の作りたいプログラムがスムーズに作れるようになります。
無料でやるならネット上の学習サイトを参考にするといいです。
こちらはJavaScriptの基礎から説明している無料のWEBサイトになります。
>>基礎から学べるWEBサイトを見てみる
過去にネットでの学習でつまずいた方には専門書をオススメします。
本なら基礎から学べる事はもちろん、読者視点で分かりやすい解説になっています。
一人で集中してコツコツ進めたい方は書籍を試してください。
本を読んでもわからない所が多すぎたり、誰かに質問したい場合はオンラインスクールを見てみましょう。
カウンセリングから目的に応じた学習プランと教材を提供してくれるので、プログラミングの敷居がとても低くなります。
誰かに相談できるのは心強いです。
>>オンラインスクールを無料体験で始める
気付き
JavaScriptは一般的にはクライアントのブラウザ上で動作するプログラムです。
JavaScriptAPIはブラウザの裏でサーバに接続して、情報を取得してきます。
これってほぼ確実にCORSエラーでるんじゃないの?と思いました。
今回は自身で作成しているサーバへAPIアクセスするので、サーバ側のレスポンスヘッダを修正して対処できました。
もしかしたら外部のサーバへAPIアクセスを試みようとしている人がいるかもしれません。
そこでこのエラーが出た場合は対処不可だと考えた方が良いと思います。
エラーの英語が読めないしAPIの事がよくわかってないしの二重苦で結構手間取りました。
新たにAPIを試そうとしている人は気をつけてください。