Skip to content

[Feature request]: [Feature request]: 在 IHttpService 接口中新增 IAsyncEnumerable 流式方法 #672

Description

@SwiftFloatFlow

相关问题

插件开发中流式处理的现代化改造

描述你希望的解决方案

描述你希望的解决方案
在 IHttpService 接口中新增一个支持 IAsyncEnumerable 的流式 POST 方法:

/// <summary>
/// 流式Post请求(IAsyncEnumerable模式)
/// </summary>
/// <param name="url">请求URL</param>
/// <param name="content">请求体</param>
/// <param name="options">请求选项</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>异步流,每项是一行SSE数据</returns>
IAsyncEnumerable<string> StreamPostAsyncEnumerable(
    string url,
    object content,
    Options? options = null,
    CancellationToken cancellationToken = default);

HttpService 实现示例:

public async IAsyncEnumerable<string> StreamPostAsyncEnumerable(
    string url,
    object content,
    Options? options = null,
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    using var client = _httpClientFactory.CreateClient(Constant.HttpClientName);
    // ... 配置 ...
    
    await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
    using var reader = new StreamReader(stream);
    
    string? line;
    while (!cancellationToken.IsCancellationRequested && (line = await reader.ReadLineAsync(cancellationToken)) != null)
    {
        if (!string.IsNullOrEmpty(line))
        {
            yield return line;
        }
    }
}

优点:
纯增量添加,不影响现有接口
向后兼容,旧插件无需修改
新插件可选择更现代的 IAsyncEnumerable 模式
便于在插件中实现 await foreach 遍历

描述你所考虑的替代方案

  1. 保持现有回调模式:继续使用 Action 回调,但这种方式在异步上下文中不够直观,且难以实现早期取消和异常处理。
  2. 自定义 HttpService 封装:在插件内部自行实现 HttpClient 流式处理,但会重复 HttpService 的配置和错误处理逻辑,且无法复用主程序的 HttpClientFactory 管理。
  3. 修改现有 StreamPostAsync 签名:破坏性太大,会强制所有插件修改。

选择 IAsyncEnumerable 的原因:

  • 官方推荐的流式处理方式
  • 天然支持 CancellationToken 和异常处理
  • 与现有方法共存,可选使用
  • 代码更简洁易读

我确认已查询历史issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions