Google Apps ScriptでGET・POST【GAS】

Google Apps Scriptには、ウェブアプリケーションを公開したりするために「doGet」「doPost」という特別な関数があります。パラメータを加えて渡して上げることで、スプレッドシートのデータなどをJSONで受け取ったり、ウェブページを生成して、ウェブアプリケーションを表示したりなど、非常に重要な機能の1つです。この仕組を使うことで、自作のREST APIを作ることも可能です。

今回は、この「doPost」「doGet」を利用して、実行をするとスプレッドシートに書き込まれるといったものを作ってみたいと思います。

今回使用するスプレッドシートや資料

概要

doGetは、URLに繋げてパラメータを与えて送ります。HTTP通信のGETなわけですが、こちらのほうが利用する範囲が広いんじゃないかなぁと。思いつくだけで言えば、

    1. パラメータ付きで送ってスプレッドシートの値をJSONで取得する(しかも、フィルタした後の値とか)
    2. 予め組んで置いたURLをメールに記載して、クリックすると発動する何か(例えば、承認されるとか、ファイルが作られるとか)
    3. 与えるパラメータに応じて表示するHTMLを切り替える
    4. パラメータを可変でユーザが選んだり、与えたパラメータによってデータを書き換える。
    5. Google Apps Scriptではウェブアプリケーション公開用のメソッドでもある。

doPostは、URLに繋げるのではなくHTTP通信にパラメータを渡すPOST通信です。GETと違いパラメータはURLには出てこないので、認証などを要するようなケースで利用されます。また、バイナリデータを送ったり(アップロード)などでもPOSTを使いますね。

両者の違い、用途としてデータを取得する場合にはGET、送る場合にはPOSTといった感じで使い分けをすると良いでしょう。

※doGetおよびdoPostは、同居は可能ですが1プロジェクトで1個しか用意できないので、複数用意したい場合には仕組みで分けるか?複数プロジェクトを作って運用する必要があります。また、Apps Script APIを利用する事で、1つのプロジェクトで直接関数を叩けるようになるので、複数用意したい場合は以下のエントリーを参考に構築しましょう。

Google Apps Scriptを色々なアプリから実行する【GAS】

doGet

仕組み

仕組みは至って簡単なものです。以下のような感じです。

  • doGetはパラメータを受け取れるようにdoGet(e)という形で記述を行う。
  • 送る側は、公開されてるウェブアプリケーションのURLにパラメータをくっつけて、叩くだけ。
  • 付け加えるパラメータは、?param1=kinoko&param2=takenoko みたいな感じ。この場合2つのパラメータを取得できる
  • パラメータを受け取る側は、e.parameter.param1kinokoという値が取得できるという塩梅です。
  • 受け取ったパラメータを後は煮るなり焼くなり好きにする。
  • 最後にreturnで、例えばHTML表示をしたり、JSONデータを返して上げれば、プログラムがそのままURLからデータを取得出来るようにもなる。(WebAPI的なものが作れるわけです)。

実行結果

コードを作ってGETパラメータ文字列を組み立ててURLを叩きます。例えば今回使用するスプレッドシートに於いて、【情報通信業】の【2009】の年のデータを引き出したい時には以下のようなURLを組み立てます。

https://script.google.com/macros/s/AKfycbzYnY1ZI3FtspAdnCc9BqC5MpTldd81m1A6KI0bPQilJ4TEU0E/exec?param1=情報通信業&param2=2009

すると、{“value”:194} といったようなJSONで返ってきます。param1が業態の指定・param2が年度の指定になります。業態の指定がおかしかったり、指定した年度の情報がない場合には、valueの値はerrorとして返すようにしています。上記のURLをクリックすると実際に値が返って来ます。

※ただし出力時に、URLはリダイレクトしますので、何かプログラムでデータを取得する場合にはそれを考慮する必要があります。

ソースコード

ポイント

  • 今回の事例は非常に単純な指定したパラメータで値を返すだけですが、複数データを返すような場合には、JSONオブジェクト作成の部分で階層的なコードを書く必要性があるでしょう。
  • 複雑なデータの出力については、SheetAsJsonのコードを再利用するとやりやすいかもしれません。
  • param1やparam2といった部分はソースコード内で決めることができるので、自由にネーミングを付けて下さい。
  • 最終的にContentService.createTextOutputにてJSON文字列を返してあげます。これをやらないと、他のプログラムからJSON出力を取得できません。
  • 以前は、doGet出力のexecで終わるURLに対して、access_token=のパラメータを付けてAccess Token(ScriptApp.getOAuthToken()で取得)したものを繋げてアクセスすると認証なしでアクセスが出来たのですが、現在はこの手法は401エラーが返ってくるようになっています。OAuth2.0認証で通さないと駄目のようです。

裏技的なリクエスト

Googleにログインしてる状態であるならば、GASのdoGetで出力したページに対してWebブラウザからexecで終わるURLにアクセスすれば前述のような結果が普通に出力されます。これは通常の動作です。

問題はこれをWebブラウザ以外の手段や別のアプリケーションから同じURLにただHTTPリクエストを投げても、「ログインを要求」される為、通常はOAuth2.0認証をしてAccess Tokenを取得し、そのtokenをヘッダに加えてexecで終わるURLに対してリクエストといったようなことが必要になります。

しかし、裏技的な手法として、もし別の方法で既にAccess Tokenを取得出来ているのであるならば、以下のようなリクエスト方法でも認証を求められずにAccess Tokenをつけてのリクエストが出来ます。例えばcurlコマンドであったり、Chrome ExtensionやJSのfetchからのリクエストなどなど。

exec?の後ろにaccess_tokenのパラメータをつなげて、取得済みのToken文字列を入れて上げます。

但しこれを実現するには以下のような設定をしておく必要があります。

  • ScriptApp.getOAuthToken()で取得したAccess Tokenである必要がある(つまり、必要なスコープを満たした結果出力してくれるTokenでなければならない)
  • この時例えばスプシにアクセスして出力するJSONならば以下のようなスコープをappsscript.jsonに記述して事前に認証を済ませて、Tokenを取得しておく必要がある。

    Drive APIは必須です。
  • この認証を済ませておかないと、401 Unauthorizeというエラーが返ってきてしまう。
  • ウェブアプリケーションとしてデプロイ時は今回は実行権限もアクセス権限も「自分のみ」としています。
  • ゲストプロフィールのChromeから上記で構築したURLにアクセスするとログインしていなくても、値が取得出来ました。

図:ターミナルからリクエストしてみた

doPost

実行結果

※入力して送信するとスプレッドシートに書き込まれます。

ソースコード

GAS側コード

意外とシンプルです。getActiveSpreadsheetが使用できないので、openByIdで開くようにしています。また、formから送られてくるデータはformの各コントロールに付与してるname属性を利用しています。なので、e.parameterの後にname属性を付けると、その値が取得できるので、これを順番に配列に格納し、appendRowで最終行に登録しています。

HTML側コード(POST送信用)

Formの各要素のname属性がdoPost側に渡るe.parameterの値を取り出すときの要素になるので、重複しないようにname属性は付けなければなりません。また、送信ボタンで実行する関数の中で、document.getElementById(“formman”).submit();とあるけれど、これがフォームデータを送るコマンド。その送信先が、formタグのactionに記入されてるURL。これはスプレッドシートの公開URLです。

※全て用意が完了したらウェブページとして一度公開し、URLを取得。一度公開を無効化して、URLをHTML側のFORMの送信先に入れて、再度公開すると使えるようになります。

WordPressで設置してみる

前述の方法は、クライアント側まで含めてGoogle Apps Scriptで作成していますが、GAS側はdoPostだけをオープンにしておいて、HTML側はWordPress上に構築して送信するといった事が可能です。GASでUIを作ってしまうと、Googleアカウントが必要であったり色々面倒な部分も多いので、切り離して管理すると楽になれるかもです。

また、Google Formsを魔改造してこのサイトに、お問い合わせフォームとして設置していますが、非常に面倒な上に本来Google Formを経由しなくても良いので、doPostだけで実現する手法の方がUIの制限も無く作れるのでオススメです。

GAS側コード

  • 前述のコードで例えばローカルのHTMLから送信をするとCORSの制限によって受信が拒否されます。
  • また、今回は送信が成功したら、responseを受け取り、送信元に表示するよう結果をリターンしています。
  • 前述の場合と異なり、e.postData.getDataAsString()にて送信内容を取得する必要があります。

図:CORSエラーが出た様子

HTML側コード

  • ローカルのただのindex.htmlからの送信で今回はテストしています。
  • 前述のformでのsubmitだとページ遷移してしまうため、formの内容を1つずつ取得し、JSON.stringify()で送信しています
  • 送信はfetch APIにて送信する必要があります。
  • responseはJSONとして取得し、GAS側から送られてくる返り値のstatusTextの内容をIDがreturnvalueの項目に表示しています。
  • responseの中にはstatusなども含まれているので、これで送信成功かどうかを判定する事も可能です。
  • wordpressのページに上記のコードを貼り付けて、送信すれば、Googleスプレッドシートに書き込まれる仕組みです。

WordPress上でテスト

ポイント

  1. 今回書き込むシートのシート名はPOSTである。
  2. ウェブアプリケーションとして公開した時の公開URLは別途必要になる。
  3. ウェブアプリケーションとして公開する場合、実行権限は今回は自分自身のみにして、他の人が実行しても自分が実行した事になるようにしている。
  4. 完全フリーで公開する場合には、実行権限は自分自身であっても、投稿許可は匿名も可にしておく必要性がある。

WordPressで設置してみる2

前述の手法は送信のメソッドをGAS側へ送ってレスポンス結果だけを受け取る手法ですが、GAS側のウェブアプリの出力結果をWordPressに貼り付ける事も可能です。このサイトの作成アプリ一覧は、WordPress上で記述したものではなく、GAS上で生成した結果を呼び出してるだけのものです。この手法をするメリットは

  1. WordPress上で複雑なHTMLやCSS、JavaScriptを記述する必要性がない
  2. スプレッドシートに一覧を記載して出力が可能になるので、コンテンツ管理が容易になる(ただし、google.script.run.withSuccessHandlerで取得してレンダリングは出来ない
  3. ただしVueなどのライブラリはWordPress側で呼び出してあげる必要がある
  4. また、Widthなどは明示的に指定してあげる必要がある(出力結果が特にモバイルではみ出てしまうため)
  5. iFrameで貼り付けるケースと違ってサイトのデザインを損ねたり、iFrameの高さで制限を受けて妙なスクロールバーが出たりせず一体感をもたせられるので非常に便利です。

ただし、特定のテーマなどの場合、VuetifyのCSSがサイドバーがバッティングする可能性があるので、デザイン設定などではそのページのみ「1カラム」にしてサイドバーを非表示にしてあげなければいけないケースがあります(Lightningテーマなどはこれが該当する)

GAS側コード

WordPress側コード

  • IDがlistの場所にGAS側からのHTML出力内容を呼び出す
  • vueやvuetifyのCDNのjsやcssをロードする記述は必要になります。
  • GAS側はウェブアプリとしてデプロイしておき、そのURLに対してJavaScriptのFetch APIにてリクエスト
  • レスポンスはresponse.text()で一旦受け取っておく
  • 受け取った内容をdataに格納し、その内容をIDがlistの中に書き出す(この手順を踏まないと、object promiseと出て出力されない)

WordPressで設置してみる3

前述のコードだと、GAS側でスプレッドシートのデータを元にレンダリングをしたい場合、スプレッドシート連携でgoogle.script.run.withSuccessHandlerが利用できないのでそのままだとVueでレンダリングが出来ません。 そこでをgoogle.script.run.withSuccessHandler使わずにデータをレンダリングしたい場合は以下のコードを利用します。こちらにサンプルスプレッドシートもアップしてあります。

GAS側コード

  • createTemplateで出力時に同時にdoIt関数で変数の値を渡す手法を利用します。

HTML側コード

  • 上記のコードでHTML側で用意したdoIt関数で受け取ることが可能です。これを直接vueのrecdata変数に突っ込みます。

WordPress側は前述と同じコードで問題なく表示が可能。スプレッドシートに記述した内容がそのまま、WordPress側で表示が可能になります。試しにランダムでスプレッドシートから1レコードカード形式で表示するものが以下のものになります。

スマフォのショートカットアプリで使う

GASで作成したdoGetやdoPostのURLに対してパラメータを投げることで、ボタン一発で色々発動させる事が可能です。例えば、ボタン一発で現在まで届いてる申請のサマリーを自分宛てにPDFで送りつけるスクリプトを作っておけば、PC立ち上げてなんてやらずとも、スマフォだけで完了します。緊急一斉通知用に作って置くと、何かの役に立つかもしれません。

また、パラメータを変更して、いつでもボタンぽち1発でメンバー招集する投稿をSlackに投げて飲みに行ったりなど、よく使うものを作り込んでおくと、恐ろしく簡単に自動化が可能です。IFTTTでタスクランナーを噛ましておけば、様々なウェブサービスを手元で発動も可能。

iOSで使ってみる

iOS12よりショートカットアプリという新機能が搭載されました。いわゆるPCのショートカットリンクと同じもので、特定のリンクをポチるだけで、起動させることが出来るもので、これにGoogle Apps Scriptの今回の機能を利用する事で、ボタンひとつで遠隔でGoogle Apps Scriptを実行させてしまおうというものです。使い方は以下の通り

  1. ショートカットアプリをインストールしておき、起動する
  2. 右上の+をクリックし、出てきた検索窓に「URL」と入力
  3. URL」という項目を選び、続けて「URLの内容を取得」も選びます
  4. URLにdoGetで作ったexecの付くURLを入力します。
  5. URLの内容を取得ボックスの方法は今回は「GET」を選択。
  6. 完了ボタンの下にある変なマークのアイコン⇒設定⇒名前で名前をつけておきましょう。アイコンは独自画像も使えます。
  7. 同じく設定にて、「Siriに追加」をタップ⇒赤丸をタップ⇒付けた名前で呼ぶ⇒設定完了。
  8. ホーム画面に追加をするとブラウザが立ち上がる。支持にしたがって、ホーム画面に追加をすると完了。
  9. POSTなども選べます。また送信時用のヘッダも付けられるので、ちょっと複雑なものもつくれそうです。
  10. 完了ボタン押して終了です。

※コンテンツとプライバシーの制限の許可されたAppにてSiriと音声入力がONになっていないとSiriから呼び出しは出来ません。

図:ショートカットアプリの設定画面

図:ショートカットの細かな設定はやっておきましょう。

図:Siriで実行してみた

Androidで使ってみる

Androidの場合、HTTP Requestを行うアプリは結構あります。HTTP Request Shortcutsというアプリでは、非常に詳細で細かくパラメータ、ヘッダー、オプション、Authenticationなどを設定可能で、iOSのそれよりも高機能です。

  1. アプリをインストールしておく
  2. プラスボタンを押して、新しいショートカットを作る
  3. From scratchを選択する
  4. 名前、説明、show as app shortcut on launcherにチェックを入れる
  5. MethodはGETやPOSTを選ぶ。今回はGETで。
  6. URLにGASで作成したexecのついたURLを入力しておく
  7. Authenticationは認証が必要な場合。Basic認証やDigest認証が使えます。OAuth2認証(Bearer認証)使えないので、doGet/doPostは公開されてるURLである必要がある。そのためここは、今回はNo Authenticationを選ぶ
  8. Add Headerでヘッダを加えられる。今回はヘッダは無し。
  9. Response Settingsではレスポンスを受け取ったらどういう動作を行わせるかを決定できる。simple toastで通知のみにした。
  10. Actionでは成功時や失敗時などのアクションを指定できる。成功したら別のショートカットを起動といったリレーも可能。
  11. Advanced Settingsでは、実行時に確認求めたり、タイムアウトの設定など細かい設定が可能
  12. 隣にある{}マークのアイコンは、細かなパラメータバリューを送る時に利用します。
  13. チェックマークを押す
  14. その後作ったショートカットをロングタップすると、Place on home screenというのがあるので、選択すると画面に一発実行用ショートカットが配置されます。これは、Chromeのホーム画面に追加と同じようなものになります。

図:マニアックでサイバーなアプリですね

console.logでログを取得

Google Apps ScriptではデバッグなどでLogger.logやconsole.logを使うことがありますが、doGetやdoPostなどに於いて、外部からアクセスした場合にもデバッグしたいことは普通にあります。しかし、実はGASではそのままでは、外部からGETやPOSTでウェブアプリケーションとして公開したURLを叩いても、console.logなどでログを取ることが出来ません

doGetやdoPostでもconsole.logでログを取れるようにするためには以下の手順でGoogle Apps ScriptのプロジェクトをGoogle Cloud Console側のプロジェクトに移動させておく必要があります。

  1. スクリプトエディタのサイドバーからプロジェクトの設定を開く
  2. 下の方にあるGCPプロジェクトの項目で、プロジェクトを変更をクリック
  3. 予め、GCP側でプロジェクトを作っておきます。
  4. GCPのホーム画面にアクセスする
  5. タイトルの横にある▼をクリックして、自分が作ったプロジェクトを選択して変更する
  6. ダッシュボードのプロジェクト情報にある「プロジェクト番号」をコピーする
  7. スクリプトエディタに戻り、GCPのプロジェクト番号の欄に6.を入力して、プロジェクトを設定をクリック
  8. これでログが取れるようになったので、あらためて、ウェブアプリケーションとしてデプロイの作業をする
  9. 実際にGETやPOSTで叩くとparameterなどが取れるようになるのでデバッグが捗る

図:GCP側のプロジェクト番号が重要

図:プロジェクト移動できちんとログが残るようになった

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)