來源:互聯網
上載者:User
關鍵字
RESTful
GET
description
status
create
比如設計一個GET介面,用來擷取滿足條件的商品
GET shop/1/goods?
參數可能是五花八門的,name,create_time,description, status, owner...
通常這種情況,如果不考慮RESTful,就會設計成POST。
但是現在RESTful風格要求做成GET,如何處理會比較合適?
回複內容:
先說結論,可以,使用POST來處理參數比較長的search請求並沒有違反REST。
再說說@張立理 同學的答案裡可以改進的地方。在張同學的理論主義玩法裡:
有這樣的URL:
/goods/ 商品集合
變通不是必要的。如果是因為URI可能超長,導致了某個組件不支援,那麼換一個組件就好了。
根據 Fielding Dissertation: CHAPTER 6: Experience and Evaluation
6.3.2.5 Size Limits 裡提到的:
There is no limit in the HTTP protocol on the length of URI
儘管
Although older Web clients have a well-known problem with URI that consist of more than 255 characters
解決方案是:
applications within a controlled context (such as an intranet) can avoid those limits by replacing the older components
首先承認超過GET的URL總長度的情況確實可能存在的,一個比較典型的情境就是多選id,鬼知道一個變態能選出多少個來
當然一個合理的應用不應該讓這種情況出現,畢竟用手勾選到能超過URL的長度限制應該是會抽筋的,我們親愛的產品組應該為使用者著想
至於“全選”和“全選後取消幾個”這種情境,其一我很懷疑後者的使用者情境是否真的存在,其二可以使用全選和反選標記來給予實現,也並不是什麼麻煩事兒
繼續說真的超過了URL長度限制怎麼辦,第一反應自然是拿POST來玩,但是使用POST除去教條式的語義性和REST規範之外,一個很嚴重的影響是
無法使用HTTP緩衝
當然這個也不是什麼大問題,畢竟
99.99%的應用是不會精心設計HTTP緩衝的(是的這句話是在噴包括自己在內的很多工程師),所以搜尋這種情境從一開始就幾乎是沒有HTTP緩衝支援
那如果我還是想要緩衝,還是想要遵守REST規範使用GET怎麼辦呢?這裡有一個理論主義的玩法
假設我們對商品進行檢索,有這樣的URL:
/goods/ 商品集合
get也可以帶body樓主的問題是一個很典型的問題,經常有人問我。我的回答一律是:別折騰了,你們根本就做不了RESTful。
絕大部分人都理解RESTful是一種介面的設計形式,然後發現很多時候某些需求根本沒法做成RESTful形式的,但就我看來RESTful是從底層架構就應該考慮的問題,或者說是一種架構設計思想,而不僅僅只針對於介面。
比如題主的這個情況,如果要讓我來做,我會設計兩個介面
POST /shop/1/query 建立一個商品的查詢,返回id
GET /shop/1/query/{id} 擷取某個查詢的結果
為什麼要這麼設計?
1.RESTful中,URI代表資源,html/圖片這類檔案是資源,query這類服務也是資源
2.RESTful中,POST用來建立或者更新,GET用來擷取資源
但是很顯然,這肯定不滿足題主的需求,要這樣做現有的架構肯定滿足不了,所以我勸題主別折騰什麼RESTful了,怎麼好做怎麼來---更新 20160213 ---
突然發現貌似 Polyfill 的方案好像和 @立青 童鞋的想法類似。。
---更新 20160213 ---
正如 @張立理@劉尚奇 所說,確實查詢條件過長的情況有可能存在,但是傾向於認為其設計的 API 過於複雜(對於每一種 Entity 的介面,都要另外設計一個 Query 的介面),並且導致了有條件查詢和無條件查詢介面的不一致性,以及使用了一個沒有確切 Representation 的中間類型。所以在此重新給出一個簡潔一致的通用介面。
1. 無條件查詢:
直接 GET。
GET /goods HTTP/1.1
GET /xxx?type=[1|2|3|4|5|6|7|8] 百試不爽,但是!別打我!前端用的也挺happy的⋯⋯要麼是get帶query string,要麼是post帶body。get帶body不符合http規範,這麼做有後患。
權衡因素:
- query string的長度限制,因用戶端瀏覽器(Firefox, Chrome, IE)和伺服器(Apache, IIS)而異。query string除了普通的索引值對,還可以包含集合參數,後者是有可能超出長度限制的,要小心
- get+query string對cache更友好
- get+query string可加入瀏覽器收藏夾
- get+query string對搜尋引擎更友好
對於複雜search做成post,不見得就違反了Restful。你可以理解為,每次search的結果是一個新建立的臨時集合。restful本來就是拿來裝的,沒必要那麼較真首先,
REST 是一種設計風格而不是標準,如果一個架構符合
REST 原則,我們就稱它為
RESTful 架構。
其關鍵就在於如何抽象資源,抽象得越好,介面設計也就越加符合
REST 風格,即能夠享受到更多 HTTP 所帶來的「好處」,要知道 Roy Fielding 是在完成 HTTP 1.1 設計之後才回到大學讀博,在博士論文中總結出了
REST。
然而,如同所有程式世界的矛盾一樣,現實中的抽象問題永遠無法得到完美的映射。
=====================進入正題=====================
搜尋能不能抽象成一個資源,這取決於你怎麼看待和使用這個介面。通常來說一個資源會有 CURD 幾種介面,如果硬要套用
REST的理念
,對應到「搜尋」這個資源其實可以這麼理解:
拆分成 create(POST)和 read(GET)這兩種介面,create 通過 POST 方法把關鍵字傳給伺服器建立一個資源,然後再通過 GET 方法顯示最後的搜尋結果。
而與此同時還有一個好處就是記錄使用者的搜尋曆史,一個使用者資源連結著多個 Search 資源,每個資源只有自己的 GET 方法,只不過是我們沒有在伺服器提供其他方法的映射。