Vapor搭建OpenAI Chat API流式代理遇实时传输问题求助
Vapor代理OpenAI流式Chat API实时转发解决方案
你当前的代码直接返回ClientResponse,Vapor默认会把OpenAI返回的整个流式响应读完之后,才一次性发送给iOS客户端,这就是为什么iOS端要等很久才收到数据、且速度极快的原因。要实现实时转发,必须手动处理响应流,每收到一块数据就立刻推送给客户端。
下面是修改后的代码,核心是通过AsyncThrowingStream逐块读取OpenAI的响应数据,并实时转发给iOS客户端:
app.post("chat") { req async throws -> Response in // 读取环境变量中的API密钥 guard let targetAPIKey = ProcessInfo.processInfo.environment["TARGET_API_KEY"] else { throw Abort(.internalServerError, reason: "API密钥未配置") } let targetAPIURL = URI(string: "https://api.openai.com/v1/chat/completions") // 解码iOS端发来的请求体 let requestBody = try req.content.decode(ChatQuery.self) // 构建向OpenAI发送的请求头 var downstreamHeaders = HTTPHeaders() downstreamHeaders.add(name: .authorization, value: "Bearer \(targetAPIKey)") downstreamHeaders.add(name: .contentType, value: "application/json") downstreamHeaders.add(name: .accept, value: "text/event-stream") downstreamHeaders.add(name: "Cache-Control", value: "no-cache") downstreamHeaders.add(name: "Connection", value: "keep-alive") // 发送请求到OpenAI并获取响应流 let openAIResponse = try await req.client.post(targetAPIURL, headers: downstreamHeaders) { downstreamReq in try downstreamReq.content.encode(requestBody) } // 验证OpenAI响应状态 guard openAIResponse.status.isSuccessful else { throw Abort(.badGateway, reason: "OpenAI API请求失败: \(openAIResponse.status)") } // 创建流式响应,实时转发数据 let stream = AsyncThrowingStream(HTTPChunk.self) { continuation in Task { do { // 逐块读取OpenAI的响应数据 for try await chunk in openAIResponse.body { continuation.yield(chunk) } continuation.finish() } catch { continuation.finish(throwing: error) } } } // 构建返回给iOS客户端的响应 var responseHeaders = HTTPHeaders() responseHeaders.add(name: .contentType, value: "text/event-stream") responseHeaders.add(name: "Cache-Control", value: "no-cache") responseHeaders.add(name: "Connection", value: "keep-alive") responseHeaders.add(name: "Transfer-Encoding", value: "chunked") return Response( status: .ok, headers: responseHeaders, body: .init(stream: stream) ) }
关键改动说明
- 使用
async throws路由处理函数替代EventLoopFuture,更简洁地处理异步流逻辑 - 手动创建
AsyncThrowingStream,逐块读取OpenAI返回的HTTPChunk,每读到一块就立刻推送给客户端 - 添加必要的响应头:
Cache-Control: no-cache避免客户端缓存数据,Transfer-Encoding: chunked告知客户端采用分块传输,Connection: keep-alive维持长连接保障流式传输 - 补充错误处理逻辑,包括API密钥未配置、OpenAI响应失败的情况
注意事项
- 确保你的
ChatQuery结构体正确编码,必须包含stream: true字段才能触发OpenAI的流式返回 - 该代码适配Vapor 4及以上版本,旧版本需调整异步处理逻辑
- 部署服务器时,需确保中间代理(如Nginx)支持长连接,避免截断流式响应
内容的提问来源于stack exchange,提问作者DavidEC
相关产品推荐
相关产品推荐

