今から10分ではじめる Google Apps Script(GAS) で Web API公開
今から10分ではじめる Google Apps Script(GAS) で Web API公開:
Googleアカウントにログインした状態で以下に行く
https://script.google.com
[APPS SCRIPTを作成]をクリックすると、プロジェクトが作成される。
無題のプロジェクト というプロジェクトとコード.gsというファイルができるので、
画面左上の無題のプロジェクトをクリックして、プロジェクト名をwebapi_example01に変更した。
さらに、↓のように、
左側ペインにコード.gsというファイルがあるのがわかる。これが最初のファイルとなる。ファイル名の右にある[▼]を押してメニューから名前を変更をクリックしてmain.gsというファイル名に変更した。
さっそくコードを書いて、WebAPIを公開する。コードはJavaScriptで書く。
Google Apps Script はJavaScriptの最新をサポートしているわけでも、すべての機能をサポートしているわけでもないが、JavaScriptが書ける人ならなんとかなる。
デフォルトだと以下のようになっているが、Web APIとして公開したいので、GETやPOSTをハンドリングできるようにする。
関数myFunctionは消して、以下のようにした
シンプルなコードだが、いくつかみておく。
コード中のdoGetで渡される引数eは、リクエストパラメータ等のイベントパラメータが入る。
e.parameterはリクエストパラメータがkey/valueペアとして入るので、
Google Apps ScriptでWeb公開したURLで
リクエストパラメータについて詳しくはこちらに書いてある。
以下の ContentService はテキストコンテンツを返すためのサービスで #createTextoutput で Textoutputオブジェクトを生成する。
Textoutputオブジェクト outに対して
これでTextoutputオブジェクト outを return すればOK。
セキュリティを考慮してスクリプトがダイレクトにテキストをブラウザに返すことはなく、実際には、ブラウザは googleusercontent.com にリダイレクトされ、そこから結果を受け取る、という構造になっている。
これで、GETメソッドでアクセスすると、JSONを返すWeb APIができた。
早速公開してみる。
上部メニューから公開>Webアプリケーションとして導入 を選択する。
するとダイアログがでる、
アプリケーションにアクセス出来るユーザーを 全員(匿名ユーザーを含む) にする
[導入]をクリックすると、現在のウェブアプリケーションのURLが表示されるので、そのURLをコピーしてブラウザからアクセスしてみる。
アクセス結果
無事、レスポンスが返ってきた。
シンプルだけど、これでWeb API公開に成功した。
ブラウザからAPIをたたくということは、まずクロスドメイン大丈夫か?ということが頭をよぎる。
つまりGoogle Apps Script で公開したWeb APIはCORS(Cross-Origin Resource Sharing)を OKにできるのか?
→Google Apps Script で公開したWeb APIはCORSできない
つまり異なるドメイン(オリジン)からAjaxはGETもPOSTもできない。
ブラウザ上で動くスクリプトからAjax的に使いたければ、同じドメインにHTMLを配備するか、別ドメインにHTMLを配備したうえで、JSONPを使うしか手がないようだ。
ということで、別ドメインにHTMLを置く前提でさきほどのコードをJSONPに書き換える
リクエストパラメータに callbackがついていたら、JSONPで返すようにした。
(本家サイトにも注意があるが、JSONPをつかうなら脆弱性に関して注意深く設計する必要がある。提供する情報はリードオンリーかつ誰にでも公開できるような情報のみとし、センシティブな情報はゼッタイ入れない)
公開>Webアプリケーションとして導入 を選択していまつくったJSONP対応コードに更新する。
新しいバージョンを公開したいときは、プロジェクトバージョンを新規作成する。
変更内容は入力しなくてもよい。
さっきのが バージョン1 だったので、次は自動的に 2 になる。
以下のような htmlファイルを作る。
今回は、JSONPへのアクセス用にjQueryを使った。
この部分には、さきほどの 公開>Webアプリケーションとして導入で確認できる現在のWebアプリケーションのURLを入力する。
さて、いまつくった index.html をブラウザで開いてみる。
ローカルファイルでも開ける。
うまく呼び出すことができた。
これで、シンプルなWeb APIがお手軽に作れた。
デバッグの方法はいろいろあるがいちばん準備が少なくて良いのは、デフォルトで準備されているスクリプトエディタとなる。
ブラウザ上から編集できるスクリプトエディタには、スクリプトの実行機能やデバッグ機能がついているので実行してみる
ここでは、doGetを呼び出すために以下のようなコードを main.gs に追加した。
#doGetのロジックがちゃんと動作しているのか、この#testLogic関数をつかって確かめてみる。
以下のように実行したい関数を選択できるので、 testLogicを選択して、
実行ボタンをクリックすると実行される。
表示>ログでログ画面を表示することができるので、
ログ画面を表示してみた。
ちゃんと動作している模様。
今のはふつうに実行だったが、今度はデバッグ機能をつかう。
デバッグ実行するまえに、プログラムの実行を一時停止するブレークポイントを設定する。
コードの行番号のところを、マウスでポチっとすると、赤丸●がついて、ここにブレークポイントがセットされる。
この状態でimage.pngをクリックする
すると、以下のような感じで、ブレークポイントまで実行され、ウォッチ画面が表示される。
一時停止や再開、ステップ実行などひととおりの機能がブラウザベースでできるので、なかなか便利。
main.gsに以下を追加する。
このコードは、自分自身を呼び出してみる関数になっている。
ScriptApp.getService().getUrl()で自分自身のURLを取得する
こちらは、実際に GETメソッドで外部サービス(といっても自分自身)を呼び出しにいっている。外部サービスに接続にいくときは、 UrlFetchAppを使う。
ここまでのコード(main.gs)は以下のようになっている。
さて、実行対象関数を testGetに指定して、
実行してみると、こんなダイアログがでてきた。
許可を確認をクリックすると、
認可画面がでてくるので、内容確認して 許可をクリック。
実行が終わった後に、ログ画面を表示してみると、きちんと動作していた。
ここまででひとまず基本的な使い方は理解できた。
Google Apps Scriptにも効率化やモダン?な開発を促進するための各種ソリューションを先人たちが親切にも準備してくれているのでキーワードだけカンタンに整理しておく。
要求:ブラウザ上のエディタじゃものたりません、ローカルで開発したいです
インストールしたらログインする。Googleのアカウントで入る。
ローカルにプロジェクトを落としてくる
pullする。バージョン指定も可能。
pushする。
claspでローカルに落としてきたものをGitHubで管理したりできそう。
要求:Google Apps ScriptのコードはGoogle Driveに保存されるが、あっぱりGitHub使いたい!
chrome拡張として提供されている。
前節でふれたclaspをつかってローカル→GitHubでもいいし、chrome拡張つかってもよさそう。
要求:クラスを使いたい!
要求:ES5のクラス風とかではなく、TypeScriptを使ってきちんと書きたい
要求:Google Apps Scriptでもユニットテストがしたい
概要
-
Google Apps Script (GAS)で、Web API(無料、サーバーレス)を公開する方法についてのメモです -
Google Apps Script (GAS)をローカルで開発したい、Gitでコード管理したい、クラスを使いたい、TypeScriptを使いたい、などのやり方も後半簡単に紹介します
Google Apps Script (GAS) の位置づけを理解してみる
- Google Apps Script はG Suite(GmailやスプレッドシートなどGoogleサービス)を JavaScriptで制御できる仕組み。だから、Microsoft OfficeのVBAのGoogleサービス版みたいな感じ。
- JavaScriptで書いた処理をWebAPIとして公開できるので、AWS LambdaとかGoogle Functionのようなサーバレスなコード実行環境のようにも使える←今回はこの用途で使いたい
- JavaScript 1.6(2005年11月)がベースでかつブラウザ系機能であるDOM API等は無いが、ツールをこねくり回せば今風なコードを書くこともできる。
- 従量課金のような考え方ではないので、お金を払っても無限に使えるわけではない。容量制限がある。
Google Apps Script のプロジェクトを作る
Google Apps Scriptのトップページにいく
Googleアカウントにログインした状態で以下に行くhttps://script.google.com
最初のプロジェクトを作る
[APPS SCRIPTを作成]をクリックすると、プロジェクトが作成される。
無題のプロジェクト というプロジェクトとコード.gsというファイルができるので、
画面左上の無題のプロジェクトをクリックして、プロジェクト名をwebapi_example01に変更した。
さらに、↓のように、
左側ペインにコード.gsというファイルがあるのがわかる。これが最初のファイルとなる。ファイル名の右にある[▼]を押してメニューから名前を変更をクリックしてmain.gsというファイル名に変更した。
コードを書いてWeb APIを公開する
さっそくコードを書いて、WebAPIを公開する。コードはJavaScriptで書く。Google Apps Script はJavaScriptの最新をサポートしているわけでも、すべての機能をサポートしているわけでもないが、JavaScriptが書ける人ならなんとかなる。
Web APIをつくる
デフォルトだと以下のようになっているが、Web APIとして公開したいので、GETやPOSTをハンドリングできるようにする。main.js
function myFunction(){ }
main.js
//HTTP GETをハンドリングする function doGet(e) { //リクエストパラメータ名"text"の値を取得する var text = e.parameter.text; var value; if (text) { value = "You say " + text; } else { value = "Please say something!"; } var result = { message: value } var out = ContentService.createTextOutput(); //Mime TypeをJSONに設定 out.setMimeType(ContentService.MimeType.JSON); //JSONテキストをセットする out.setContent(JSON.stringify(result)); return out; }
コード中のdoGetで渡される引数eは、リクエストパラメータ等のイベントパラメータが入る。
function doGet(e) { var text = e.parameter.text;
Google Apps ScriptでWeb公開したURLで
https://xxxxxx/exec?text=Hello
とリクエストされたら e.parameter.textには"Hello"が入ることになる。リクエストパラメータについて詳しくはこちらに書いてある。
以下の ContentService はテキストコンテンツを返すためのサービスで #createTextoutput で Textoutputオブジェクトを生成する。
var out = ContentService.createTextOutput();
#setMimeType
でJSONを指定し、#setContent
で実際に返すテキスト(この場合は JSON形式のテキストにして)をセットする。out.setMimeType(ContentService.MimeType.JSON); out.setContent(JSON.stringify(result)); return out;
セキュリティを考慮してスクリプトがダイレクトにテキストをブラウザに返すことはなく、実際には、ブラウザは googleusercontent.com にリダイレクトされ、そこから結果を受け取る、という構造になっている。
これで、GETメソッドでアクセスすると、JSONを返すWeb APIができた。
早速公開してみる。
Web APIの公開
上部メニューから公開>Webアプリケーションとして導入 を選択する。するとダイアログがでる、
アプリケーションにアクセス出来るユーザーを 全員(匿名ユーザーを含む) にする
[導入]をクリックすると、現在のウェブアプリケーションのURLが表示されるので、そのURLをコピーしてブラウザからアクセスしてみる。
アクセス結果
無事、レスポンスが返ってきた。
シンプルだけど、これでWeb API公開に成功した。
ブラウザからこのAPIをたたきたい
ブラウザからAPIをたたくということは、まずクロスドメイン大丈夫か?ということが頭をよぎる。つまりGoogle Apps Script で公開したWeb APIはCORS(Cross-Origin Resource Sharing)を OKにできるのか?
→Google Apps Script で公開したWeb APIはCORSできない
つまり異なるドメイン(オリジン)からAjaxはGETもPOSTもできない。
ブラウザ上で動くスクリプトからAjax的に使いたければ、同じドメインにHTMLを配備するか、別ドメインにHTMLを配備したうえで、JSONPを使うしか手がないようだ。
Web APIをJSONP対応化する
ということで、別ドメインにHTMLを置く前提でさきほどのコードをJSONPに書き換えるmain.js
//HTTP GETをハンドリングする function doGet(e) { //リクエストパラメータ名"text"の値を取得する var text = e.parameter.text; var value; if (text) { value = "You say " + text; } else { value = "Please say something!"; } var result = { message: value } var responseText; var out = ContentService.createTextOutput(); var callback = e.parameter.callback; if (callback) { responseText = callback + "(" + JSON.stringify(result) + ")"; //Mime Typeをapplication/javascriptに設定 out.setMimeType(ContentService.MimeType.JAVASCRIPT); } else { responseText = JSON.stringify(result); //Mime Typeをapplication/jsonに設定 out.setMimeType(ContentService.MimeType.JSON); } //JSONPテキストをセットする out.setContent(responseText); return out; }
var callback = e.parameter.callback; if (callback) { responseText = callback + "(" + JSON.stringify(result) + ")"; //Mime Typeをapplication/javascriptに設定 out.setMimeType(ContentService.MimeType.JAVASCRIPT); } else { responseText = JSON.stringify(result); //Mime Typeをapplication/jsonに設定 out.setMimeType(ContentService.MimeType.JSON); }
(本家サイトにも注意があるが、JSONPをつかうなら脆弱性に関して注意深く設計する必要がある。提供する情報はリードオンリーかつ誰にでも公開できるような情報のみとし、センシティブな情報はゼッタイ入れない)
公開しているWeb APIを更新する
公開>Webアプリケーションとして導入 を選択していまつくったJSONP対応コードに更新する。新しいバージョンを公開したいときは、プロジェクトバージョンを新規作成する。
変更内容は入力しなくてもよい。
さっきのが バージョン1 だったので、次は自動的に 2 になる。
HTMLをつくって、ブラウザからアクセスする
以下のような htmlファイルを作る。今回は、JSONPへのアクセス用にjQueryを使った。
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>GAS Client Example</title> </head> <body> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script> const endpoint = "https://script.google.com/macros/s/xxxxxxxxxx/exec"; $.ajax({ type: 'GET', url: endpoint, dataType: 'jsonp', data: { text: 'Hi,There!' }, success: out => { alert(out.message); } }); </script> </body> </html>
const endpoint = "https://script.google.com/macros/s/xxxxxxxxxx/exec";
さて、いまつくった index.html をブラウザで開いてみる。
ローカルファイルでも開ける。
うまく呼び出すことができた。
これで、シンプルなWeb APIがお手軽に作れた。
デバッグ、テストの方法
デバッグの方法はいろいろあるがいちばん準備が少なくて良いのは、デフォルトで準備されているスクリプトエディタとなる。
スクリプトエディタ上で実行する
ブラウザ上から編集できるスクリプトエディタには、スクリプトの実行機能やデバッグ機能がついているので実行してみるここでは、doGetを呼び出すために以下のようなコードを main.gs に追加した。
main.gsへの追加分
function testLogic() { var e = { "parameter": { "text": "hello", "callback": "myCallbackFunc" } }; var out = doGet(e); var content = out.getContent(); Logger.log("content=" + content); }
以下のように実行したい関数を選択できるので、 testLogicを選択して、
実行ボタンをクリックすると実行される。
表示>ログでログ画面を表示することができるので、
ログ画面を表示してみた。
ちゃんと動作している模様。
デバッグ機能を使う
今のはふつうに実行だったが、今度はデバッグ機能をつかう。デバッグ実行するまえに、プログラムの実行を一時停止するブレークポイントを設定する。
コードの行番号のところを、マウスでポチっとすると、赤丸●がついて、ここにブレークポイントがセットされる。
この状態でimage.pngをクリックする
すると、以下のような感じで、ブレークポイントまで実行され、ウォッチ画面が表示される。
一時停止や再開、ステップ実行などひととおりの機能がブラウザベースでできるので、なかなか便利。
Google Apps Scriptから自分自身を呼び出す
main.gsに以下を追加する。main.gs追加分
function testGet() { var url = ScriptApp.getService().getUrl() + "?text=Hello&callback=myFunc001"; Logger.log("url=" + url); var options = { "method": "GET", "followRedirects": true, }; var response = UrlFetchApp.fetch(url, options); Logger.log("response=" + response); }
var url=ScriptApp.getService().getUrl() ・・・
var options = { "method": "GET", "followRedirects": true, }; var response = UrlFetchApp.fetch(url, options);
ここまでのコード(main.gs)は以下のようになっている。
main.gs
//HTTP GETをハンドリングする function doGet(e) { //リクエストパラメータ名"text"の値を取得する var text = e.parameter.text; var value; if (text) { value = "You say " + text; } else { value = "Please say something!"; } var result = { message: value } var responseText; var out = ContentService.createTextOutput(); var callback = e.parameter.callback; if (callback) { responseText = callback + "(" + JSON.stringify(result) + ")"; //Mime Typeをapplication/javascriptに設定 out.setMimeType(ContentService.MimeType.JAVASCRIPT); } else { responseText = JSON.stringify(result); //Mime Typeをapplication/jsonに設定 out.setMimeType(ContentService.MimeType.JSON); } //JSONPテキストをセットする out.setContent(responseText); return out; } function testLogic() { var e = { "parameter": { "text": "hello", "callback": "myCallbackFunc" } }; var out = doGet(e); var content = out.getContent(); Logger.log("content=" + content); } function testGet() { var url = ScriptApp.getService().getUrl() + "?text=Hello&callback=myFunc001"; Logger.log("url=" + url); var options = { "method": "GET", "followRedirects": true, }; var response = UrlFetchApp.fetch(url, options); Logger.log("response=" + response); }
実行してみると、こんなダイアログがでてきた。
許可を確認をクリックすると、
認可画面がでてくるので、内容確認して 許可をクリック。
実行が終わった後に、ログ画面を表示してみると、きちんと動作していた。
ここまででひとまず基本的な使い方は理解できた。
ローカルで開発したい、Gitでコード管理したい、クラスを使いたい、TypeScriptを使いたい、などの要求(欲求)とやり方
Google Apps Scriptにも効率化やモダン?な開発を促進するための各種ソリューションを先人たちが親切にも準備してくれているのでキーワードだけカンタンに整理しておく。
ローカルで開発したい!
要求:ブラウザ上のエディタじゃものたりません、ローカルで開発したいです- そんなときは、ローカルでの開発を助けてくれるclasp。GITに似たコマンド体系で操作できる。
npm i @google/clasp -g
clasp login
clasp clone [scriptId/scriptURL]
例
clasp clone "15ImUCpyi1Jsd8yF8Z6wey_7cw793CymWTLxOqwMka3P1CzE5hQun6qiC" clasp clone "https://script.google.com/d/15ImUCpyi1Jsd8yF8Z6wey_7cw793CymWTLxOqwMka3P1CzE5hQun6qiC/edit"
clasp pull clasp pull -versionNumber 2
clasp push
GitHubでコード管理したい!
要求:Google Apps ScriptのコードはGoogle Driveに保存されるが、あっぱりGitHub使いたい!chrome拡張として提供されている。
前節でふれたclaspをつかってローカル→GitHubでもいいし、chrome拡張つかってもよさそう。
クラスを使って書きたい!
要求:クラスを使いたい!- そんなときは、まずES5のprototypeをつかったクラス風で満足できないか?
ES5時代のクラス風構文
function Greeting(timing) { this.timing = timing; } Greeting.prototype.sayHello = function (name) { if (!name) { name = "Man"; } if (this.timing == 'morning') { return 'Good morning,' + name; } else { return 'Hello,' + name; } }; function doGet(e) { var g = new Greeting("morning"); var hello = g.sayHello("John"); var result = { message: hello }; var responseText = JSON.stringify(result); var out = ContentService.createTextOutput(); out.setMimeType(ContentService.MimeType.JAVASCRIPT); out.setContent(responseText); return out; }
- そんなときはclaspのTypeScriptサポート
webpackやbabelの手動設定は最低限で済む
ユニットテストがしたい
要求:Google Apps Scriptでもユニットテストがしたい- そんなときは Google Apps Script用Qunitとか。
まとめ
- Google Apps Script(GAS)でWeb APIを公開する方法をハンズオン的にみてきました
- 今回はほんの触りだけでしたが、機能豊富で味わい深い使い方ができそうです
コメント
コメントを投稿