LoginSignup
30
21

More than 3 years have passed since last update.

[備忘録] GASのdoPost()にJavaScriptからJSONを渡す方法

Last updated at Posted at 2020-05-27

(とりあえずまずは備忘録として残します。あとでちゃんと書き直すかも)

はじめに

簡易的なデータベースとして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を使用するような動きに見えた。
その為、パラメータを以下のように指定。

script.js
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を受け取れる。

gas.js
function doPost(e){
 var JsonDATA = JSON.parse(e.postData.getDataAsString());

 ~~ (JSONを使った処理) ~~
}

  • e のpostDataを呼び出す。これで POST の content を呼び出せる。
  • さらにgetDataAsString()を呼び出すことでcontentの中身を文字列として抜き出せる。
  • JSON.parse()を使って、呼び出した文字列をJSONに変換する。

要は、ただの文字列として渡してしまって後で文字列からJSONを復元しますよ、ということ。
valueにスペースが入っているものも試したが、問題なく渡せた。

おわり

30
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
21