Looking through the curl code transfer.c it seems that the program is able to repackage request data (from curl to the server) using the chunking protocol, where each chunk of data is prefixed by the length of the chunk in ascii hexadecimal, and suffixed by \r\n
.
It seems the way to make it use this in a streaming way, after connecting to the server is with -T -
. Consider this example:
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/...
This script sends 5 blocks of data, each beginning with the date and padded to 512 bytes by dd
, to a pipe, where strace
runs curl -T -
to read the pipe.
In the terminal we can see
== 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
which shows the connection, and the headers sent. In particular curl
has not provided a Content-length:
header, but an Expect:
header to which the server (apache) has replied Continue
. Immediately after comes the first 512 bytes (200 in hex) of data:
=> 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)
Looking in the strace
output file we see each timestamped read
from the pipe, and sendto
write to the connection:
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
As you can see they are spaced out by 1 second, showing that the data is being sent as it is being received. You must just have at least 512 bytes to send, as the data is being read by fread()
.
curl
consider it enough to send? – Jeff Schaller Sep 13 '18 at 16:50stdout
ofmyDataGeneratingApp
they should be sent "across the wire" to the server. The request completes when the stdout completes... – Ramón J Romero y Vigil Sep 13 '18 at 16:51curl --no-buffer
(-N
)? – meuh Sep 13 '18 at 19:12setbuf(3)
) while network transfers are block-buffered by default. you'd have to try to disable that buffering (in bothmyDataGeneratingApp
and probably alsocurl
) or to write something very custom to feed the web service – thrig Sep 13 '18 at 21:19