首頁 > 軟體

建立 REST API 的最佳入門教學

2020-06-16 17:49:48

如果你看到這裡,你以前可能聽說過API 和REST,然後你就會想:“這些都是什麼東西?”。也許你已經了解過一些這方面的知識,但卻不知道從何入手。在這個教學中,我將會詮釋REST的基礎以及如何給應用建立一個API(包括認證授權)。

 

什麼是API?

API是Application Programming Interface(應用程式介面)的縮寫,它是拿來描述一個類庫的特徵或是如何去運用它。你個人收藏的類庫也許包含有可用功能的“API文件”,那些必需的引數我們該怎麼稱呼它們?諸如此類等等。

然而,如今很多人參考API文件時,他們常常參考一種可能會通過網路分享你的應用資料HTTP API,例如,Twitter提供一個API能讓使用者在特定的格式下請求推文,以便使用者方便匯入到自己的應用程式中。這就是HTTP API的真正強大之處。它能夠從多個應用程式中混搭資料到混合應用程式中,或是建立一個能增強使用他人應用體驗的應用程式。

這樣說吧,比如說我們有一個可以允許我們檢視(view),建立(create),編輯(edit)以及刪除(delete)部件的應用程式。我們可以建立一個可以讓我們執行這些功能的HTTP API:

  1. http://example.com/view_widgets
  2. http://example.com/create_new_widget?name=Widgetizer
  3. http://example.com/update_widget?id=123&name=Foo
  4. http://example.com/delete_widget?id=123

當人們開始去實現他們自己的API介面時,問題就出現了。竟然沒有一個標準的方法來命名URL,人們總是要參考API才得知它是如何運作的。一個API中可能命名一個URL為/view_widgets,但是另一個API可能就命名成/widgets/all.

不用擔心!REST幫你搞定這些混亂!

 

什麼是REST?

REST是Representational State Transfer的縮寫,它是由羅伊·菲爾丁(Roy Fielding)提出的,是用來描述建立HTTP API的標準方法的,他發現這四種常用的行為(檢視(view),建立(create),編輯(edit)和刪除(delete))都可以直接對映到HTTP 中已實現的GET,POST,PUT和DELETE方法。

HTTP 中的8中不同的方法:

  1. GET
  2. POST
  3. PUT
  4. DELETE
  5. OPTIONS
  6. HEAD
  7. TRACE
  8. CONNECT

大多數情況下,當你在使用你的瀏覽器的點點看看的時候,其實只用到HTTP的GET方法。GET方法是在你向因特網請求資源的時候才會用到的。當你提交一個表單時,你就會經常用到POST方法來回傳資料到網站上。至於其他的幾種方法,某些瀏覽器可能根本就沒有去完全實現它們。但是,如果是供我們使用的話,就沒什麼問題。問題是我們有很多要選擇去幫助描述這四大行為的HTTP方法,我們將會用到那些已經知道如何去使用這些不同的HTTP方法的用戶端類庫。

 

REST例子

讓我們來看下幾個讓API表述性狀態轉移的例子,就用我們之前說的那幾個部件來解釋:

如果我們想要檢視所有部件,URL將是這個樣子:

  1. GET http://example.com/widgets

用POST方法新建一個用來發出請求資料的部件:

  1. POST http://example.com/widgets
  2. Data:
  3. name =Foobar

用GET方法檢視一個簡單的部件,我們從指定的部件id中獲取:

  1. GET http://example.com/widgets/123

用PUT方法傳送新資料來更新部件:

  1. PUT http://example.com/widgets/123
  2. Data:
  3. name =New name
  4. color = blue

用DELETE方法來刪除部件:

  1. DELETE http://example.com/widgets/123

 

解剖REST URL

你可能已經注意的前面的幾個例子,REST URL使用著一套一致的命名方法。當你跟API互動時,你幾乎經常操作一些物件。在我們的例子中,我們講的是部件。在REST中,我們稱之為Resource。URL的第一部分經常是這個資源的複數形式:

  1. /widgets

當我們參考收集的資源時(list all:列出所有 和add one:新增一個),這將會經常用到。當你用到一些特殊的資源的時候,你就會給URL增加一個id,這個URL在你想要“view”,“edit”和“delete”特殊資源的時候會被使用。

 

巢狀資源

如果說,我們的部件有很多使用者使用,URL的結構又將會是怎樣的呢?

列出所有使用者

  1. GET /widgets/123/users

新增一個使用者

  1. POST /widgets/123/users
  2. Data:
  3. name =Andrew

巢狀資源在URL裡是完全相容的,但是超過兩層巢狀就不是很好的方法了。其實這根本不需要,因為你完全可以以ID的形式參考到那些巢狀資源,總比巢狀在父類別中好。例如:

  1. /widgets/123/users/456/sports/789

這可以替換為:

  1. /users/456/sports/789

甚至可以替換成這樣:

  1. /sports/789

HTTP 狀態碼

REST的另一重要部分就是為既定好請求的型別來響應正確的狀態碼。如果你對HTTP狀態碼陌生,以下是一個簡易總結。當你請求HTTP時,伺服器會響應一個狀態碼來判斷你的請求是否成功,然後用戶端應如何繼續。以下是四種不同層次的狀態碼:

  • 2xx = Success(成功)
  • 3xx = Redirect(重定向)
  • 4xx = User error(用戶端錯誤)
  • 5xx = Server error(伺服器端錯誤)

以下是一些最重要的狀態碼:

 

請求成功的狀態碼:

  • 200 – OK (預設的)
  • 201 – Created(已建立)
  • 202 – Accepted (已接受:常用語刪除請求)

 

用戶端錯誤狀態碼:

  • 400 –請求出錯(語法格式有誤或伺服器無法理解此請求)
  • 401 – 未授權(需要登入)
  • 404 – 找不到 (找不到所請求的檔案或指令碼)
  • 405 – 不允許此方法(錯誤的 HTTP方法)
  • 409 – 衝突 (IE嘗試以PUT請求建立相同的資源時)

 

API響應格式

當你請求HTTP時,你可以請求你想要接收的格式。例如,請求一個網頁,你想以HTML的格式請求,或者如果你想要下載一張圖片,返回格式應該是圖片的格式。然而,響應請求格式是伺服器的職責。

如今,JSON 已經快速發展成為REST API選擇的格式,它有一個輕量級的、可讀性又很高的語法,以致其很容易操作。所以,當使用我們API的使用者按他們想要的格式發出請求和指定JSON時。

  1. GET /widgets
  2. Accept: application/json

我們的API將會以JSON的格式返回一批部件:

  1. [
  2. {
  3. id:123,
  4. name:'Simple Widget'
  5. },
  6. {
  7. id:456,
  8. name:'My other widget'
  9. }
  10. ]

要是使用者請求一個我們沒有實現的方法的格式時,我們又該怎麼辦呢?你大可以丟擲一些錯誤的型別。但我建議你將JSON格式作為你的標準響應格式,因為這是開發者想要的格式。沒理由去支援其他的格式,除非你已經有一個可支援的API。

 

建立一個REST API

事實上,建立一個REST API是超出此教學範圍的,因為它是有特定語言的。但我將以Ruby(一種為簡單快捷的物件導向程式設計而創的指令碼語言)的方式給出一個簡易例子,它使用一個叫Sinatra的類庫(不懂得可以自行百度)。

  1. require'sinatra'
  2. require'JSON'
  3. require'widget'#our imaginary widget model
  4. #list all
  5. get'/widgets'do
  6. Widget.all.to_json
  7. end
  8. # view one
  9. get'/widgets/:id'do
  10. widget=Widget.find(params[:id])
  11. returnstatus404ifwidget.nil?
  12. widget.to_json
  13. end
  14. # create
  15. post'/widgets'do
  16. widget=Widget.new(params['widget'])
  17. widget.save
  18. status201
  19. end
  20. # update
  21. put'/widgets/:id'do
  22. widget=Widget.find(params[:id])
  23. returnstatus404ifwidget.nil?
  24. widget.update(params[:widget])
  25. widget.save
  26. status202
  27. end
  28. delete'/widgets/:id'do
  29. widget=Widget.find(params[:id])
  30. returnstatus404ifwidget.nil?
  31. widget.delete
  32. status202
  33. end

 

API授權認證

在一般的網頁應用中,認證操作是經常要接收使用者名稱和密碼的,然後在session中儲存使用者ID。使用者的瀏覽器就會儲存對談中的ID到cookie中。當使用者在網站上存取需要認證授權的頁面時,瀏覽器就會傳送cookie,應用程式就會查詢seesion對談中的ID(如果它沒有失效的話),由於使用者的ID儲存在seesion中,使用者就可以瀏覽頁面了。

用這個API,就可以使用seesion對談儲存使用者記錄,但這畢竟不是最好的方法。有時候,使用者想直接存取API,或是使用者想自己授權其他應用程式去存取這個API。

解決方法是在認證的基礎上使用秘鑰。使用者輸入使用者名稱和密碼以登入,應用程式就以一個特殊秘鑰返回給使用者以備後續之需。這個秘鑰可以通入應用程式,以至於如果使用者想要選擇拒絕應用更進一步的接入時,可以撤回這個秘鑰。

其實,網上已經有一個做上面這件事的很流行的標準方式,叫做OAuth(開放授權:是一個開放標準,允許使用者讓第三方應用存取該使用者在某一網站上儲存的私密的資源(如照片,視訊,聯絡人列表),與以往的授權方式不同之處是OAUTH的授權不會使第三方觸及到使用者的帳號資訊(如使用者名稱與密碼),即第三方無需使用使用者的使用者名稱與密碼就可以申請獲得該使用者資源的授權,因此OAUTH是安全的。),特別的,標準第二版的OAuth。網上有很多非常好的實現OAuth的資源,所以我才說那是超出此教學範圍的。如果你正在使用Ruby,這裡有一些幫你解決大多數工作的很好的類庫,比如OmniAuth 。

花了那麼多時間給你們講解這個教學,希望對你們有所幫助。

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-11/125339.htm


IT145.com E-mail:sddin#qq.com