(とりあえずまずは備忘録として残します。あとでちゃんと書き直すかも)
#はじめに
簡易的なデータベースとしてGoogle Spreadsheetにデータを記録していく仕組みを作ろう!
ということで、WebページからGoogle Application Script (GAS) で作ったWebアプリケーションにJSONを投げ、Google Spreadsheetに書き込むという仕組みを思いつく。
同じWebアプリケーション上に入力用のWebページも用意したいので、順当にdoGet()で入力ページを表示、doPost()でJSONデータを受け取ることにした。
#はまったこと
CORS (Cross-Origin Resource Sharing) にガッツリはまった。
JavaScriptからJSON投げると、GASのWebアプリケーションにさえ到達しない。
全く無反応。
Chromeのデベロッパーツールでコンソールを確認すると、
Access to fetch at 'https://script.google.com/macros/s/XXXXXXXXXXXX/exec' from origin 'null' 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.
とエラーをはいていた。
尚、この時点でJavaScript側でエラー表示するようにしていても「結果はだめだよん」という返事しか返ってこなくて何が悪いのか何もわからなかった。
なので、このChromeのデベロッパーツールコンソールが唯一のエラー把握の方法。
どうやらGoogle様、CORSのドメイン制限はワイルドカードで全許可にしてくれたけど、preflight には対応していないとのこと。
意味ないじゃん!!!
どうしてそういう中途半端なことするわけ!?!
結局使えないことは変わらないじゃん!!!
Googleに限らず、こういうの大嫌い。
#解決方法
最初は XMLHttpRequest() を使っていたのだが、どうも動きが分かりずらかったので fetch() に変更。
fetch() のPOSTはデフォルトでCORSを使用するような動きに見えた。
その為、パラメータを以下のように指定。
var URL = "https://script.google.com/macros/s/XXXXXXXXXXXX/exec";
var SendDATA = {
"param1" : value1,
"param2" : value2,
"param3" : {
"subparam1" : subvalue1,
"subparam2" : subvalue2
}
};
var postparam =
{
"method" : "POST",
"mode" : "no-cors",
"Content-Type" : "application/x-www-form-urlencoded",
"body" : JSON.stringify(SendDATA)
};
fetch(URL, postparam);
- method に "POST" を指定。
- mode に "no-cors" を指定。
- ここが必須。これにより CORS を使用しなくなる。
- Content-Type に "application/x-www-form-urlencoded" を指定。
- たぶんこの指定でないと後の方法でdoPost()にデータを渡せない。
- body に "JSON.stringify(SendDATA)" と指定。
- この SendDATA に送りたいJSONを入れておく。
- body を使わないと後のdoPost()での方法で取得できない。
#GASのdoPost()側での受け方
以下のようにすればJSONを受け取れる。
function doPost(e){
var JsonDATA = JSON.parse(e.postData.getDataAsString());
~~ (JSONを使った処理) ~~
}
- e のpostDataを呼び出す。これで POST の content を呼び出せる。
- さらにgetDataAsString()を呼び出すことでcontentの中身を文字列として抜き出せる。
- JSON.parse()を使って、呼び出した文字列をJSONに変換する。
要は、ただの文字列として渡してしまって後で文字列からJSONを復元しますよ、ということ。
valueにスペースが入っているものも試したが、問題なく渡せた。
#おわり