本文將構建一個SMS應用。爲了讓其更加有趣,本文將加入一些幽默元素。當用戶在應用中打字時,它將會回覆您一個由icanhazdadjoke API免費提供的笑話。該應用會展示如何上手Jets,以及創建控制器、動作和線路。我們將構建一個單端點,當某個號碼接收到SMS信息時,這個端點會對來自Twilio的HTTP請求做出反應。端點每次都會返回TwiML,以及一個隨機的、令人爆笑的笑話。
當AWS在2014年發佈Lambda時,沒有支持Ruby,而Python、Node.js和Java等平臺開始了針對雲託管和雲運行功能的無服務化革命。在2018年底,對Ruby的支持終於發佈。
開發者可以使用原始功能和無服務應用模型(SAM)模板,通過Ruby on Lambda構建任何東西,正如《Ruby on Lambda的開始指南》中描述的那樣。但是,Ruby的主要目的在於讓開發者更快樂,而不是更痛苦。因爲,當配置文件比程序還長時,整個流程可以說會讓人非常痛苦。Jets 框架是一個利用Ruby來讓無服務化更加快樂的框架。
從Rails過渡到Jets
Jets將構建Rails 應用體驗和部署AWS Lambda,並和相關服務能力加以結合。相關服務包括:API Gateway, S3和DynamoDB。在本帖中,我們將看看如何使用Jets並部署一個基於Lambda、用Ruby編寫的的Twilio應用。
我們構建的是什麼
爲了簡便,我們將要構建一個SMS應用。而且,爲了讓其更加有趣,我們還將加入一些幽默元素。當你在該應用中打字時,它將會回覆一個笑話,由icanhazdadjoke API免費提供。
這個應用會向我們展示如何上手Jets,以及如何創建控制器、動作和線路。我們將構建一個單端點,當某個號碼接收到SMS信息時,這個端點會對來自Twilio的HTTP請求做出反應。每次,這個端點會返回TwiML,以及一個隨機的、令人爆笑的笑話。
需要什麼
爲了完成這個項目,開發者需要準備:
- 一個Twilio賬戶 (點擊此處免費註冊)
- 一個AWS賬戶
- 已安裝Ruby 2.5 (Lambda支持的版本)和 Bundler。如果沒有安裝Ruby 2.5,可以使用這裏列出的工具來安裝和管理你的Ruby版本。
開始
首先,全局安裝jets gem。在命令行中鍵入:
gem install jets
然後,Jets可執行文件就可以被當做生成器使用,如同Rails,用來發起一個新項目,並運行該項目中的命令。我們現在會創建一個新項目,但是鑑於本帖子的範圍有限,我們會對該項目適當進行限制。首先,我們將在API模式下創建項目,因爲在這個應用中,我們不需要HTML視圖。而且,我們也無需通過webpacker來進行資產編譯,所以,這會節省我們的構建時間。我們也不需要數據庫。運行以下命令,創建一個新的項目:
jets new dad-jokes-sms --mode api --no-database
在生成器完成運行後,切換到dad-jokes-sms目錄下,運行以下命令,以本地運行你的應用:
jets serve
打開http://localhost:8888,你會看到以下的頁面:
如果看到了這個頁面,說明新Jets項目運行成功。
第一個Jets控制器
現在已經有了Jets應用,因此可以使用gem來生成應用部件,從模型和控制器到完整架構。對於應用來說,需要只有一個動作的控制器。怎麼生成它呢?運行以下命令:
jets generate controller Messages create
生成器將創建和編輯一些文件。開發者需要檢查新的路徑,因此請打開config/routes.rb。
Jets生成了一個GET線路,但是Twilio webhook會默認生成POST請求,而我寧可讓它保持現在這樣。設置應用,使之在/messages端點上接收POST請求webhook,像這樣:
Jets.application.routes.draw do
post 'messages', to: 'messages#create'
root "jets/public#show"
jets/public#show 控制器可以提供來自公共文件夾的靜態utf8內容。注意,作爲部署流程的一部分,Jets會將公共文件夾下的文件上傳到s3中,並且從s3中直接提供這些文件。S3非常適合提供靜態資產。此處有更多信息: http://rubyonjets.com/docs/assets-serving/
any "*catchall", to: "jets/public#show"
end
現在,讓我們編寫控制器的動作。打開app/controllers/messages_controller.rb,你會看到“創建”動作的方法。這一動作會接收Twilio webhook,並用TwiML進行回覆,且返回一個笑話。
獲取笑話
爲了返回笑話,我們需要對icanhazdadjoke API進行調用。讓我們快速寫一個能夠實現這一目標的私有方法。
我們將使用open-uri,因爲它在發送簡單的web請求方面(包括下載文具和圖片)十分有用。Jets生成了一個GET路徑,但是Twilio webhook會默認生成POST請求,而我寧可讓它保持這樣。在MessagesController中加入以下內容:
require 'open-uri'
class MessagesController < ApplicationController
def create
end
private
def random_joke
open('https://icanhazdadjoke.com/', { 'Accept' => 'text/plain' }).read
end
end
現在,可以將笑話以TwiML的形式返回給Twilio。
返回TwiML
我們將構建一個回覆,方法是使用來自twilio-ruby助手庫中的助手程序。打開Gemfile,添加twilio-ruby:
source "https://rubygems.org"
gem "jets"
gem "twilio-ruby"
在命令行中運行bundle install,以安裝gem。在create動作中,實例化一個新的TwiML回覆對象,使用
require 'open-uri'
class MessagesController < ApplicationController
def create
twiml = Twilio::TwiML::MessagingResponse.new
twiml.message body: random_joke
render xml: twiml.to_xml
end
private
def random_joke
open('https://icanhazdadjoke.com/', { 'Accept' => 'text/plain' }).read
end
end
要知道更多關於如何使用twilio-ruby助手庫來生成TwiML的信息,請閱讀文檔。
我們可以在本地運行以測試是否可得到預期回覆。如果應用停止,請運行jets serve重啓。使用curl向localhost:8888/messages發送POST請求,你便會在TwiML回覆中看到由icanhazdadjoke提供的笑話。
curl --data "" http://localhost:8888/messages
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>What’s the advantage of living in Switzerland? Well, the flag is a big plus.</Message>
</Response>
非常好,Jets開始工作了!現在我們要把它部署到AWS Lambda中。
要將Jets應用部署到AWS,首先需要設置好項目和證書,以便讓它可以訪問AWS服務。一個比較好的做法是創建擁有其工作所需最少權限的用戶,Jets文檔描述了用戶需要的最少權限。在AWS賬戶中創建一個策略,該策略包含所有這些權限。此外,還要創建一個新用戶,該策略將被分配給這個用戶。然後,就可以使用該用戶的證書來部署應用。
在AWS 控制面板中,找到IAM服務,或者直接跳到IAM部分。
跳轉到Policies部分,並創建一個新的策略。
選擇JSON選項卡,輸入來自Jets文檔的以下JSON:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"apigateway:*",
"cloudformation:*",
"dynamodb:*",
"events:*",
"iam:*",
"lambda:*",
"logs:*",
"route53:*",
"s3:*"
],
"Resource": [
"*"
]
}
]
}
繼續點擊,檢查該策略,並命名。
保存策略。現在,需要創建一個新用戶,並且將策略添加給該用戶,並給予該用戶創建Jets需要部署的資源的權限。打開IAM控制面板中的Users部分,創建一個新用戶。
給該用戶命個名,再在Access Type中選擇Programmatic Access。
點擊Next,並選擇給予該新用戶的權限。選擇Attach existing policies directly,並篩選剛剛創建的策略。選擇該策略,並點擊Next。
點擊Next,直到成功頁面出現爲止。
保存最終頁面上顯示的Access key ID和Secret access key。在部署的時候,我們要用到它們。現在,我們已經做好部署準備。
在Lambda上進行部署
在命令行中輸入:
AWS_ACCESS_KEY_ID=YOUR_USER_KEY AWS_SECRET_ACCESS_KEY=YOUR_USER_SECRET_KEY jets deploy
Jets將把證書作爲環境變量來設置AWS賬戶中的所有資源,以方便應用運行。這會花費一些時間,但是完成後,你會得到一個URL,而且應用會在上面運行。
你會注意到應用被部署到一個“開發”環境中。要知道更多關於Jets如何處理環境的信息,請閱讀文檔。
現在可以用curl來測試這個URL。記住,我們使用了/messages這條線路,所以務必在API網關端點末端加上它,並且發出一個POST請求。
$ curl --data "" https://YOUR_API_GATEWAY_ENDPOINT/messages
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>I knew a guy who collected candy canes, they were all in mint condition</Message>
</Response>
現在,我們便可以隨時收到笑話了,讓我們把它與Twilio號碼連接起來。
通過SMS發送笑話
訪問Twilio 控制面板,轉到有效電話號碼。如果你已經有一個號碼,請編輯它,否則,請購買一個可以接收SMS信息的新號碼。在A message comes in字段中,輸入你的應用URL。
保存號碼,並向其發送一條信息,應該會在回覆中得到一個笑話。
無服務化有趣的事情
在本帖中,我們見證瞭如何使用Jets來編寫Ruby應用,並將它部署到AWS Lambda中。你可以在GitHub上看到完整的項目。
Jets能幫助完成的東西遠不止這些,譬如:對事件作出反應,將數據儲存到數據庫中,甚至是運行你現有的Rails應用等等。閱讀Jets文檔中的這些文章,瞭解更多Jets的功能。
查看英文原文:Serverless Ruby on AWS Lambda with the Jets framework