Skip to content

支持了按 chunk 返回的 HTTP 客户端 #1718

Open

Description

@Barenboim

这个功能非常适合于访问大模型服务,之后我们会给出一个和deepseek对话的示例出来。
接口头文件:
https://github.com/sogou/workflow/blob/master/src/client/WFHttpChunkedClient.h

其中WFHttpChunkedClient是一个静态类,用于创建基于 chunk 回调的 HTTP 任务,类型为WFHttpChunkedTask。
示例:

#include "workflow/WFHttpChunkedClient.h"
#include "workflow/WFFacilities.h"
#include <stdio.h>

void extract(WFHttpChunkedTask *task)
{
    protocol::HttpResponse *resp = task->get_resp();   // 可以获得resp的header等信息。
    protocol::HttpMessageChunk *chunk = task->get_chunk();
    const void *chunk_data;
    size_t chunk_size;

    chunk->get_chunk_data(&chunk_data, &chunk_size);    // extract函数里,get_chunk_data必然成功
    printf("Chunk size = %zu. Chunk data:\n", chunk_size);
    fwrite(chunk_data, chunk_size, 1, stdout);
    printf("\n");
}

WFFacilities::WaitGroup wg(1);

void callback(WFHttpChunkedTask *task)
{
    protocol::HttpResponse *resp = task->get_resp();
    printf("state = %d, error = %d\n", task->get_state(), task->get_error());
    if (task->get_state() == WFT_STATE_SUCCESS)
        printf("%s %s %s", resp->get_http_version(), resp->get_status_code(), resp->get_reason_phrase());

    wg.done();
}

int main()
{
    WFHttpChunkedTask *task = WFHttpChunkedClient::create_chunked_task("http://github.com/", 3, extract, callback);
    task->start();
    wg.wait();
}

这个client的特色是支持重定向,create_chunked_task函数的第二个参数就是重定向最大次数。示例中指定的HTTP URL会重定向到 HTTPS。

另外,如果返回 HTTP 回复不是chunked编码,则extract函数不会被调用,用户可以在callback里获得完整的 HTTP 消息体。相当于退化为普通的 HTTP 任务。

WFHttpChunkedTask类代理了WFHttpTask的大多数接口,简单参考头文件即可了解用法。

extract函数的调用位置是在网络io线程,串行调用。用户不应该在extract函数内阻塞或调用执行大量CPU计算。可以通过HttpMessageChunk类的move_chunk_data(),把数据无拷贝的移动走以便后续处理(需自行调用free释放内存),也可以std::move()移动整个chunk对象,例如:

void extract(WFHttpChunkedTask *task)
{
    protocol::HttpMessageChunk *chunk = task->get_chunk();
    auto *c = new protocol::HttpMessageChunk(std::move(*chunk));
    ...
}

这个与我们大多数网络任务里,移动resp数据的做法是一致的。

Activity

  1. povs2012 commented on Dec 25, 2025

    @povs2012

    能不能给TLVMessage也实现类似的机制,方便自定义协议持续接收响应呢

  2. Barenboim commented on Dec 25, 2025

    @Barenboim
    ContributorAuthor

    能不能给TLVMessage也实现类似的机制,方便自定义协议持续接收响应呢

    可以重新发个issue,描述清楚需求。

  3. MirrorYuChen commented on Apr 19, 2026

    @MirrorYuChen

    整了个Chatbot项目练手,不知道用的对不对,有时间大佬帮忙看一下:https://github.com/MirrorYuChen/WFChatbot

  4. Barenboim commented on Apr 22, 2026

    @Barenboim
    ContributorAuthor

    整了个Chatbot项目练手,不知道用的对不对,有时间大佬帮忙看一下:https://github.com/MirrorYuChen/WFChatbot

    感谢支持。SSE那里,由于我们框架内没有实现push的异步,遇到写buffer满(出现EAGAIN错误)可以考虑加个Timer重试。这个是框架的问题。

  5. MirrorYuChen commented on Apr 23, 2026

    @MirrorYuChen

    好的,我研究一下

  6. MirrorYuChen commented on Apr 23, 2026

    @MirrorYuChen

    参考wfrest实现了一下这个逻辑,麻烦大佬帮忙看一下实现的对不对,MirrorYuChen/WFChatbot@d15fb94

  7. Barenboim commented on Apr 23, 2026

    @Barenboim
    ContributorAuthor

    参考wfrest实现了一下这个逻辑,麻烦大佬帮忙看一下实现的对不对,MirrorYuChen/WFChatbot@d15fb94

    wfrest里那个实现其实是有问题的…… 例如需要push多次,某一次buffer满需要定时重试,为了让push的数据保序,下一次push应该在上一次的retry成功之后才能执行。需要拉个链表。不过这些情况基本上都遇不到。

  8. MirrorYuChen commented on Apr 23, 2026

    @MirrorYuChen

    好的,多谢大佬指导

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions