Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
14
Help us understand the problem. What is going on with this article?
@fuga___

【Vue.js】 Google SpreadSheet をデータベースの代わりに使う。

More than 1 year has passed since last update.

はじめに

JS、Vue.js ともに初学者です。
間違いもあるかと思いますので、指摘していただけたら幸いです。

環境

今回グーグルアカウントはG Suiteを利用しています。
なのでGAS,Spreadsheetともに公開範囲は社内のみとなっていますが、一般のアカウントでもOKです。

また、Vue CLI3を使ってプロジェクトを作成しています。

方法

  1. SpreadsheetをJSON形式に変換し、Web APIとして公開する
  2. VueでそのAPIを叩く
  3. おしまい

問題

素直にJSONを取得しようとすると、CORSエラーが発生します。

CORS(Cross-Origin Resource Sharing)とは?

ブラウザがオリジン(HTMLを読み込んだサーバのこと)以外のサーバからデータを取得する仕組みです。
デフォルトでは、自分自身以外のドメインからのデータ取得を拒否する設定になっているようです。

→簡単に言うと、認証されてないドメインからデータ取得させないようにする仕様です。

サーバから送信されるレスポンスヘッダに
access-control-allow-origin:*
が付与されている場合、すべてのドメインにデータ取得を許可できます。

GASもCORSに対応しており、
レスポンスヘッダにも、access-control-allow-origin:*が付与されます。
なのに何故CORSエラーが発生するのでしょうか?
調べたところ、うまく行かないパターンがあるようです。

うまく行かないパターン
・JSONテキストをまるごと POST するような場合は エラーとなる
 →なぜなら、JSONテキストの content-typeが application/json となるため。
 →なぜ application/json だとエラーとなるかというと、 application/jsonの場合は preflightリクエストが発生するため
 →なぜなら、Google Apps Script は OPTION メソッドをサポートしていないため。

▲引用 - 今から10分ではじめる Google Apps Script(GAS) で Web API公開 - Qiita

正直理解しきれていないですが、どうやらJSONをそのままPOSTする場合はダメみたいです。
サーバ側の処理をいじることはできないので、クライアント側で対処します。

クライアント側の対処方法はいくつかあります。

  1. ブラウザのセキュリティをOFFにする。
  2. JSONPを使う。

ブラウザのセキュリティをOFFにする場合

参考 : クロスドメイン制約を回避するChromeショートカットを作る - Qiita
Chromeの起動オプションでセキュリティを切ります。

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C://Chrome dev session

手軽にできるので開発中には良いのですが、他人に成果物を共有するとき、
※ブラウザのセキュリティを切っています
なんて注意書きを入れなきゃいけません。

JSONPを使う場合

素のaxiosではJSONPが取得できないようなので、vue-jsonpというプラグインを導入します。
JSONPとは、コールバック関数を埋め込み、関数の戻り値としてJSON文字列を受け取る形式です。

※JSONPは情報漏洩の可能性があります。機密情報を取り扱わないようにしましょう。

→今回はGASの公開範囲によって社内限定にデータが守られているので、JSONPを使って実装します。

実装

1.SpreadsheetをJSON形式に変換し、Web APIとして公開する

JSON形式というかJSONP形式ですが、、
以下のGASを作成します。
参考 : Google SpreadSheet のデータを JSON 形式で取得する Web API をサクッと作る - Qiita

function getData(id, sheetName) {
  var sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName);
  var rows = sheet.getDataRange().getValues();
  var keys = rows.splice(0, 1)[0];
  return rows.map(function(row) {
    var obj = {}
    row.map(function(item, index) {
      obj[keys[index]] = item;
    });
    return obj;
  });
}

function doGet() {
  var data = getData('スプレッドシートID', 'シート名');
  return ContentService.createTextOutput("callbackFunction" + '(' + JSON.stringify(data, null, 2) + ')')
  .setMimeType(ContentService.MimeType.JAVASCRIPT);
}

作成したGASを「公開>ウェブアプリケーションとして導入」と進み
アプリケーションにアクセス出来るユーザーを 全員(匿名ユーザーを含む) にして公開します。
末尾に「exec」のついたURLが表示されるので、そのURLを使ってGASにアクセスします。

2. VueでそのAPIを叩く

参考 : 覚え書き Vue.jsでjsonpを使ってみる - Qiita
先にvue-jsonpプラグインを導入しておき、以下のようにAPIを叩きます。
この場合jsonDateという変数にJSON形式のデータが格納されます。


data() {
  return {
    jsonData:'' // JSONを格納するための変数
  }
},
methods: {
  getData (apiUrl) {
    // this.$jsonp(url, dataObj, timeout) で使える。 Vueコンポーネント内だとthisで呼び出せる。
    this.$jsonp("APIのURL",{ callbackName: "callbackFunction" })
    .then(json => {
      // Success.
      this.jsonData = json
    }).catch(err => {
      // Failed.
    })
  }
}

これでSpreadsheetをデータベース代わりに使うことができるようになりました!
もっと良いやり方を知っている人がいらっしゃいましたら御教示頂けると幸いですm(_ _)m

参考一覧

Google SpreadSheet のデータを JSON 形式で取得する Web API をサクッと作る - Qiita
覚え書き Vue.jsでjsonpを使ってみる - Qiita
今から10分ではじめる Google Apps Script(GAS) で Web API公開 - Qiita
JSONPで悩むある程度の人々へ
CORS(Cross-Origin Resource Sharing)によるクロスドメイン通信の傾向と対策 | DevelopersIO

14
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
fuga___
新卒4年目の赤ちゃんエンジニアです。 勢いだけはあります。深みはこれから出ます。 好きな言葉 「怠惰、短気、傲慢」 「許可を求めるな、謝罪せよ」
infomart
50万社以上の企業に商取引を電子データ化して効率化・利便性をもたらすBtoBプラットフォームを提供しています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
14
Help us understand the problem. What is going on with this article?