HTTP methods 與 RESTful API


更新:

  1. Richardson 成熟度模型(2020-6-16更新)

目錄:

  1. RESTful 是什么
  2. JSON-server (提供 RESTful API 接口 + JSON 返回數據)
  3. 如何選擇 REST 方法
  4. HTTP verbs / method (安全 | 冪等)
  5. HTTP POST V.S. PUT
  6. REST POST | PUT | PATCH

 

  • Richardson 成熟度模型2020-6-16更新)可以幫助層層遞進地思考RESTful本質思想。
    • level0 -類似RPC
      • 利用http,但不使用Web的任何機制
    • level1-資源;面向對象
      • 面向對象的思想。將一個資源的對外顯示方式和內部存儲方式解耦。
    • level2-動詞&響應碼
      • 遵循http規則,合理使用http動詞,來利用Web的一些能力。(如GET請求,允許路由中的各級參與者使用緩存,因為GET方法是冪等的)
      • 配合響應狀態碼來表明過程中的種種錯誤。
    • level3-超媒體控制
      • 服務器的相應中告訴了下一步能做什么,即對應的URI。
      • 客戶端和服務端有隱式的約定,可以改變服務端返回的URI,而客戶端不受影響。(如不論網站怎么迭代,用戶總可以找到加入購物車的按鈕)
        • 第1次:rel="/cart",href="/cart/cartInitialized"
        • 第N次:rel="/cart",href="/cart/cartUpdated"

 

  • RESTful 是什么 阮一峰:理解RESTful架構

    • Representational State Transfer 表征狀態轉移
    • 核心:resource。representation 指的是 resource 的表現層。
      resource,資源,即一個實體(文本/圖片/服務),可以用一個 URI 唯一標識。
    • representation,表現層
      資源,是一個實體,可以有多種外在表現形式。這個表現形式,即 representation 表現層。
      e.g. 文本可以用txt表示,也可以用 HTML/ XML/ JSON。
    • State Transfer,狀態轉移
      client <-> server,這個交互涉及到數據和狀態的變化。
      client 操作 server,即通過某種手段(HTTP method),使 server 發生狀態轉移。

    • 目前對 REST 的理解:(2016-8-20)

      • 每個 URI 代表一種資源。用名詞表示。
      • HTTP method 表示對資源進行了哪種類型的操作。
    • HTTP verbs 推薦返回的狀態碼 

    • TOP10 HTTP Status Code in REST
      • 200 OK 201 Created 204 No Content
      • 304 Not Modified
      • 400 Bad Request 401 Unauthorized 403 Forbidden 404 Not Found 409 Conflict
      • 500 Internal Server Error
    • 水很深,現在還理解不了

JSON-Server

  • JSON-Server 是一款前端測試工具,可提供 REST API + JSON 服務。
  • 來看一組 JSON-Server 提供的 RESTful API 接口:

    GET   /posts    //獲取posts下的所有資源
    GET   /posts/1  //獲取posts下id為1的資源
    GET   /posts?title=json-server&author=typicode //獲取posts下title=json-server&author=typicode的資源
    POST  /posts   //posts添加操作
    PUT   /posts/1 //對posts下id為1的資源進行修改操作:完全替換
    PATCH /posts/1 //對posts下id為1的資源進行修改操作:局部更新
    DELETE   /posts/1  //對posts下id為1的資源進行刪除操作
    
  • 有這兩個明顯的特點:
    • 每個 URI 代表一種資源。用名詞表示。
    • HTTP method 表示對資源進行了哪種類型的操作。
  • 使用時需注意:

    • get
      將查詢的參數用 & 拼接成查詢字符串

      if(data && Object.prototype.toString.call(data) == "[object Object]") {
          for (var i in data) {
              dataStr += i + "=" + data[i] + "&";
          }
      }
      
      lastPos = dataStr.lastIndexOf("&");
      dataStr = dataStr.slice(0, lastPos);

       

    • post put patch 請求中,content-type的值必須為 application/json
      相應的,需要將提交的數據,由 JS對象 -> JSON  JSON.stringify()

      xhr.setRequestHeader("content-type", "application/json");
      xhr.send(data ? JSON.stringify(data) : null);

       


  • RESTful

    RESTful 只是一種 architectural style,意思是如果大家都依此行事的話,溝通成本會很低,開發效率就高。

    那么只要前后台約定好,就可以隨意選取方法了么?

    This is wrong because a request passes through many intermediaries and middleware applications which perform optimizations based on the HTTP method type. These optimizations depend on two key characteristics of HTTP methods: idempotency and safety, which are defined in the HTTP specification.
    Code Ahoy: REST Design - Choosing the Right HTTP Method

    從這個角度來說,對哪種操作使用哪種方法,取決於 HTTP 方法本身的特性前后台交互接口的約定

  • HTTP 方法的兩個關鍵特性:安全|冪等safe|idempotent

    • safe
      安全的方法被期望不會產生任何副作用(side effects)。這些操作是只讀的。e.g. 查詢數據庫。
    • idempotent
      冪等的方法保證了重復進行一個請求和一次請求的效果相同。(並不是指返回 client 的響應總是相同的;而是指 server 上資源的狀態從第一次請求后就不再改變)
      在數學中,冪等性指N次變換和一次變換的結果相同。

      x = 1;    /* 冪等 */
      x++;      /* 非冪等 */
      

  • 安全|冪等 是由 HTTP 標准定義的契約:開發者在實現 RESTful API 時必須遵守。

    • 如果一個操作沒有以冪等的方式實現,那么即使它是通過 GET 方法調用的,它也不會自動變成 冪等的/ 安全的。
    • 當使用 HTTP 構建 RESTful 程序時,對HTTP method 的實現應該滿足其安全性和冪等性,來使 client 和中間件能自由地按契約優化,並增強用戶體驗。

      e.g. 瀏覽器並不確切知道某個特定的 form 用途,但如果這個 form 是通過 HTTP GET 提交的,瀏覽器就會知道當出現網絡異常的時候,它可以安全的、自動再次嘗試提交。 而通過 HTTP POST 提交的 form,如果瀏覽器不先向用戶確認就重復提交,會是不安全的。

  • RESTful 下的 post put patch

    • post

      • 非冪等:兩次相同的POST請求會在服務器端創建兩份資源,它們具有不同的URI。
      • POST 所對應的URI並非創建的資源本身,而是資源的接收者。比如:POST xx/articles 的語義是在 xx/articles下創建一篇帖子。
      • 從另一個角度理解 POST 如何設計下單的接口?post /orders ?

        本來 POST 就是被設計來提交表單這樣的事務型操作的。所以 POST 可以理解為執行服務器的一個事務。POST 請求服務器執行一個動作,多次發起請求可能導致動作多次執行:非冪等。

    • put
      • 冪等:對同一URI進行多次PUT的副作用和一次PUT是相同的。
      • PUT 所對應的URI是要創建或更新的資源本身。比如:PUT xx/articles/4231 的語義是創建或更新ID為4231的帖子。
    • patch
      • 非冪等 e.g. patch 可以對資源進行邏輯判斷增量修改,如每次加3,那么執行多次,就會造成額外影響。
      • 對已有資源的局部更新(而不用指定整個資源)。

  • 有人認為應該用 POST 來創建新資源,用 PUT 來更新已有資源。如果用 POST 來做更新操作,就不符合 RESTful 風格。

  • 實際並非如此。

    The REST standard doesn’t stop us from using POST requests for updates. In fact, it doesn’t even talk about it because idempotency and safety guarantees are properties of the HTTP protocol, not of the REST standard.

    作者 Code Ahoy 又引用了 Roy Fielding 的話, 大意是,例如 RESTful 不使用 GET 來進行不安全的操作,是因為這會違反 HTTP 中對 GET 方法的定義,反過來就會影響中間件和搜索引擎。由 HTTP 定義的方法是 Web's architecture definition 的一部分,而不屬於 REST architecture style.

  • 因此,使用 POST 還是 PUT 歸結於:這些方法的冪等性保證。

  • 因為 PUT 是冪等的,所以當第一個請求的響應沒有及時到達的時候,clients 或者中間件可以重復發送 PUT 請求,而不用考慮 server 是否已經處理了第一個請求。 而為了保證冪等性,PUT 請求必須替換整個資源,因此必須發送所有屬性。 如果要進行局部更新,就必須使用 POST 或者 PUT 這些非冪等的方法。


  • 既然選擇 POST 還是 PUT 不屬於 REST architecture style 的范圍,而屬於 HTTP 的設計,那我們來看看兩者在 HTTP 中分別應用於什么場景。
  • HTTP 中的 POST V.S. PUT

    The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request – the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. Method Definitions RFC2616

    • POST 和 PUT 最根本的區別反映在 request URI 的含義上:

      • POST 請求中的 URI,標識了要處理所附實體的資源。
      • PUT 請求的的 URI,標識了所附實體。
    • PUT

      PUT puts a file or resource at a specific URI, and exactly at that URI.

      如果這個這個 URI 所指定的位置上已有資源,PUT 就會替換掉這個資源;如果沒有, PUT 會創建一個。
      但是 PUT 請求的響應不會被緩存。

    • POST

      POST sends data to a specific URI and expects the resource at that URI to handle the request.

      POST 請求的響應的是可以緩存的,只要 server 設置了合適的 Cache-Control 和 Expires 首部。

      HTTP RFC 指定 POST 用來:

      • Annotation of existing resources;
      • Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
      • Providing a block of data, such as the result of submitting a form, to a data-handling process;
      • Extending a database through an append operation.
    • 使用 REST 的好處之一就是促進了 HTTP verbs/methods 的正確使用。

    • What's the difference between a POST and a PUT HTTP REQUEST?

  • 最后來歸納一下:

    POST to a URL creates a child resource at a server defined URL.
    PUT to a URL creates/replaces the resource in its entirety at the client defined URL.
    PATCH to a URL updates part of the resource at that client defined URL.

    • post put

      創建的對象,其URL是由 client 命名,還是 server?server 決定 - post;client 命名 - put.

      如果只是知道這個資源的父級類別的 URL,用 post;(比如說創建的資源id是數據庫中自增長的);

      POST /expense-report
      

      換句話說,如果知道將要創建的資源的 URL,用 put

      PUT  /expense-report/10929
      

      put 是創建時的一個候選方法:當 client 在資源創建前就已經知道了它的URL。

    • put patch

      • put 用來對已知資源做完全替換,要求前端提供一個完整的資源對象,缺了的字段會被清空。
      • patch 做局部更新,后台只會更新接收到的字段。【節省帶寬】
    • ref:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM