如何在Vapor中处理客户端取消的请求?
Vapor服务器捕获客户端取消请求的实现方法
Vapor提供了Request.onCancel方法来监听客户端取消请求的事件(比如前端通过AbortController.abort()触发的请求终止),结合可取消的任务机制,就能在服务器端终止耗时计算操作。以下是具体实现方案:
核心思路
- 通过
req.onCancel注册回调,当客户端取消请求时触发任务终止逻辑 - 耗时计算任务需支持取消:优先使用Swift的
Task(天然支持取消),或自定义取消标记
异步计算场景(推荐)
利用Swift的Task封装耗时计算,在计算过程中定期检查取消状态,代码示例:
import Vapor // 定义请求和响应结构体 struct CalculationInput: Content { let text: String } struct CalculationResponse: Content { let result: String } // 注册路由 app.post("api", "dosomething") { req async throws -> CalculationResponse in // 解析前端传入的参数 let input = try req.content.decode(CalculationInput.self) // 创建可取消的Task执行耗时计算 let calculationTask = Task { () -> String in for step in 0..<1000 { // 检查任务是否被取消,若取消则抛出CancellationError try Task.checkCancellation() // 模拟耗时计算步骤 try? await Task.sleep(nanoseconds: 1_000_000_000) print("执行计算步骤:\(step)") } return "基于'\(input.text)'的计算结果" } // 注册取消回调:前端取消请求时,终止计算Task req.onCancel { calculationTask.cancel() } // 等待计算结果,处理取消情况 do { let result = try await calculationTask.value return CalculationResponse(result: result) } catch is CancellationError { // 返回客户端取消的自定义状态码(499为Nginx定义的客户端关闭请求状态码,Vapor支持) throw Abort(.custom(code: 499, reasonPhrase: "Client Cancelled Request")) } }
同步计算场景
如果你的计算是同步阻塞操作,可通过原子变量维护取消标记,代码示例:
import Vapor import Atomics app.post("api", "dosomething") { req throws -> CalculationResponse in let input = try req.content.decode(CalculationInput.self) // 原子变量存储取消状态,保证线程安全 let isCancelled = ManagedAtomic<Bool>(false) // 注册取消回调,标记任务需要终止 req.onCancel { isCancelled.store(true, ordering: .relaxed) } // 执行同步耗时计算 for step in 0..<1000 { if isCancelled.load(ordering: .relaxed) { throw Abort(.custom(code: 499, reasonPhrase: "Client Cancelled Request")) } // 模拟同步耗时操作 Thread.sleep(forTimeInterval: 1) print("执行计算步骤:\(step)") } return CalculationResponse(result: "基于'\(input.text)'的计算结果") }
关键说明
req.onCancel:当客户端断开连接或主动取消请求时,注册的闭包会被调用,此时可触发任务终止逻辑Task.checkCancellation():在异步任务中定期调用该方法,可检测任务是否被取消,若已取消则抛出CancellationError- 状态码选择:返回499状态码能明确告知客户端请求已被服务器感知并终止,也可根据需求使用408(请求超时)等标准状态码
内容的提问来源于stack exchange,提问作者silberz
相关产品推荐
相关产品推荐

