2014年12月10日 星期三

用 Google Apps Script 開發 Web Services (Micro Services)

下午5:03 Posted by Envisioning U-Commerce Lab

借用這篇文章G Suite Microservices with Workflow and Google Apps Script的示意圖如下,來跟大家談談用 Google Apps Script 開發 Web Services (Micro Services)的觀點。就如同該作者所述: Microservice (or “serverless”) architecture is a way to build software applications composed of smaller, flexible, independent modules (or functions) which work together to provide a service. They run in the “cloud” and communicate over a light-weight protocol. With G Suite, Google Apps Script and the iOS Workflow app … I‘m discovering I can build interactive “microservices” which enable me to get a lot done from my phone.





讓我們從下列一個個例子來練習,用Google Apps Script實作一些雲端微服務,但無需自己架設或租用伺服器。(因為Google Drive是免費的,而Google Apps Script可以讓只有Javascript概念的人都能基於Google Drive環境很容易寫出伺服器端的程式。)


首先,從這篇文章所介紹的「備審資料上傳系統」開始來練習,幾乎相同介紹的還有這篇文章所介紹的「匿名上傳」(提供Script程式連結可另存副本到自己的Google Drive拿回去用)。這個程式的server.gs是在Google伺服器端執行的,首先要認識的是doGet()及部署Web App的方式,另外就跟其他後端程式一樣也要了解如何產生前端網頁的語法,就是用HtmlService.createHtmlOutputFromFile()向前端"吐出"呈現網頁。前端網頁呈現的表單,按下submit按鈕的onclick設定是執行google.script.run,它是一個非同步的客戶端JavaScript API,它允許HTML頁面呼叫服務器端的Apps Script function。 


但是第一個練習還沒有用到Google Sheet,可是要建立雲端服務很重要的一定會需要有個資料庫啊,只要懂得如何用Google Apps Script寫入Google試算表 (甚至應該瞭解可能需要避免同時競爭執行寫入而應該做到延遲寫入Google試算表),Google Sheet就能用來做個陽春但適合的資料庫。另一篇文章所介紹的「如何建立可以上傳檔案的google表單」就有納入Google Sheet當作資料庫使用(提供Script程式連結可另存副本到自己的Google Drive拿回去用)。


基於前一個Sript程式,更進一步想要讓表單有簽名欄(這是因為我們打算把資安管理或個資管理的四階文件都用GAS來做在雲端上),這部分能實作出來就蠻有意思的。搜尋了一下,就可以找到有個 jSignature 可用,而且有人提問如何在Google Apps Script引用 jSignature (只是此例並非獨立GAS執行,而是依附在Google Sheet執行的例子)。有了這些參考資訊,就著手將 jSignature 整合到我們寫的這個Script程式(另存副本到自己的Google Drive拿回去用),其中主要異動部分在form.html的5~6行、32~38行、42行、50~54行,以及server.gs的21~44行、69行。



基於前一個Sript程式,更進一步將整個頁面改為現今主流的Material Design,我選擇用Materialize CSS這個框架來用,於是將前一個Sript程式的form.html再做修改成這個Script程式(另存副本到自己的Google Drive拿回去用),其中主要異動部分在orm.html的8~19行(引用cdnjs上的Materialize CSS)、26~58行(使用Materialize CSS的Input FieldGridMaterial IconsFile Input)。(此版本再改寫成這個Script程式(另存副本到自己的Google Drive拿回去用)其中主要異動部分在server.gs的47~100行以及在上傳區資料夾裡面有一份Google文件,利用該Google文件為版型套疊資料建立PDF檔,如此可以依據表單填寫的欄位內容產生一個PDF文件讓使用者下載列印。)


基於前一個Sript程式,更進一步將Google reCAPTCHA驗證也整合到表單上,以確保公開的表單不致於遭受有心人士以程式進行大量填答。而如何使用Google reCAPTCHA先看這篇文章reCAPTCHA with Google Apps Script的做法,自己申請Google reCAPTCHA驗證服務的key並測試OK之後,再參考Google reCAPTCHA整合到我們寫的這個Script程式(另存副本到自己的Google Drive拿回去用),其中主要異動部分在form.html的8~9行、71~72行,以及server.gs的1~17行、25~29行

到這個版本為止,我們寫出的Google Apps Script已經等同於這篇文章How to Create Forms that allow File Uploads to Google Drive的做法,就不必花200美金去買它的服務授權及原始程式







再回到表單的設計方面,我們再加個下拉選單的欄位,但是其選項要從伺服器端Load Data Asynchronously,透過接下來的這個例子瞭解如何將後端的資料拉到前端的網頁來呈現,請參考這個Script程式(另存副本到自己的Google Drive拿回去用),其中最關鍵的是在form.html的第45行,執行google.script.run呼叫伺服器端server.gs的getGroups()來得到一個二維陣列資料,然後繼續由form.html的showGroups()接手執行,26~58行的邏輯就是將得到的資料變成下拉選單的選項呈現(使用Materialize CSS的Select)

更進一步,伺服器端server.gs的getGroups()若是先從Google Sheet讀取資料再組成二維陣列傳回,那麼程式的使用彈性就會更大。請參考這個Script程式(另存副本到自己的Google Drive拿回去用)以及這個Spreadsheet檔案(另存副本到自己的Google Drive拿回去用)伺服器端server.gs的getGroups()的8~28行就是開啟指定名稱資料夾的指定檔名試算表(第17行檔名必須是前述另建副本的Spreadsheet的正確檔名,第9行則是該檔案所在的資料夾名稱),然後30~38行讀取工作表的資料。

填完表單後,通常流程是要Email通知主管簽核,而我們確實可以寫Google Apps Script利用Gmail自動發送,這個部分只要用MailApp語法就很容易做到我們還參考兩篇文章からメールを送る方法發送電郵,另外準備一個HTML檔做為Mail套版,再將其中要套疊資料位置予以取代,那麼就能發送個人化的郵件內容了。請參考這個Script程式(另存副本到自己的Google Drive拿回去用)以及這個Spreadsheet檔案(另存副本到自己的Google Drive拿回去用,但記得先將3~5欄的資料改一下)伺服器端server.gs的getGroups()第38行所傳回二維陣列擴增為5欄,然後由form.html的showGroups()接手也將第52行的option value改為 items[i] 就是整列資料。於是當伺服器端server.gs的uploadFiles()收到的form.myGroup是整列資料變成以逗點分隔的字串,而46~69行就是將資料處理好並用MailApp語法發送郵件。








===============================================================================================


當系統發展成更大規模時,或許會遇到下列需求:
  • 兩個Google Apps Script間呼叫傳遞參數,這裡有個簡單的示範(按下按鈕後,主動端會丟一個有兩個欄位的JSON資料給被動端,被動端再加上第三個欄位傳回來,然後主動端將其show出來),想要了解程式,請參考這個主動端Script程式以及被動端Script程式(另存副本到自己的Google Drive拿回去用)
  • 較具規模的HTML+CSS+Javascript例子,通常就是有獨立的css與js,想要在Google Apps Script的前端html,還是應該讓css及js維持獨立,這裡有個示範,想要了解程式,請參考這個Spreadsheet及其Script程式(另存副本到自己的Google Drive拿回去用)這個例子其實是從這個原始碼小幅度改寫而成的,將原本幾個css集中起來、幾個js也集中起來,但同樣仍是讓css及js在程式碼編輯時是獨立存在的。
  • 本來在前端引用的js套件,其實是可以用在Google Apps Script的後端程式碼.gs裡面喔,舉例來說,如果有需要在後端計算HASH(像是通常在資料庫記錄的密碼表都是將密碼做HASH後儲存起來),可以考慮將jsSHA這個js套件引入後端的程式碼.gs來用,請參考這個Script程式(另存副本到自己的Google Drive拿回去用)程式重點就在第5行Load External JavaScript Libraries in Google Scripts with eval(),於是就能用jsSHA的函式計算出字串的HASH值 (執行結果就 查看 > 記錄)。








延伸閱讀.....