【GAS】doGetやdoPostのCORS問題回避と戻り値の受け取り方

Google Apps Script

doGetとdoPostにやられた、、、CORSでどハマりした、、、

ということで、解決方法の備忘録です。

最初に、参考サイト

こちらのサイトが大変参考になりました。

GASでCORSエラーを回避したウェブアプリを作成する方法
 `doGet`, `doPost`を`Content-Type:x-www-form-urlencoded`でリクエストすればいい。 # 前回 1. [] 1. [] : : # 今回  CORSエラーを回避する。 # 情報源 * * *  CORSエラーの原因は`Content-Type:...

というかここに全てが載っている。

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" を使っています

Cross-Origin Resource Sharing (CORS) - HTTP | MDN
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own...

その関係上、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 動かないことも多かったので、今回記事にしました。
誰かの助けになることを願っています。

タイトルとURLをコピーしました