最近,用于Web開發(fā)的Rust已經走了很長的路;盡管生態(tài)系統(tǒng)可能不像JavaScript等流行語言那樣龐大,但其內存安全、低內存占用、富有表現(xiàn)力的語法以及高度勝任的錯誤處理(當然還有速度?。┑某兄Z。隨著板條箱生態(tài)系統(tǒng)的擴大,變得更容易實現(xiàn)。支持Stripe、SMTP(通過lettre)、AWS-SES和其他郵件網絡服務提供商、websockets和SSR、子域等。
在本文結束時,我們將有一個以CRM為模型的易于擴展的SaaS入門包,該包具有以下內容:
如果您堅持使用本文中的代碼(或只是想查看最終結果),可以在這里找到帶有最終代碼的GitHub repo。本文使用前端模板,如果您決定使用它,則假設了解React/Next.js。您還可以在上找到此模板的實時部署。
我們將通過Shuttle進行部署,這是一個Rust原生云開發(fā)平臺,旨在通過放棄復雜的配置文件并允許您使用代碼注釋(通過Rust宏)來使部署Rust Web服務盡可能簡單。數(shù)據(jù)庫和靜態(tài)文件?沒問題。只需將相關宏寫入主函數(shù)中的參數(shù),它即可工作!沒有供應商鎖定,可以從您最喜歡的數(shù)據(jù)庫管理工具(如pgAdmin)訪問數(shù)據(jù)庫。
我們可以使用create-shuttle-app開始編寫我們的全棧應用程序,這是一個npm軟件包,可以安裝cargo-shuttle(用于部署管理的shuttle的CLI),如果尚未安裝,則使用貨物的Rust,然后引導Next.js應用程序初始化以及包含我們開始的所有基礎知識的后端文件夾。我們可以使用以下命令初始化應用程序:
我們希望通過訪問Shuttle的網站登錄,并通過GitHub登錄,然后在您最喜歡的終端上編寫shuttle login,并按照說明進行操作。這將使我們能夠部署到航天飛機。
帶有API密鑰的Stripe帳戶,以便我們可以遠程付款(您可以在這里注冊Stripe)
帶有API密鑰的Mailgun帳戶,以便我們可以遠程訂閱Mailgun郵件列表(您可以在這里注冊Mailgun-您只需取消勾選“立即添加付款信息”,它就可以讓您使用無限期免費試用!)
您需要創(chuàng)建一個具有每月經常性成本的Stripe訂閱項目,并將項目價格ID保存在我們稍后使用的某個地方。你可以在這里找到更多關于這個的信息。
登錄后,您可以通過進入儀表板的底部找到Mailgun API密鑰,API密鑰部分應該在那里:
您需要獲取專用API密鑰-每當我們想對Mailgun進行API調用時,我們都需要此密鑰進行身份驗證,以便我們可以從自己的網絡服務遠程與服務進行交互。
您還需要獲取您的Mailgun域名-您可以通過單擊“發(fā)送”,然后單擊“域”來找到它,如下所示:
您還需要在Mailgun上創(chuàng)建一個郵件列表,并將您的mailgun域名、私鑰和郵件列表名稱保存在某個地方。您的mailgun域和密鑰將私下存儲在秘密文件中,但您可以在常規(guī)文件中使用郵件列表名稱,因為這不需要是私有的(因為它可以從字面上命名為任何東西)。你可以在這里找到更多關于這個的信息。
我們稍后會在我們的網絡服務中使用API密鑰和Mailgun域,因此您需要找到一個安全的地方來記錄您的API密鑰和Mailgun域,這些密鑰和其他人無法讀取-我們稍后會使用這些。
您還需要安裝Docker-您可以在此處找到有關如何安裝Docker的更多信息。Docker是一個很棒的實用程序,主要用于使Shuttle能夠運行自己的本地數(shù)據(jù)庫實例,這意味著您可以避免自己設置任何東西。
接下來,我們希望安裝SQLx命令行工具,這樣我們就可以毫不費力地進行遷移。謝天謝地,作為Rust板條箱,安裝起來非常簡單,所以我們可以使用一句話,然后繼續(xù)編寫我們的遷移:
當我們需要編寫SQLx遷移時,我們希望在項目根目錄中運行sqlx migrate add name,它將創(chuàng)建一個遷移文件,以便我們可以添加遷移。這些將是我們將用于網絡服務的遷移:
目前,我正在使用一個模板來充實我的前端!它有用于登錄和注冊的頁面,基本儀表板和CRUD記錄頁面,以及分層定價頁面和每月訂閱結賬。您可以在這里找到示例(確保插入后端,否則它將無法工作?。;刭弲f(xié)議將假設您了解React/Next.js。
首先,讓我們進入帶有cd backend的后端文件夾。我們希望從添加我們所有的依賴項開始,您可以使用這句簡單的一句話來完成:
首先,我們希望定義一些結構,這些結構將作為我們想要使用的響應或請求類型模型。如果請求類型或響應類型與模型不匹配,HTTP請求將自動失敗,因此我們希望確保我們擁有所需的一切。見下文:
然后我們會想創(chuàng)建我們的端點!為了說明以下內容,我們創(chuàng)建了一個簡短的功能,從數(shù)據(jù)庫中獲取給定用戶的所有客戶。讓我們看看這個功能會是什么樣子:
這將是一個POST請求,因為它更安全-客戶端將發(fā)送用戶的電子郵件以及他們的身份驗證cookie,我們稍后會查看。我們還可以使用fetch_one()方法創(chuàng)建一個函數(shù),該函數(shù)僅通過給定的ID返回一個特定客戶,該方法僅返回1行,并將忽略任何其他行,如果出現(xiàn)問題,則返回錯誤:
如您所見,此函數(shù)采用“路徑”類型。這基本上意味著,例如,如果我們轉到這個localhost:8000/api/customers/1,我們將能夠看到它返回一個記錄,如果存在,客戶的ID為1。我們可以通過編寫相關的SQL查詢、綁定我們使用的變量并根據(jù)數(shù)據(jù)庫連接運行它,以類似的方式創(chuàng)建、編輯和刪除客戶:
我們的用戶需要能夠創(chuàng)建使用客戶的銷售交易記錄,我們可以通過定義我們的請求和響應模型應該是什么樣子來像上面一樣創(chuàng)建它們,然后我們可以構建我們的端點。
獲取銷售記錄將比獲取客戶稍微復雜一些,因為我們需要進行SQL連接才能為銷售記錄獲取客戶名稱-客戶名稱不會存儲在銷售記錄本身中,因為銷售記錄與客戶記錄相關聯(lián),因此我們可以輕松地從客戶記錄中獲取它:
如您所見,盡管原始SQL查詢比我們以前的端點更復雜一些,因為左連接,我們做了一個簡單的選擇,但它并不太復雜。我們正在從交易表中選擇列,然后使用子查詢從客戶表中連接客戶的名字和姓氏,并將其添加到我們的查詢結果中。
同樣,我們可以從數(shù)據(jù)庫中獲取單個銷售記錄,并通過為交易ID添加WHERE條件(從路徑)將其返回到我們的端點:
創(chuàng)建、編輯和刪除銷售記錄并不像上述之前的查詢那么困難!我們可以像為用戶客戶編寫API端點一樣為他們編寫端點,因為我們不需要引用其他表中的任何數(shù)據(jù)。
對于郵件,我們將使用Mailgun,它有一個慷慨的免費計劃,我們可以用它來保留郵件列表,并輕松地向新用戶和我們的會員發(fā)送郵件。這部分將假設您有一個開始,我們希望制作一個結構,該結構采用一個電子郵件地址,我們可以使用Serde反序列化到JSON:
一旦我們定義了結構,我們就可以創(chuàng)建一個函數(shù),為Mailgun API的POST請求制作參數(shù)的哈希圖,最后是我們自己的API端點,以便能夠將人們訂閱到我們的Mailgun郵件列表:
對于付款,我們可以使用Stripe API使用async-stripe庫輕松創(chuàng)建訂閱。我們希望首先為我們的API端點初始化一個結構,以便能夠獲取付款信息:
接下來,我們要為我們的訂閱計劃編寫參數(shù)列表(您需要在Stripe上創(chuàng)建一個每月經常性價格的訂閱計劃,并獲取產品ID,我們之前已經這樣做了):
我們需要在Stripe上創(chuàng)建客戶和付款方式對象的功能。這部分非常簡單-我們可以為各自的對象添加所需的任何參數(shù),然后將其他所有內容稱為默認值,如下所示:
現(xiàn)在,如果我們嘗試使用相關表單數(shù)據(jù)向其發(fā)送POST請求,它應該會在我們的Stripe帳戶上返回訂閱!然后,我們可以將用戶(在前端)重定向到成功頁面或失敗頁面,具體取決于訂閱嘗試是否成功。
我們想從創(chuàng)建我們想要使用的結構開始。我們需要一個結構,作為用戶注冊詳細信息的請求類型類型,然后是用戶登錄的類似結構:
像之前的其他示例一樣,以下函數(shù)將采用狀態(tài)和Json類型,并將返回在Axum中解析為響應的東西。讓我們來看看:
我們也可以以類似的方式編寫我們的登錄功能;但是,登錄功能也將從axum_extra中采用一種PrivateCookieJar,這是一種抽象,您可以輕松地安全地處理cookie。讓我們看看那會是什么樣子:
現(xiàn)在讓我們看看驗證一個會話。這并不難:我們試圖用我們?yōu)闀捖暶鞯拿Q抓取cookie,并嘗試將其與數(shù)據(jù)庫中的內容進行匹配。如果匹配,那么我們允許用戶繼續(xù)-如果沒有,我們返回403 Forbidden。
一些用戶也希望能夠退出登錄。為此,我們需要做的就是編寫一個函數(shù)來設置SQL查詢,以便從會話數(shù)據(jù)庫表中刪除,其中會話ID是用戶cookie的值,然后像這樣返回cookie刪除:
現(xiàn)在我們可以合并我們所有的功能了!我們最終可以將所有功能合并成一個最終的API路由器,我們可以像這樣使用:
使用Next.js,與webapp的其余部分相比,這部分非常簡單:我們需要做的就是將Next.js前端編譯到Rust后端。為此,我們只需要確保我們的fig.js文件看起來像這樣(在項目目錄的根目錄中):
現(xiàn)在,您需要做的就是在您的終端中編寫npm run build,它應該為您完成所有工作!現(xiàn)在,您可以毫不費力地將前端與后端一起使用。您甚至可以在Rust后端運行時運行npm run build,它將為您重新編譯資產,使您無需完全重新運行應用程序。
您可能還想設置一個npm腳本來從npm運行后端,而不必每次都進入后端文件夾,以及一個易于部署的腳本。我們可以這樣設置:
現(xiàn)在我們只需要運行npm run deploy,如果沒有錯誤,Shuttle將把我們的SaaS部署到實時服務器!您應該獲得一個部署ID,以及一個數(shù)據(jù)庫連接字符串和秘密列表以及您的應用程序使用的任何其他資源(在我們的案例中,公共文件夾)。
感謝您的閱讀!我希望你能從頭到尾拿走一些關于如何在Rust中構建自己的SaaS的想法,并用一個命令進行部署。如果您希望引導此Web應用程序,以便用自己的想法擴展它,您可以通過運行npx create-shuttle-app --fullstack-examples saas輕松完成。
Rust是一種出色的語言,用于編寫具有富有表現(xiàn)力的語法的內存安全程序,內存占用更少,可以降低您的開銷,并讓您以更低的價格部署更多,這對(潛在的)SaaS制造商來說非常好。