doGetとdoPostにやられた、、、CORSでどハマりした、、、
ということで、解決方法の備忘録です。
最初に、参考サイト
こちらのサイトが大変参考になりました。
というかここに全てが載っている。
GAS側
最小構成のサンプルコードでいきます。
doGet
function doGet(e) {
return ContentService.createTextOutput(JSON.stringify({status: "OK"})).setMimeType(ContentService.MimeType.JSON);
}
doPost
function doPost(e) {
// リクエストボディをオウム返しする
const requestBody = e.parameter;
return ContentService.createTextOutput(JSON.stringify(requestBody)).setMimeType(ContentService.MimeType.JSON);
}
デプロイ
実行アカウントは「自分」で、公開範囲は「全員」にします。
Webアプリ側
JavaScriptコードだけ載せます
GET
const url = "https://script.google.com/macros/s/{project_id}/exec";
const requestParams = {
method: "GET",
headers: {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
},
};
fetch(url, requestParams)
.then((response) => response.json())
.then((result) => {
console.log(result); // {"status":"OK"}が返ってくる
})
.catch((e) => console.log(e));
POST
const url =
"https://script.google.com/macros/s/{project_id}/exec";
const params = new URLSearchParams();
params.append("param1", "hoge");
params.append("param2", "fuga");
const requestParams = {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
},
body: params,
};
fetch(url, requestParams)
.then((response) => response.json())
.then((result) => {
console.log(result); // {param1: 'hoge', param2: 'fuga'} が返ってくる
})
.catch((e) => console.log(e));
ちょっとだけ解説
GASはGETとPOSTしか受け付けてくれません。
なので、OPTIONSメソッドによるCORSのpreflightリクエストが使えません。
そのため、CORSのpreflightを飛ばさないようにするために "Content-Type": "application/x-www-form-urlencoded"
を使っています
その関係上、POSTの場合はリクエストボディに URLSearchParams
を使うのがミソです。
また、レスポンスをJSONで受け取りたいことが多いと思うので、リクエストヘッダに "Accept": "application/json"
をつけています。
例外
リクエストヘッダが正しくても、CORSエラーが出る場合があります。
それは、GASのコードが単純にエラーでコケている場合です。
500エラーとかじゃなくて、CORSエラーという形で見えるので、なんかGAS側が悪いような気になりにくいのですが、GAS側も疑ってください。
doPostとかdoGetとか、Webアプリ側からじゃないと関数が叩けなくてデバッグがしにくいような印象を(勝手に)持っているのですが、
以下のような感じで、私はいつもリクエストパラメータをモックするような形でGAS側にテストコードを書いています。(デバッグモードで動かすと、処理の内容も追えますね)
function testDoPost() {
const e = {
parameter: {
param1: "hoge",
param2: "fuga",
}
}
doPost(e);
}
おわりのつぶやき
この方法でCORSも回避できて、戻り値も無事受け取ることができます。
ネットに転がっている情報があまりにもバラバラすぎ and 動かないことも多かったので、今回記事にしました。
誰かの助けになることを願っています。