🐣

Node.js/FrontendからGASへfetch

2024/02/07に公開

NuxtアプリからGASへpostしたい

GAS(Google Apps Script)からプログラミングに入ったノンプログラマーですが、
最近はNuxt.jsを勉強してみています!

GASは、公開したWebアプリをAPIサーバとして利用して、
スプレッドシートやドライブ、GmailなどのGoogleサービスを手軽に操作できるのが魅力の1つですね!

その中で1つ、ハマったことがありましたので、備忘録代わりにまとめます。

axiosだとびみょい

Nuxtアプリを立てる際に、オプションでaxiosモジュールを入れるか訊かれますね。
私も「んじゃaxiosで!」と入れ、gas側も用意。
早速動かそうとしてみましたが、バックエンドからだとCORSエラーを吐きます…
GAS側の実行履歴にはログすら残ってねぇですね。

どうやら、参考記事にもあるように、XmlHttpRequestがうまくないよう。

api/gas.js これが通らん
import axios from 'axios';
const post = async (postData = {}) {
  const options = {
    'Content-Type': "application/json"
  }
  try {
    const res = await axios(GAS_ENDPOINT_URL, JSON.stringify(postData), options);
    const json = await res.text();
    return JSON.parse(json);
  } catch (e) {
    console.error(e.stack);
    return null;
  }
}
export default post;
main.gs GAS側
function doPost(e) {
  return ContentService.createTextOutput().setMimeType(ContentService.MimeType.JSON).setContent(JSON.stringify({ result: 'ok!', e }));
}

フロントからなら、content-typeをform形式に指定すれば通りますね。

pages/index.vue
// js部分だけ
export default {
  methods: {
    async post(postData = {}) {
      const options = {
        'content-type': 'x-www-form-urlencoded',
        mode: 'no-cors'
      }
      try {
        const res = await this.$axios.post(GAS_ENDPOINT_URL, postData, options);
        const json = await res.text();
        return JSON.parse(json);
      } catch (e) {
        console.error(e.stack);
        return null;
      }
    }
  }
}

node-fetchならフロントからもバックエンドからもOK

じゃあnpmパッケージを変えてみるか!と、fetch API系のnode-fetchをインストール。

pages/index.vue こりゃ通る
// js部分だけ
import fetch from 'node-fetch';
export default {
  methods: {
    async post(postData = {}) {
      const options = {
        method: "post",
        'Content-Type': "application/json",
        body: postData
      }
      try {
        const res = await fetch(GAS_ENDPOINT_URL, options);
        const json = await res.text();
        return JSON.parse(json);
      } catch (e) {
        console.log(e.stack);
        return null;
      }
    }
  }
}
api/gas.js バックエンドからも通る
import fetch from 'node-fetch';
const post = async (postData = {}) {
  const options = {
    method: "post",
    'Content-Type': "application/json",
    body: JSON.stringify(postData)
  }
  try {
    const res = await fetch(GAS_ENDPOINT_URL, options);
    const json = await res.text();
    return JSON.parse(json);
  } catch (e) {
    console.log(e.stack);
    return null;
  }
}
export default post;

参考記事

https://www.bugbugnow.net/2019/06/gasweb.html
https://knmts.com/become-engineer-31/

Discussion