restful api

https://blog.igevin.info/posts/restful-architecture-in-general/


Request 和 Response

????????RESTful API的開發(fā)和使用,無非是客戶端向服務(wù)器發(fā)請求(request),以及服務(wù)器對客戶端請求的響應(yīng)(response)。RESTful架構(gòu)風(fēng)格具有統(tǒng)一接口的特點,即,使用不同的http方法表達(dá)不同的行為

????????GET(SELECT):從服務(wù)器取出資源(一項或多項)

????????POST(CREATE):在服務(wù)器新建一個資源

????????PUT(UPDATE):在服務(wù)器更新資源(客戶端提供完整資源數(shù)據(jù))

????????PATCH(UPDATE):在服務(wù)器更新資源(客戶端提供需要修改的資源數(shù)據(jù)

????????DELETE(DELETE):從服務(wù)器刪除資源

????????客戶端會基于GET方法向服務(wù)器發(fā)送獲取數(shù)據(jù)的請求,基于PUT或PATCH方法向服務(wù)器發(fā)送更新數(shù)據(jù)的請求等,服務(wù)端在設(shè)計API時,也要按照相應(yīng)規(guī)范來處理對應(yīng)的請求,這點現(xiàn)在應(yīng)該已經(jīng)成為所有RESTful API的開發(fā)者的共識了,而且各web框架的request類和response類都很強大,具有合理的默認(rèn)設(shè)置和靈活的定制性,在響應(yīng)request時,常用的Response要包含的數(shù)據(jù)和狀態(tài)碼(status code):

????????當(dāng)GET,?PUT和PATCH請求成功時,要返回對應(yīng)的數(shù)據(jù),及狀態(tài)碼200,即SUCCESS

????????當(dāng)POST創(chuàng)建數(shù)據(jù)成功時,要返回創(chuàng)建的數(shù)據(jù),及狀態(tài)碼201,即CREATED

????????當(dāng)DELETE刪除數(shù)據(jù)成功時,不返回數(shù)據(jù),狀態(tài)碼要返回204,即NO CONTENT

????????當(dāng)GET?不到數(shù)據(jù)時,狀態(tài)碼要返回404,即NOT FOUND

????????任何時候,如果請求有問題,如校驗請求數(shù)據(jù)時發(fā)現(xiàn)錯誤,要返回狀態(tài)碼?400,即BAD REQUEST

????????當(dāng)API 請求需要用戶認(rèn)證時,如果request中的認(rèn)證信息不正確,要返回狀態(tài)碼?401,即NOT AUTHORIZED

????????當(dāng)API 請求需要驗證用戶權(quán)限時,如果當(dāng)前用戶無相應(yīng)權(quán)限,要返回狀態(tài)碼?403,即FORBIDDEN

????????最后,關(guān)于Request 和 Response,不要忽略了http header中的Content-Type。以json為例,如果API要求客戶端發(fā)送request時要傳入json數(shù)據(jù),則服務(wù)器端僅做好json數(shù)據(jù)的獲取和解析即可,但如果服務(wù)端支持多種類型數(shù)據(jù)的傳入,如同時支持json和form-data,則要根據(jù)客戶端發(fā)送請求時header中的Content-Type,對不同類型是數(shù)據(jù)分別實現(xiàn)獲取和解析;如果API響應(yīng)客戶端請求后,需要返回json數(shù)據(jù),需要在header中添加Content-Type=application/json。


Serialization 和 Deserialization

????????Serialization 和 Deserialization即序列化和反序列化。RESTful API以規(guī)范統(tǒng)一的格式作為數(shù)據(jù)的載體,常用的格式為json或xml,以json格式為例,當(dāng)客戶端向服務(wù)器發(fā)請求時,或者服務(wù)器相應(yīng)客戶端的請求,向客戶端返回數(shù)據(jù)時,都是傳輸json格式的文本,而在服務(wù)器內(nèi)部,數(shù)據(jù)處理時基本不用json格式的字符串,而是native類型的數(shù)據(jù),最典型的如類的實例,即對象(object),json僅為服務(wù)器和客戶端通信時,在網(wǎng)絡(luò)上傳輸?shù)臄?shù)據(jù)的格式服務(wù)器和客戶端內(nèi)部,均存在將json轉(zhuǎn)為native類型數(shù)據(jù)和將native類型數(shù)據(jù)轉(zhuǎn)為json的需求,其中,將native類型數(shù)據(jù)轉(zhuǎn)為json即為序列化,將json轉(zhuǎn)為native類型數(shù)據(jù)即為反序列化。雖然某些開發(fā)語言,如Python,其原生數(shù)據(jù)類型list和dict能輕易實現(xiàn)序列化和反序列化,但對于復(fù)雜的API,內(nèi)部實現(xiàn)時總會以對象作為數(shù)據(jù)的載體,因此,確保序列化和反序列化方法的實現(xiàn),是開發(fā)RESTful API最重要的一步準(zhǔn)備工作。

? ??????序列化和反序列化是RESTful API開發(fā)中的一項硬需求,所以幾乎每一種常用的開發(fā)語言都會有一個或多個優(yōu)秀的開源庫,來實現(xiàn)序列化和反序列化,因此,我們在開發(fā)RESTful API時,沒必要制造重復(fù)的輪子,選一個好用的庫即可,如python中的marshmallow,如果基于Django開發(fā),Django REST Framework中的serializer即可。


Validation

????????Validation即數(shù)據(jù)校驗,是開發(fā)健壯RESTful API中另一個重要的一環(huán)。仍以json為例,當(dāng)客戶端向服務(wù)器發(fā)出post,?put或patch請求時,通常會同時給服務(wù)器發(fā)送json格式的相關(guān)數(shù)據(jù),服務(wù)器在做數(shù)據(jù)處理之前,先做數(shù)據(jù)校驗,是最合理和安全的前后端交互。如果客戶端發(fā)送的數(shù)據(jù)不正確或不合理,服務(wù)器端經(jīng)過校驗后直接向客戶端返回400錯誤及相應(yīng)的數(shù)據(jù)錯誤信息即可。常見的數(shù)據(jù)校驗包括:

????????數(shù)據(jù)類型校驗,如字段類型如果是int,那么給字段賦字符串的值則報錯

????????數(shù)據(jù)格式校驗,如郵箱或密碼,其賦值必須滿足相應(yīng)的正則表達(dá)式,才是正確的輸入數(shù)據(jù)

????????數(shù)據(jù)邏輯校驗,如數(shù)據(jù)包含出生日期和年齡兩個字段,如果這兩個字段的數(shù)據(jù)不一致,則數(shù)據(jù)校驗失敗

????????以上三種類型的校驗,數(shù)據(jù)邏輯校驗最為復(fù)雜,通常涉及到多個字段的配合,或者要結(jié)合用戶和權(quán)限做相應(yīng)的校驗。Validation雖然是RESTful API 編寫中的一個可選項,但它對API的安全、服務(wù)器的開銷和交互的友好性而言,都具有重要意義。因此,開發(fā)一套完善的RESTful API時,Validation的實現(xiàn)必不可少。


Authentication 和 Permission

????????Authentication指用戶認(rèn)證,Permission指權(quán)限機制,這兩點是使RESTful API 強大、靈活和安全的基本保障。

????????常用的認(rèn)證機制是Basic Auth和OAuth,RESTful API 開發(fā)中,除非API非常簡單,且沒有潛在的安全性問題,否則,認(rèn)證機制是必須實現(xiàn)的,并應(yīng)用到API中去。Basic Auth非常簡單,很多框架都集成了Basic Auth的實現(xiàn),自己寫一個也能很快搞定,OAuth目前已經(jīng)成為企業(yè)級服務(wù)的標(biāo)配,其相關(guān)的開源實現(xiàn)方案非常豐富。

????????權(quán)限機制是對API請求更近一步的限制,只有通過認(rèn)證的用戶符合權(quán)限要求,才能訪問API。權(quán)限機制的具體實現(xiàn)通常依賴于系統(tǒng)的業(yè)務(wù)邏輯和應(yīng)用場景,generally speaking,常用的權(quán)限機制主要包含全局型的和對象型的,全局型的權(quán)限機制,主要指通過為用戶賦予權(quán)限,或者為用戶賦予角色或劃分到用戶組,然后為角色或用戶組賦予權(quán)限的方式來實現(xiàn)權(quán)限控制;對象型的權(quán)限機制,主要指權(quán)限控制的顆粒度在object上,用戶對某個具體對象的訪問、修改、刪除或其行為,要單獨在該對象上為用戶賦予相關(guān)權(quán)限來實現(xiàn)權(quán)限控制。

????????全局型的權(quán)限機制容易理解,實現(xiàn)也簡單,有很多開源庫可做備選方案,不少完善的web開發(fā)框架,也會集成相關(guān)的權(quán)限邏輯,object permission 相對難復(fù)雜一點,但也有很多典型的應(yīng)用場景,如多人博客系統(tǒng)中,作者對自己文章的編輯權(quán)限即為object permission,其對應(yīng)的開源庫也有很多。

????????開發(fā)一套完整的RESTful API,權(quán)限機制必須納入考慮范圍,雖然權(quán)限機制的具體實現(xiàn)依賴于業(yè)務(wù),權(quán)限機制本身,是有典型的模式存在的,需要開發(fā)者掌握基本的權(quán)限機制實現(xiàn)方案,以便隨時應(yīng)用到API中去。


CORS

????????CORS即Cross-origin resource sharing,在RESTful API開發(fā)中,主要是為js服務(wù)的,解決javascript 調(diào)用 RESTful API時的跨域問題

????????由于固有的安全機制,js的跨域請求時是無法被服務(wù)器成功響應(yīng)的。現(xiàn)在前后端分離日益成為web開發(fā)主流方式的大趨勢下,后臺逐漸趨向只提供API服務(wù),為各客戶端提供數(shù)據(jù)及相關(guān)操作,而網(wǎng)站的開發(fā)全部交給前端搞定,網(wǎng)站和API服務(wù)很少部署在同一臺服務(wù)器上并使用相同的端口,js的跨域請求時普遍存在的,開發(fā)RESTful API時,通常都要考慮到CORS功能的實現(xiàn),以便js能正常使用API。

????????目前各主流web開發(fā)語言都有很多優(yōu)秀的實現(xiàn)CORS的開源庫,我們在開發(fā)RESTful API時,要注意CORS功能的實現(xiàn),直接拿現(xiàn)有的輪子來用即可。


URL Rules

????????RESTful API 是寫給開發(fā)者來消費的,其命名和結(jié)構(gòu)需要有意義。因此,在設(shè)計和編寫URL時,要符合一些規(guī)范。Url rules 可以單獨寫一篇博客來詳細(xì)闡述,本文只列出一些關(guān)鍵點。

? ? ? ? Version your API

????????規(guī)范的API應(yīng)該包含版本信息,在RESTful API中,最簡單的包含版本的方法是將版本信息放到url中,如:

????????另一種優(yōu)雅的做法是,使用HTTP header中的accept來傳遞版本信息,這也是GitHub API 采取的策略

????????Use nouns, not verbs

????????RESTful API 中的url是指向資源的,而不是描述行為的,因此設(shè)計API時,應(yīng)使用名詞而非動詞來描述語義,否則會引起混淆和語義不清。即:

????????上面四個url都是指向同一個資源的,雖然一個資源允許多個url指向它,但不同的url應(yīng)該表達(dá)不同的語義,上面的API可以優(yōu)化為:

????????article 資源的獲取、更新和刪除分別通過?GET,?PUT?和?DELETE方法請求API即可。試想,如果url以動詞來描述,用PUT方法請求?/api/deleteArticle/1/?會感覺多么不舒服。

? ??????GET?and?HEAD?should always be safe

????????RFC2616已經(jīng)明確指出,GET和HEAD方法必須始終是安全的。例如,有這樣一個不規(guī)范的API:

????????Nested resources routing

????????如果要獲取一個資源子集,采用?nested routing?是一個優(yōu)雅的方式,如,列出所有文章中屬于Gevin編寫的文章:

????????獲取資源子集的另一種方式是基于filter(見下面章節(jié)),這兩種方式都符合規(guī)范,但語義不同:如果語義上將資源子集看作一個獨立的資源集合,則使用?nested routing?感覺更恰當(dāng),如果資源子集的獲取是出于過濾的目的,則使用filter更恰當(dāng)。

????????Filter

????????對于資源集合,可以通過url參數(shù)對資源進(jìn)行過濾,如:

????????分頁就是一種最典型的資源過濾。

????????Pagination

????????對于資源集合,分頁獲取是一種比較合理的方式。如果基于開發(fā)框架(如Django REST Framework),直接使用開發(fā)框架中的分頁機制即可,如果是自己實現(xiàn)分頁機制,Gevin的策略是:

????????返回資源集合是,包含與分頁有關(guān)的數(shù)據(jù)如下:

????????另外,系統(tǒng)內(nèi)還設(shè)置一個per_page_max字段,用于標(biāo)記系統(tǒng)允許的每頁最大記錄數(shù),當(dāng)per_page值大于?per_page_max?值時,每頁記錄條數(shù)為?per_page_max。

????????Url design tricks

????????(1)Url是區(qū)分大小寫的,這點經(jīng)常被忽略,即:

????????????????/Posts

????????????????/posts

????????上面這兩個url是不同的兩個url,可以指向不同的資源

????????(2)Back forward Slash (/)

????????目前比較流行的API設(shè)計方案,通常建議url以/作為結(jié)尾,如果API?GET請求中,url不以/結(jié)尾,則重定向到以/結(jié)尾的API上去(這點現(xiàn)在的web框架基本都支持),因為有沒有?/,也是兩個url,即:

????????????????/posts/

????????????????/posts

????????這也是兩個不同的url,可以對應(yīng)不同的行為和資源

????????(3)連接符?-?和 下劃線?_

????????RESTful API 應(yīng)具備良好的可讀性,當(dāng)url中某一個片段(segment)由多個單詞組成時,建議使用?-?來隔斷單詞,而不是使用?_,即:?????

????????這主要是因為,瀏覽器中超鏈接顯示的默認(rèn)效果是,文字并附帶下劃線,如果API以_隔斷單詞,二者會重疊,影響可讀性。


restful 架構(gòu)風(fēng)格

????????REST即Representational State Transfer的縮寫,可譯為"表現(xiàn)層狀態(tài)轉(zhuǎn)化”。REST最大的幾個特點為:資源、統(tǒng)一接口、URI和無狀態(tài)


資源

????????資源是以json(或其他Representation)為載體的、面向用戶的一組數(shù)據(jù)集,資源對信息的表達(dá)傾向于概念模型中的數(shù)據(jù):

????????資源總是以某種Representation為載體顯示的,即序列化的信息

????????常用的Representation是json(推薦)或者xml(不推薦)等

????????Representation 是REST架構(gòu)的表現(xiàn)層

????????相對而言,數(shù)據(jù)(尤其是數(shù)據(jù)庫)是一種更加抽象的、對計算機更高效和友好的數(shù)據(jù)表現(xiàn)形式,更多的存在于邏輯模型中

????????資源和數(shù)據(jù)關(guān)系如下:


URI

????????可以用一個URI(統(tǒng)一資源定位符)指向資源,即每個URI都對應(yīng)一個特定的資源。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地址或識別符。

????????一般的,每個資源至少有一個URI與之對應(yīng),最典型的URI即URL。


無狀態(tài)

????????所謂無狀態(tài)的,即所有的資源,都可以通過URI定位,而且這個定位與其他資源無關(guān),也不會因為其他資源的變化而改變。有狀態(tài)和無狀態(tài)的區(qū)別,舉個簡單的例子說明一下。如查詢員工的工資,如果查詢工資是需要登錄系統(tǒng),進(jìn)入查詢工資的頁面,執(zhí)行相關(guān)操作后,獲取工資的多少,則這種情況是有狀態(tài)的,因為查詢工資的每一步操作都依賴于前一步操作,只要前置操作不成功,后續(xù)操作就無法執(zhí)行;如果輸入一個url即可得到指定員工的工資,則這種情況是無狀態(tài)的,因為獲取工資不依賴于其他資源或狀態(tài),且這種情況下,員工工資是一個資源,由一個url與之對應(yīng),可以通過HTTP中的GET方法得到資源,這是典型的RESTful風(fēng)格。


ROA、SOA、REST與RPC

????????ROA即Resource Oriented Architecture,RESTful 架構(gòu)風(fēng)格的服務(wù)是圍繞資源展開的,是典型的ROA架構(gòu)(雖然“A”和“架構(gòu)”存在重復(fù),但說無妨),雖然ROA與SOA并不沖突,甚至把ROA看做SOA的一種也未嘗不可,但由于RPC也是SOA,比較久遠(yuǎn)一點點論文、博客或圖書也常把SOA與RPC混在一起討論,因此,RESTful 架構(gòu)風(fēng)格的服務(wù)通常被稱之為ROA架構(gòu),很少提及SOA架構(gòu),以便更加顯式的與RPC區(qū)分。

????????RPC風(fēng)格曾是Web Service的主流,最初是基于XML-RPC協(xié)議(一個遠(yuǎn)程過程調(diào)用(remote procedure call,RPC)的分布式計算協(xié)議),后來漸漸被SOAP協(xié)議(簡單對象訪問協(xié)議(Simple Object Access Protocol))取代;RPC風(fēng)格的服務(wù),不僅可以用HTTP,還可以用TCP或其他通信協(xié)議。但RPC風(fēng)格的服務(wù),受開發(fā)服務(wù)采用語言的束縛比較大,如.NET框架中,開發(fā)web service的傳統(tǒng)方式是使用WCF,基于WCF開發(fā)的服務(wù)即RPC風(fēng)格的服務(wù),使用該服務(wù)的客戶端通常要用C#來實現(xiàn),如果使用python或其他語言,很難實現(xiàn)可以直接與服務(wù)通信客戶端;進(jìn)入移動互聯(lián)網(wǎng)時代后,RPC風(fēng)格的服務(wù)很難在移動終端使用,而RESTful風(fēng)格的服務(wù),由于可以直接以json或xml為載體承載數(shù)據(jù),以HTTP方法為統(tǒng)一接口完成數(shù)據(jù)操作,客戶端的開發(fā)不依賴于服務(wù)實現(xiàn)的技術(shù),移動終端也可以輕松使用服務(wù),這也加劇了REST取代RPC成為web service的主導(dǎo)。

????????RPC與RESTful的區(qū)別如下面兩個圖所示:


認(rèn)證機制

????????由于RESTful風(fēng)格的服務(wù)是無狀態(tài)的,認(rèn)證機制尤為重要。例如上文提到的員工工資,這應(yīng)該是一個隱私資源,只有員工本人或其他少數(shù)有權(quán)限的人有資格看到,如果不通過權(quán)限認(rèn)證機制對資源做一層限制,那么所有資源都以公開方式暴露出來,這是不合理的,也是很危險的。

????????認(rèn)證機制解決的問題是,確定訪問資源的用戶是誰權(quán)限機制解決的問題是,確定用戶是否被許可使用、修改、刪除或創(chuàng)建資源。權(quán)限機制通常與服務(wù)的業(yè)務(wù)邏輯綁定,因此權(quán)限機制需要在每個系統(tǒng)內(nèi)部定制,而認(rèn)證機制基本上是通用的,常用的認(rèn)證機制包括?session auth(即通過用戶名密碼登錄),basic auth,token auth和OAuth,服務(wù)開發(fā)中常用的認(rèn)證機制為后三者。

OAuth

????????OAuth(開放授權(quán))是一個開放的授權(quán)標(biāo)準(zhǔn),允許用戶讓第三方應(yīng)用訪問該用戶在某一web服務(wù)上存儲的私密的資源(如照片,視頻,聯(lián)系人列表),而無需將用戶名和密碼提供給第三方應(yīng)用。

????????OAuth允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務(wù)提供者的數(shù)據(jù)。每一個令牌授權(quán)一個特定的第三方系統(tǒng)(例如,視頻編輯網(wǎng)站)在特定的時段(例如,接下來的2小時內(nèi))內(nèi)訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth讓用戶可以授權(quán)第三方網(wǎng)站訪問他們存儲在另外服務(wù)提供者的某些特定信息,而非所有內(nèi)容

????????正是由于OAUTH的嚴(yán)謹(jǐn)性和安全性,現(xiàn)在OAUTH已成為RESTful架構(gòu)風(fēng)格中最常用的認(rèn)證機制,和RESTful架構(gòu)風(fēng)格一起,成為企業(yè)級服務(wù)的標(biāo)配。

????????目前OAuth已經(jīng)從OAuth1.0發(fā)展到OAuth2.0,但這二者并非平滑過渡升級,OAuth2.0在保證安全性的前提下大大減少了客戶端開發(fā)的復(fù)雜性,因此,Gevin建議在實戰(zhàn)應(yīng)用中采用OAuth2.0認(rèn)證機制。



?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內(nèi)容