🧡

GASのリクエストとレスポンスについてわかりやすくまとめてみた

2024/04/02に公開

はじめに

GASのウェブアプリケーションAPIにPOSTリクエストを送る際にCORSエラーが出てしまったので、この機会に解決方法とGASのリクエストとレスポンスについて自分なりにわかりやすくまとめてみました。

CORSエラーとは

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

GASではスクリプトのエラーがあった場合にもCORSエラーが表示されます。
ですので、下記で解決しない場合はスクリプトの内容も確認した方が良いかと思います。

CORSエラーを回避する方法

①リクエストヘッダを設定しない

下記の場合にはJSONデータを送信しているので、Content-Type: application/jsonを明示的に設定するのが適切です。

しかし、GASにリクエストを送る場合はContent-Typeがapplication/jsonだとCORSエラーが発生してしまうので、下記のようなbodyがJSON形式の場合はリクエストヘッダを設定していません。

// https://script.google.com/macros/s/*****/exec
const endPoint = process.env.NEXT_PUBLIC_ENDPOINT || '';

      fetch(endPoint, {
        method: 'POST',
        body: JSON.stringify({ data: data }),
      })
        // HTTPリクエストが完了した場合
        .then((response) => {
          console.log('response', response.body);
          if (!response.ok) {
            console.error('レスポンスが失敗しました。');
            throw new Error('Network response was not ok.');
          }
          return response.text();
        })

②単純リクエストとして送信する

HTTPリクエストのbodyに含まれるデータの種類によりますが、text/plainまたは application/x-www-form-urlencodedをContent-Typeとして指定して、追加のセキュリティチェック(プリフライトリクエスト)を行わずに直接サーバーに単純リクエストを送信してください。
https://developer.mozilla.org/ja/docs/Glossary/Preflight_request
https://qiita.com/nnishimura/items/1f156f05b26a5bce3672

const data = {
  name: 'Mike',
  age: 30,
};

const formData = new URLSearchParams();
formData.append('data', JSON.stringify(data));

      fetch(endPoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
        },
         // URLエンコードされた文字列を生成する key=value&key2=value2のような形式です
               body: formData.toString(),
      })
        // HTTPリクエストが完了した場合
        .then((response) => {
          console.log('response', response.body);
          if (!response.ok) {
            console.error('レスポンスが失敗しました。');
            throw new Error('Network response was not ok.');
          }
          return response.text();
        })

https://developer.mozilla.org/ja/docs/Web/API/URLSearchParams

GASからのレスポンスについて

GASからのレスポンスは、成功時に302 FOUND Access-Control-Allow-Origin * 、
失敗の場合は200 OK Access-Control-Allow-Origin は設定されずに返ってきます。

no-cors

Request.modeをno-cors(mode: 'no-cors')にすると送られるHeaderが制限されてCORSエラーは出なくなりリクエストは送れますが、その内容は不透明(opaque)とみなされ、レスポンスの内容は読み込めません。
https://developer.mozilla.org/ja/docs/Web/API/Request/mode

レスポンスの内容
type: "opaque" URL list: 空 status: 0 status message: 空文字列 header list: 空 body: null

GAS側のコード

doPost関数で受け取れるデータは、postDataプロパティを介してアクセスする必要があり、postData.contentsを使用してPOSTリクエストのボディに含まれるデータを取得します。

イベント オブジェクトの構造
https://developers.google.com/apps-script/guides/web?hl=ja

index.gs
const doPost = (e: GoogleAppsScript.Events.DoPost) => {
// POSTリクエストのボディからJSON文字列を取得し、パースする
const payload = JSON.parse(e.data.contents);

// dataオブジェクトにアクセス
const name = payload.name; //'Mike'

// JSON文字列に変換する
const response = JSON.stringify({
          result: 'Success',
          message: 'リクエストに成功しました。',
        });
// JSON形式のレスポンスを返す
return ContentService.createTextOutput(response).setMimeType(
          ContentService.MimeType.JSON
        );
}

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

https://developers.google.com/apps-script/reference/content/mime-type?hl=ja

参考にさせていただきました

https://www.sambaiz.net/article/319/
https://knmts.com/become-engineer-31/

終わりに

何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉

Discussion