Streaming HTTP responses【翻譯】

原文:Streaming HTTP responses

標(biāo)準(zhǔn)的應(yīng)答和Content-Length頭

由于HTTP 1.1遵守一個(gè)連接為多個(gè)HTTP請(qǐng)求和應(yīng)答服務(wù)開放的規(guī)則,因此服務(wù)器在應(yīng)答時(shí)必須發(fā)送相應(yīng)的Content-Length HTTP頭。

默認(rèn)情況下滞谢,當(dāng)你發(fā)送一個(gè)簡(jiǎn)單的結(jié)果,如:

public Result index() {
return ok("Hello World");
}

你沒有指定 Content-Length頭端幼。是因?yàn)槟惆l(fā)送的內(nèi)容很有名幸斥,因此Play可以為你計(jì)算內(nèi)容的長(zhǎng)度并生產(chǎn)相應(yīng)的頭。

注意:對(duì)于基于文本的內(nèi)容俊庇,這不像看起來那樣簡(jiǎn)單狮暑,由于Content-Length頭必須用根據(jù)把字符轉(zhuǎn)換為字節(jié)的編碼計(jì)算。

為了可以正確的計(jì)算Content-Length頭辉饱,Play必須解析整個(gè)應(yīng)答數(shù)據(jù)并把它的內(nèi)容加載到內(nèi)存搬男。

文件服務(wù)

如果對(duì)于簡(jiǎn)單內(nèi)容來說,可以把整個(gè)內(nèi)容加載進(jìn)內(nèi)容彭沼,那么對(duì)于大數(shù)據(jù)集怎么辦呢缔逛?比如我們想給客戶端發(fā)送一個(gè)大文件。

Play提供了易于使用的助手來提供本地文件服務(wù)這樣的普通任務(wù):

public Result index() {
return ok(new java.io.File("/tmp/fileToServe.pdf"));
}

此外,這個(gè)助手也會(huì)根據(jù)文件名計(jì)算 Content-Type頭褐奴。并且他也添加Content-Disposition頭指定Web瀏覽器應(yīng)該怎樣處理這個(gè)應(yīng)答按脚。默認(rèn)是使用Content-Disposition: attachment; filename=fileToServe.pdf.讓W(xué)eb瀏覽器下載這個(gè)文件。

分塊應(yīng)答

現(xiàn)在敦冬,流文件內(nèi)容的處理還行辅搬,由于我們?cè)诹髦翱梢杂?jì)算內(nèi)容長(zhǎng)度。但是動(dòng)態(tài)計(jì)算沒有可用的內(nèi)容長(zhǎng)度的內(nèi)容會(huì)如何脖旱?

對(duì)于這種類型的應(yīng)答堪遂,我們不得不使用分塊傳輸編碼

分塊傳輸編碼是HTTP 1.1版在Web服務(wù)器的一系列塊的服務(wù)內(nèi)容的數(shù)據(jù)傳輸機(jī)制萌庆。這使用了Transfer-Encoding HTTP 應(yīng)答頭替代 Content-Length頭溶褪,該協(xié)議將需要另外的需求。由于不使用 Content-Length 頭踊兜,服務(wù)器在開始傳送應(yīng)答到客戶端(通常是Web瀏覽器)之前不需要知道內(nèi)容的長(zhǎng)度竿滨。 Web服務(wù)器可以在知道內(nèi)容的所有長(zhǎng)度之前開始動(dòng)態(tài)的生成傳送應(yīng)答內(nèi)容佳恬。

每一個(gè)塊的大小都是在塊本身發(fā)送之前發(fā)送捏境,因此當(dāng)客戶端完成對(duì)塊數(shù)據(jù)的接受時(shí)可以告知服務(wù)端,數(shù)據(jù)傳輸是由最后一塊長(zhǎng)度是0的塊終止毁葱。
https://en.wikipedia.org/wiki/Chunked_transfer_encoding

好處是我們可以實(shí)時(shí)提供數(shù)據(jù)垫言,意味著我們按照它們的接受能力盡可能快的發(fā)送數(shù)據(jù)塊。缺點(diǎn)是由于Web瀏覽器不知道內(nèi)容的長(zhǎng)度倾剿,因此就不能正確的顯示下載進(jìn)度條。

比如,我們有一個(gè)服務(wù)器截珍,這個(gè)服務(wù)器提供了一個(gè)計(jì)算一些數(shù)據(jù)的動(dòng)態(tài)InputStream 坎拐。我們可以讓Paly直接用分塊相應(yīng)把這個(gè)內(nèi)容轉(zhuǎn)為流:

public Result index() {
InputStream is = getDynamicStreamSomewhere();
return ok(is);
}

你也可以設(shè)置你自己的分塊響應(yīng)構(gòu)建器:

public Result index() {
// Prepare a chunked text stream
Source<ByteString, ?> source = Source.<ByteString>actorRef(256, OverflowStrategy.dropNew())
.mapMaterializedValue(sourceActor -> {
sourceActor.tell(ByteString.fromString("kiki"), null);
sourceActor.tell(ByteString.fromString("foo"), null);
sourceActor.tell(ByteString.fromString("bar"), null);
sourceActor.tell(new Status.Success(NotUsed.getInstance()), null);
return null;
});
// Serves this stream with 200 OK
return ok().chunked(source);
}

Source.actorRef 方法創(chuàng)建一個(gè)實(shí)現(xiàn)了Akka Streams Source 的ActorRef。然后你可以通過發(fā)送信息到Actor的方式發(fā)布內(nèi)容到流芹缔。另一種可選的反射是創(chuàng)建一個(gè)ActorPublisher 的Actor并使用Stream.actorPublisher創(chuàng)建它坯癣。
我們可以檢查服務(wù)器發(fā)送的HTTP響應(yīng):

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked

4
kiki
3
foo
3
bar
0

我們獲得了三個(gè)塊和一個(gè)最終關(guān)閉響應(yīng)的空塊。
關(guān)于更多使用 Akka Streams的信息最欠,你可以參考Akka Streams文檔.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末示罗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子芝硬,更是在濱河造成了極大的恐慌蚜点,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拌阴,死亡現(xiàn)場(chǎng)離奇詭異绍绘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門陪拘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來实辑,“玉大人,你說我怎么就攤上這事藻丢〖羟耍” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵悠反,是天一觀的道長(zhǎng)残黑。 經(jīng)常有香客問我,道長(zhǎng)斋否,這世上最難降的妖魔是什么梨水? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮茵臭,結(jié)果婚禮上疫诽,老公的妹妹穿的比我還像新娘。我一直安慰自己旦委,他們只是感情好奇徒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缨硝,像睡著了一般摩钙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上查辩,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天胖笛,我揣著相機(jī)與錄音,去河邊找鬼宜岛。 笑死长踊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的萍倡。 我是一名探鬼主播身弊,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼遣铝!你這毒婦竟也來了佑刷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤酿炸,失蹤者是張志新(化名)和其女友劉穎瘫絮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體填硕,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡麦萤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年鹿鳖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壮莹。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡翅帜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出命满,到底是詐尸還是另有隱情涝滴,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布胶台,位于F島的核電站歼疮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏诈唬。R本人自食惡果不足惜韩脏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铸磅。 院中可真熱鬧赡矢,春花似錦、人聲如沸阅仔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)霎槐。三九已至送浊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丘跌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工唁桩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闭树,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓荒澡,卻偏偏與公主長(zhǎng)得像报辱,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子单山,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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

  • 本文整理自MIN飛翔博客 [1] 1. 概念 協(xié)議是指計(jì)算機(jī)通信網(wǎng)絡(luò)中兩臺(tái)計(jì)算機(jī)之間進(jìn)行通信所必須共同遵守的規(guī)定或...
    HoyaWhite閱讀 2,674評(píng)論 2 20
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理碍现,服務(wù)發(fā)現(xiàn),斷路器米奸,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • 一昼接、概念(載錄于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434閱讀 8,359評(píng)論 6 152
  • 深入淺出HTTP協(xié)議(WEB開發(fā)和面試必備) 1.基礎(chǔ)概念篇 a.簡(jiǎn)介 HTTP是Hyper Text Trans...
    半世韶華憶闌珊閱讀 1,221評(píng)論 0 7
  • Http協(xié)議詳解 標(biāo)簽(空格分隔): Linux 聲明:本片文章非原創(chuàng),內(nèi)容來源于博客園作者M(jìn)IN飛翔的HTTP協(xié)...
    Sivin閱讀 5,224評(píng)論 3 82