avatarJen-Hsuan Hsieh (Sean)

总结

这篇文章介绍了使用Golang和React.js构建一个简单的Web服务的过程,包括注册、登录和注销等功能。

摘要

这篇文章首先介绍了Cookie、Session和Web存储的特性,然后介绍了如何使用React开发SPA,以及使用AJAX在操作cookie时需要注意的事情。接着,介绍了Web页面服务器和API服务器的工作流程,以注册为例。然后,介绍了Web页面服务器和React组件的结构,以及如何在React中使用Fetch发送请求。最后,介绍了API服务器的架构和实现细节。

观点

这篇文章的主要观点是,使用Golang和React.js构建一个简单的Web服务需要了解Cookie、Session和Web存储的特性,以及如何在React中使用Fetch发送请求。同时,也需要了解Web页面服务器和API服务器的工作流程,以及API服务器的架构和实现细节。

[Golang] Build A Simple Web Service part.6 — Sign up, Login & Logout with React.js

Copy right@A layman

Introduction

這篇的學習目標是Golang的註冊,登入及登出。

過程中會先複習到Cookie,Session,Web storage的特性; 前端將使用React開發並用上SPA,以及用AJAX在操作cookie應注意的事情,後端仍用Golang; 最後串起在註冊,登入及登出雙方向的互動。

實作將會以[Golang]Build A Simple Web Service系列以及[React.js] Build An React App系列為基礎,依舊將API server跟web page server分開,以保留開發時的自由度,因此在cookie的操作上將是cross domain的。

Cookie

HTTP的特性之一是stateless(無狀態),網景公司發明cookie繞過無狀態而使HTTP更好使用,但也造成了一些問題。

讓我們回顧cookie在瀏覽器中的特性如下: 1.client端的資料有變動時,藉由寫入cookie可以知道使用者做了哪些動作。 2.cookie是用domain name區分 (domain specific),在任何時機點只要對該domain的server發送request,對應的cookie會被一併夾帶到server。 3.cookie在HTTP中是明文傳送,有安全性的疑慮。 4.cookie的形式為key-value pair,並可以設定expired time以指定其存活時間。

當server收到帶有cookie的request時將會將帶有cookie的response回去。因此也可以在server side為瀏覽器設定cookie。

Session

session是server side儲存使用者資訊的機制。

剛才有提到,server side有能力為瀏覽器設定cookie。使用場景是server會將使用者的uuid放到cookie中,因此如果使用者曾經登入過,當傳到server時,若cookie中的uuid在session中確實有對應的使用者,則可以視為已登入過。

以下是session儲存的地方以及其優缺點: 1.內存: 可能會造成memory leak。 2.緩存: 是實務上最常採用,像是Redis,Memcache。 3.cookie: cookie會隨之變大,而導致request的資料量變大。 4.Database: 可能會造成讀取相當頻繁。

Other storage: Local storage and Session storage

除了cookie外,可以儲存client端資料的還有 web storage,這是HTML5時加入的新技術,可細分為local storage及session storage兩種,三者差異如下:

1.cookie: 大小大約4kb,關閉瀏覽器後會被清除,client side跟server side都可以設定cookie。 2.local storage: 大小大約5MB,將會被永久保存,需要被清除(explicitly deleted),但僅存在於client side中,不參與跟server side的通訊。 3.session storage:大小大約5MB,關閉瀏覽器或是頁面都會清除,但僅存在於client side中,不參與跟server side的通訊

用cookie可以追蹤使用者的行為,然而現在歐洲國家有GDPR使用cookie時都必須要提示consent給使用者,使用者也必須同意。 web storage由於無法參與與server side的通訊,因此無法追蹤使用者的行為。

Copy right@A layman

workflow

接著要說明的是web page server與API server的workflow,以Sign up為例:

Copy right@A layman
  • Web page的行為: 使用者訪問/signup頁面並送出使用者資料時,頁面會透過AJAX呼叫 API server的/signup endpoint,設定session並儲存使用者資料,會再透過AJAX呼叫call API server的/user endpoint以獲得使用者資料,並更新狀態React component的state,此時會重新rendering頁面,用User component取代Signup component。
  • API server的行為: 1.檢查使用者的名字是否被註冊過了。 2.建立新的Session及替clien side設定cookie。 3.將使用者資訊存到database (這裡是用內存當範例)。

Login的workflow:

Copy right@A layman
  • Web page的行為: 使用者訪問/login頁面並送出資料時,頁面會透過AJAX呼叫 API server的/login endpoint,設定session並儲存使用者資料,會再透過AJAX呼叫call API server的/user endpoint以獲得使用者資料,並更新狀態React component的state,此時會重新rendering頁面,用User component取代Signup component。
  • API server的行為: 1.檢查使用者的名字是否被註冊過了。 2.建立新的Session及替clienside設定cookie。

Logout則是清除sessin及使用者的cookie。

Implementation

Web page server and React components

Copy right@A layman

Web page server的架構是延續[React.js] Build An React App part.2- Material-UI, SPA and React Router. web page server為SPA,採用Node.js,僅提供一個entry point且有三個頁面: 1. /Sign up: 提供新註冊用的表單 2. /Login: 提供登入用的表單。 3. /User: 登入成功後跳轉的頁面 + Log out按鈕。

檔案結構將會如左圖所示, 多了Register.js,Login.js及User.js。

Main page component

要注意的事有:

  • 用react-dom-router的Route來控制路由,並用render來加入條件判斷,並在child components裡更新parent component的state.hasLogin。
  • 在componentDidMount時檢查cookie,有cookie則詢問API server此使用者是註冊過,若有則親自改寫state.hasLogin (使用js-cookie)。

MainPage.js的程式碼如下:

Fetch in React

關於React中使用Fetch使用方法,先前在此篇文章已經有簡單介紹過: [Golang] Build A Simple Web Service part.5 — Communicate with the ReactJS page, 這裡再記錄一些細節。

Fetch的Request參數比較重要的是mode跟credentials,mode可分為same-origin/cors/cors-with-forced-preflight/no-cors; 而credentials可分為include/omit/same-origin。

Fetch的Response類型也有分成三種, 分別是basic/cors/opaque,basic可以拿到response的所有資料,cors除了Cache-Control,Content-Language,Content-Type,Expires,Last-Modified和 Progma之外的資料都拿不到,如果是opaque則基本上拿不到任何有用的資料。

在跨域操作Cookie時,需要將mode設為no-cors及將credentials設為include,而這樣得到的Response類型會是opaque。

Sub page component

需要新增Register.js,Login.js及User.js。

Register.js的程式碼:

Login.js的程式碼:

User.js的程式碼:

API server

API server的架構是延續[Golang] Build A Simple Web Service part.5 — Communicate with the ReactJS page的專案。API server提供3個end point: 1. /Sign up: 新增新的session並將使用者資料寫到database (或內存) 2. /Login 3. /Logout

新用到的package將會有:

程式碼只要修改routes/webService.go的內容,此範例用內存代替database以簡化程式碼,並新增兩個global variable: dbSessions以存放當前的session,dbUsers存放註冊過的使用者資料。

getUser()會回傳JSON格式的資料,將Golang struct封裝成JSON格式回傳有兩種方式,一種是用json.Marshall, 寫法如下:

第二種是用json.NewEncoder.encode,也是這次的範例所採用的方式,routes/webService.go的程式碼如下:

Summary

下圖為Sign up的頁面(使用者登入前):

Copy right@A layman

使用者登入後的頁面:

Copy right@A layman

在Golang及React都有一些累積後,逐漸進到前後端互動的操作,登入,登出,註冊,這篇牽涉到的範圍有點廣,盡可能地將這篇整理地收斂一些,若有不清楚的地方建議您可以參考Related topics或是Reference。

謝謝你耐心地讀到Summary,我是Sean HS, 是位軟體工程師。 這片文章是我在研究過程時的筆記,若有錯誤之處,期待您的見解,與您交流討論。

Related topics

Introduction To SaaS for APM & Logging

[Golang] Build A Simple Web Service:

[React.js] Build An React App:

  1. gorilla/sessions 学习笔记
  2. Go实战 — Gorilla web toolkit使用之gorilla/sessions(iris+sessions)
  3. 介紹 Session 及 Cookie 兩者的差別說明
  4. React-router-dom: Redirect
  5. React-cookie
  6. js-cookie
  7. 使用 Fetch 發送請求 ( request )區段
  8. Pass props to a component rendered by React Router
  9. CORS requests with session/cookie
  10. Fetch进阶指南
  11. Golang Response Snippets: JSON, XML and more
Web Development
Golang
React
Software Development
中文
Recommended from ReadMedium