原文發表在我的個人部落格:REST - 如何抽象為資源(Resource)
HTTP 協議最初的目的是為了提供一種釋出和接收 HTML 頁面的方法。HTTP 1.0 之前的版本,支援的 Method 只有 GET
,用於獲取用 URI 定義的 HTML 檔案。
URI(Uniform Resource Identifiers)的含義是“統一資源定位符”,即從 HTTP 誕生之初,就是圍繞著**資源(Resource)**進行的。
2000年 Roy Thomas Fielding 發表著名論文《架構風格與基於網路的軟體設計》,被認為是首次提出了 REST(Representational State Transfer) 的概念。Fielding 本人也參與了 HTTP 的設計工作,說 HTTP 1.0/1.1 協議是 REST 的實踐者一點都不過分。
在 RESTful API 設計中,重點在於如何將 WEB 應用中的萬事萬物都抽象為資源,這個物件導向程式設計是有異曲同工之妙的。
就我個人而言,第一階段作為一個 PHP 初學者,所有操作是基於頁面跳轉/提交的。例如登入即先訪問 /login.php
,在這個頁面填寫一個表單,使用 POST
方法提交到 /login_post.php
,在 login_post.php
有判斷,成功則跳轉至使用者首頁 /my_homepage.php
,此時,在 my_homepage.php
已可以根據 PHP 內建變數 $_SESSION
查詢資料庫獲取當前使用者資訊,展示豐富的頁面。
這種方法很明顯是非常容易把展示性頁面可功能型頁面混淆,而且命名及其困難。
到了第二階段,開始使用 Ajax
傳遞資料(第二階段對 SPA 和 SSR 是一樣的), 依然是訪問 /login.php
填寫提交表單,但不再是一個頁面,而是一個 API。我會寫類似的 Jeuery 程式碼:
$.post (
"/api/login.php",
{
username: "user1",
password: "123456"
},
function (data, status) {
if (200 <= status < 300 && data.success) {
alert("Login Success");
location.href = "/my_homepage.php";
} else {
alert("Login Field");
}
}
);
複製程式碼
實際上,在這個階段我們實現了一種非常非常蹩腳的 JSON-RPC 協議。RPC 的主要思想是把函式對映到 API ,對應 login.php
就應該是一個抽象函式的例項,退出登入也是一個函式 logout.php
。即:
function login ($username, $password) -> Json;
function logout () -> Json;
複製程式碼
我一開始覺得登入、登出等操作抽象為資源很困難,主要原因是 PHP 、 Python Flask 這些工具已經遮蔽了 Session 實現的細節,我並不瞭解登入、登出等操作的本質。
對於 HTTP 協議來說,其本身是無狀態的,即使 HTTP/1.1 加入了 Connection: keep-alive
,但不能做到真正的長連線。於是大家想出了很多辦法來儲存使用者的登入狀態。從最早的不靠譜的 在 URL 引數裡寫入 Token 實現到 Cookie 到 Storage 甚至 IndexDB。
PHP 預設使用 Cookie 實現 Session,很多 PHP 網站返回的 HTTP 報文裡都會帶有一個 Cookie:PHPSESSID=xxx
的 HTTP Hearder。 PHP 就是靠這個 PHPSESSID 來判斷使用者身份的。同時 PHP 會在伺服器磁碟上留下相關檔案,來持久化儲存。
劃重點:使用者登入 = 建立識別符號、使用者登出 = 刪除識別符號
這裡資源即使用者識別符號,支援建立、刪除操作
建立(登入):
POST /api/token.php HTTP/1.1
Host: exapmle.com
Content-Type: application/json
{
"username": "user1",
"password": "123456"
}
複製程式碼
POST /user_access_token HTTP/1.1
Host: exapmle.com
Content-Type: application/json
Cookie:PHPSESSID=123456789
{
"msg": "登入成功",
"success": true
}
複製程式碼
刪除(登出):
DELETE /api/token.php HTTP/1.1
Host: exapmle.com
Content-Type: application/json
Cookie:PHPSESSID=123456789
{
"msg": "登出成功",
"success": true
}
複製程式碼
我們也可以不使用 PHP 自帶的 Seesion 功能,也可以自己實現,本文不在不說。