Pipe

使用 Unix 管道將數據流式傳輸到 REST 服務

  • September 14, 2018

根據對另一個問題的回答,我正在使用 curl 將stdout一個程序的流式傳輸作為POST請求的實體:

myDataGeneratingApp \
| curl -H "Content-Type: application/json" -H "Transfer-Encoding: chunked" -X POST -d @- http://localhost:12000

EOF不幸的是,curl在開始發送數據之前正在等待標準輸出。我知道這一點是因為我可以獨立執行我的應用程序,並且數據會立即輸出到控制台,但是當我通過管道進行 curl 時,在服務開始接收數據之前會有很大的延遲。

當數據從應用程序的標準中可用時,如何使用 curl 立即流式傳輸數據?如果在 curl 中不可能,那麼是否有另一種解決方案(例如 wget)?

查看 curl 程式碼transfer.c似乎該程序能夠使用分塊協議重新打包請求數據(從 curl 到伺服器),其中每個數據塊都以 ascii 十六進制的塊長度為前綴,並以由\r\n.

在連接到伺服器後,似乎讓它以流的方式使用它的方法是使用-T -. 考慮這個例子:

for i in $(seq 5)
do date
  sleep 1
done | 
dd conv=block cbs=512 |
strace -t -e sendto,read -o /tmp/e \
curl --trace-ascii - \
-H "Transfer-Encoding: chunked" \
-H "Content-Type: application/json" \
-X POST -T -  http://localhost/...

此腳本將 5 個數據塊發送到一個管道,每個數據塊都以日期開頭並由 填充到 512 個字節dd,在該管道中strace執行curl -T -以讀取管道。在終端中我們可以看到

== Info: Connected to localhost (::1) port 80 (#0)
=> Send header, 169 bytes (0xa9)
0000: POST /... HTTP/1.1
001e: Host: localhost
002f: User-Agent: curl/7.47.1
0048: Accept: */*
0055: Transfer-Encoding: chunked
0071: Content-Type: application/json
0091: Expect: 100-continue
00a7: 
<= Recv header, 23 bytes (0x17)
0000: HTTP/1.1 100 Continue

它顯示了連接和發送的標頭。特別是curl沒有提供Content-length:標頭,而是Expect:伺服器(apache)已回复的標頭Continue。緊隨其後的是數據的前 512 個字節(200 十六進制):

=> Send data, 519 bytes (0x207)
0000: 200
0005: Fri Sep 14 15:58:15 CEST 2018                                   
0045:                                                                 
0085:                                                                 
00c5:                                                                 
0105:                                                                 
0145:                                                                 
0185:                                                                 
01c5:                                                                 
=> Send data, 519 bytes (0x207)

查看strace輸出文件,我們看到管道中的每個時間戳read,並sendto寫入連接:

16:00:00 read(0, "Fri Sep 14 16:00:00 CEST 2018   "..., 16372) = 512
16:00:00 sendto(3, "200\r\nFri Sep 14 16:00:00 CEST 20"..., 519, ...) = 519
16:00:00 read(0, "Fri Sep 14 16:00:01 CEST 2018   "..., 16372) = 512
16:00:01 sendto(3, "200\r\nFri Sep 14 16:00:01 CEST 20"..., 519, ...) = 519
16:00:01 read(0, "Fri Sep 14 16:00:02 CEST 2018   "..., 16372) = 512
16:00:02 sendto(3, "200\r\nFri Sep 14 16:00:02 CEST 20"..., 519, ...) = 519
16:00:02 read(0, "Fri Sep 14 16:00:03 CEST 2018   "..., 16372) = 512
16:00:03 sendto(3, "200\r\nFri Sep 14 16:00:03 CEST 20"..., 519, ...) = 519
16:00:03 read(0, "Fri Sep 14 16:00:04 CEST 2018   "..., 16372) = 512
16:00:04 sendto(3, "200\r\nFri Sep 14 16:00:04 CEST 20"..., 519, ...) = 519
16:00:04 read(0, "", 16372)             = 0
16:00:05 sendto(3, "0\r\n\r\n", 5, ...) = 5

如您所見,它們間隔 1 秒,表明數據在接收時正在發送。您必須至少有 512 個字節要發送,因為數據正在被fread().

引用自:https://unix.stackexchange.com/questions/468813