URL(統一資源定位符),咱們比較熟悉,URI是3個單詞的縮寫,Uniform Resource Identifierhtml
URI用字符串表示某一互聯網資源,而URL表示資源的地點,可見URL是URI的子集;採用HTTP協議時,協議方案就是http,除此以外,還有ftp、file等,標準的URI協議有30種方案左右。json
hierarchical part
┌───────────────────┴──────────────────┐
authority path
┌───────────────┴────────────┐┌───┴────┐
abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
└┬┘ └───────┬───────┘└────┬────┘└┬┘ └─────────┬───────┘ └──┬──┘
scheme user information host port query fragment
複製代碼
eg:api
登陸信息:指定用戶名和密碼做爲從服務器端獲取資源時必要的登陸信息(身份認證),可選項。緩存
查詢字符串:針對已指定的文件路徑內的資源,可使用查詢字符串傳入任意參數,可選項。安全
片斷標識符:使用片斷標識符一般可標識出已獲取資源中的子資源,可選項。bash
URI 和 URL 的區別:服務器
URI 用字符串標識某一互聯網資源,而 URL 標識資源的地址cookie
URL 是 URI 的子集網絡
發送規則app
HTTP協議規定,請求從客戶端發出,最後服務器端響應該請求並返回
HTTP無狀態
HTTP是一種不保存狀態,即無狀態協議,不會對以前發送過的請求進行信息的保存
GET(SELECT):從服務器取出資源(一項或多項)
POST(CREATE):在服務器新建一個資源
PUT(UPDATE):在服務器更新資源(客戶端提供改變後的完整資源)
PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)(通常使用PUT)
DELETE(DELETE):從服務器刪除資源
cookie會根據服務端發送的一個叫作Set-Cookie的首部字段信息,通知客服端保存Cookie,當下次客服端在往服務端發送請求的時候,客服端會自動在請求報文中加入Cookie而後發送過去,服務端接收到Cookie以後,對Cookie進行解析,而後找出是哪一個用戶。
eg:
1、請求報文(沒有Cookie信息的狀態)
GET /reader/HTTP/1.1
Host:host
// 首部字段沒有cookie的相關信息
複製代碼
2、響應報文(服務器端生成Cookie信息)
HTTP/1.1 200 OK
Date:Thu ,12 JUl 2012 07:12:20 GMT
Server: Apache
<Set-Cookie:sid=1342077140;path=/;expires=wed>
Content-Type:text/plain;charset=UTF-8
複製代碼
3、請求報文(自動發送保存的Cookie信息)
GET /image/ HTTP/1.1
Host host
Cookie:sid=1342077140
複製代碼
結構:首部 + 主體
分類:通用首部、請求首部、響應首部、實體首部、拓展首部
通用首部:客戶端和服務端均可以用,描述一些通用信息
請求首部:請求報文特有,爲服務器提供額外信息
響應首部:響應報文特有,爲客戶端提供信息
實體首部:描述實體主體部分的首部
拓展首部:非標準首部,由應用開發者建立,未添加到HTTP規範中
Date:報文建立時間
Connection:客戶端和服務器鏈接的有關選項
Via:報文通過的中間節點(代理、網關)
Cache-control:緩存
Host:接受請求的服務器的主機名和端口
Referer:當前請求的URL
UA-OS:客戶端操做系統及版本
Accept:告訴服務器可以發送的媒體類型
Accept-Charset:告訴服務器可以發送的字符集
Accept-Encoding:告訴服務器可以發送的編碼方式
Accept-Language:告訴服務器可以發送的語言
Authorization:包含客戶端提供給服務端,以便進行安全認證的數據
Cookie:客戶端須要發送的cookie
Cache-Control: 取值爲通常爲no-cache
或max-age=XX
,XX爲個整數,表示該資源緩存有效期(秒)
Allow:對該實體可執行的請求方法
Location:資源的新地址,重定向中經常使用到
Content-Language:理解主體應該使用的語言
Content-Length:主體的長度
Content-Encoding:對主體實行的編碼方式
Content-Type:主體的類型
Expires:實體再也不有效,須要再次獲取該實體的時間
Last-Modified:實體最後一次被修改的時間
Server:服務器應用軟件名稱及版本
Set-Cookie:設置cookie
1xx 信息響應
2xx 成功相應
3xx 重定向
4xx 客戶端響應
5xx 服務端響應
在 URL 中標明版本
eg:
http://shonzilla/api/v2.2/customers/1234
http://shonzilla/api/v2.0/customers/1234
http://shonzilla/api/v2/customers/1234
http://shonzilla/api/v1.1/customers/1234
http://shonzilla/api/v1/customers/1234
複製代碼
在 Header 中標明版本
自定義 header
HTTP GET:
https://haveibeenpwned.com/api/breachedaccount/foo
api-version: 2
複製代碼
利用 content type
HTTP GET:
https://haveibeenpwned.com/api/breachedaccount/foo
Accept: application/vnd.haveibeenpwned.v2+json
複製代碼
HTTP GET:
https://haveibeenpwned.com/api/breachedaccount/foo
Accept: application/vnd.haveibeenpwned+json; version=2.0
複製代碼
爲每一次的響應返回合適的HTTP狀態碼. 成功的HTTP響應應該使用以下的狀態碼:
200
: GET
請求成功, 以及DELETE
或 PATCH
同步請求完成
201
: POST
同步請求完成
202
: POST
, DELETE
, 或 PATCH
異步請求將要完成
。。。
對於用戶請求的錯誤狀況,及服務器的異常錯誤狀況,請查閱完整的HTTP狀態碼 HTTP response code spec
在 PUT
/PATCH
/POST
請求的body體使用JSON格式數據, 而不是使用 form 表單形式的數據. 這裏咱們使用JSON格式的body請求建立對稱的格式數據, 例如.:
$ curl -X POST https://service.com/apps \
-H "Content-Type: application/json" \
-d '{"name": "demoapp"}'
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "demoapp",
"owner": {
"email": "username@example.com",
"id": "01234567-89ab-cdef-0123-456789abcdef"
},
...
}
複製代碼
在默認狀況給每個資源一個id
屬性. 用此做爲惟一標識除非你有更好的理由不用.不要使用那種在服務器上或是資源中不是全局惟一的標識,好比自動增加的id標識。
返回的惟一標識要用小寫字母並加個分割線格式 8-4-4-4-12
, 例如.:
"id": "01234567-89ab-cdef-0123-456789abcdef"
複製代碼
提供默認的資源建立時間,更新時間 created_at
and updated_at
, 例如:
{
...
"created_at": "2012-01-01T12:00:00Z",
"updated_at": "2012-01-01T13:00:00Z",
...
}
複製代碼
這些時間戳可能不適用於某些資源,這種狀況下能夠忽略省去。
在接收的返回時間數據時只使用UTC格式. 查閱ISO8601時間格式, 例如:
"finished_at": "2012-01-01T12:00:00Z"
複製代碼
使用複數形式爲資源命名
好的末尾展示形式不準要指定特殊的資源形爲,在某些狀況下,指定特殊的資源的形爲是必須的,用一個標準的actions
前綴去替代他, 清楚的描述他:
/resources/:resource/actions/:action
複製代碼
例如.
/runs/{run_id}/actions/stop
複製代碼
使用小寫字母並用-
短線分割路徑名字,而且緊跟着主機域名 e.g:
service-api.com/users
service-api.com/app-setups
複製代碼
一樣屬性也要用小寫字母, 可是屬性名字要用下劃線_
分割。例如.:
"service_class": "first"
複製代碼
序列化的外鍵關係一般創建在一個有嵌套關係的對象之上, 例如.:
{
"name": "service-production",
"owner": {
"id": "5d8201b0..."
},
...
}
複製代碼
而不是這樣 例如:
{
"name": "service-production",
"owner_id": "5d8201b0...",
...
}
複製代碼
這種方式儘量的把相關聯的資源信息內聯在一塊兒,而不用改變響應資源的結構,或者展現更高一級的響應區域, 例如:
{
"name": "service-production",
"owner": {
"id": "5d8201b0...",
"name": "Alice",
"email": "alice@heroku.com"
},
...
}
複製代碼
在某些狀況下,爲了方便用戶使用接口,在末尾提供用id標識資源,例如,一個用戶想到了他在heroku平臺app的名字,可是這個app的惟一標識是id,這種狀況下,你想讓接口經過名字和id都能訪問,例如:
$ curl https://service.com/apps/{app_id_or_name}
$ curl https://service.com/apps/97addcf0-c182
$ curl https://service.com/apps/www-prod
複製代碼
不要只接受使用名字而剔除了使用id。
在網絡請求響應錯誤的時候,返回統一的,結構化的錯誤信息。要包含一個機器可讀的錯誤 id
,一我的類能識別的錯誤信息 message
, 根據狀況能夠添加一個url
,告訴客戶端關於這個錯誤的更多信息以及如何去解決它。 例如:
HTTP/1.1 429 Too Many Requests
複製代碼
{
"id": "rate_limit",
"message": "Account reached its API rate limit.",
"url": "https://docs.service.com/rate-limits"
}
複製代碼
把你的錯誤信息格式文檔化,以及這些可能的錯誤信息id
s 讓客戶端能獲取到.
在每個API響應中要包含一個Request-Id
頭信息, 一般用惟一標識UUID. 若是服務器和客戶端都打印出他們的Request-Id
, 這對咱們的網絡請求調試和跟蹤很是有幫助.
對於服務器響應的大量數據咱們應該爲此分頁。 使用Content-Range
頭傳遞分頁請求的數據.這裏有個例子詳細的說明了請求和響應頭、狀態碼,限制條件、排序以及分頁處理:Heroku Platform API on Ranges.
注:服務器會在響應頭中添加 Accept-Ranges: bytes
來表示支持 Range 的請求,以後客戶端纔可能發起帶 Range 的請求
eg:
# first
Content-Length:1200
Content-Range:bytes 0-1199/5000
# second
Content-Length:1200
Content-Range:bytes 1200-2399/5000
# third
Content-Length:1200
Content-Range:bytes 2400-3599/5000
# fourth
Content-Length:1400
Content-Range:bytes 3600-5000/5000
複製代碼
客戶端的訪問速度限制能夠維護服務器的良好狀態,進而爲其餘客戶端請求提供高性的服務
爲每個帶有 RateLimit-Remaining
響應頭的請求,返回預留的請求tokens。
在開始的時候指定API版本,使用Accepts
頭傳遞版本信息,也能夠是一個自定義的內容, 例如:
Accept: application/vnd.heroku+json; version=3
複製代碼
最好不要給出一個默認的版本, 而是要求客戶端明確指明他們要使用特定的版本.
提供人類可讀的文檔讓客戶端開發人員能夠理解你的API。
除此之在詳細信息的結尾,提供一個關於以下信息的API摘要:
驗證受權,包含獲取及使用驗證tokens.
API 穩定性及版本控制, 包含如何選擇所須要的版本.
通常的請求和響應頭信息.
錯誤信息序列格式.
不一樣語言客戶端使用API的例子.
提供可執行的示例讓用戶能夠直接在終端裏面看到API的調用狀況,最大程度的讓這些示例能夠逐字的使用,以減小用戶嘗試使用API的工做量。例如:
$ export TOKEN=... # acquire from dashboard
$ curl -is https://$TOKEN@service.com/users
複製代碼