curl -C, --continue-at 在管道标准输出时工作吗?

Does curl -C, --continue-at work when piping standard out?

来自curl's manpage

Use "-C -" to tell curl to automatically find out where/how to resume the transfer. It then uses the given output/input files to figure that out.

所以如果使用

curl \
    --retry 9999 \
    --continue-at - \
    https://mydomain.test/some.file.bin \
| target-program

并且下载中途失败(一次),并且服务器支持范围请求,将通过范围请求进行 curl 重试,因此 target-program 收到 some.file.bin 的完整字节作为它的输入?

根据测试,curl 将不会使用范围请求重试。

我编写了一个损坏的 HTTP 服务器,要求客户端使用 range-request 重试以获得完整响应。使用 wget

wget -O - http://127.0.0.1:8888/ | less

得到完整的回复

abcdefghijklmnopqrstuvwxyz

我可以在服务器端看到 headers.

请求中带有 'Range': 'bytes=24-' 的请求

但是,使用 curl

curl --retry 9999 --continue-at - http://127.0.0.1:8888/ | less

结果只有不完整的响应,服务器日志中没有范围请求。

abcdefghijklmnopqrstuvwx

使用的Python服务器

import asyncio
import re
from aiohttp import web

async def main():
    data = b'abcdefghijklmnopqrstuvwxyz'

    async def handle(request):
        print(request.headers)

        # A too-short response with an exception that will close the
        # connection, so the client should retry
        if 'Range' not in request.headers:
            start = 0
            end = len(data) - 2
            data_to_send = data[start:end]
            headers = {
                'Content-Length': str(len(data)),
                'Accept-Ranges': 'bytes',
            }
            print('Sending headers', headers)
            print('Sending data', data_to_send)
            response = web.StreamResponse(
                headers=headers,
                status=200,
            )
            await response.prepare(request)
            await response.write(data_to_send)
            raise Exception()

        # Any range request
        match = re.match(r'^bytes=(?P<start>\d+)-(?P<end>\d+)?$', request.headers['Range'])
        start = int(match['start'])
        end = \
            int(match['end']) + 1 if match['end'] else \
            len(data)
        data_to_send = data[start:end + 1]
        headers = {
            'Content-Range': 'bytes {}-{}/{}'.format(start, end - 1, len(data)),
            'Content-Length': str(len(data_to_send)),
        }
        print('Sending headers', headers)
        print('Sending data', data_to_send)
        response = web.StreamResponse(
            headers=headers,
            status=206
        )
        await response.prepare(request)
        await response.write(data_to_send)
        await response.write_eof()
        return response

    app = web.Application()
    app.add_routes([web.get(r'/', handle)])

    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, '0.0.0.0', 8888)
    await site.start()
    await asyncio.Future()

asyncio.run(main())