You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

URLSession默认缓存策略下未捕获304状态码问题咨询

获取URLSession真实的304状态码

默认情况下,URLSession的completion handler会自动封装304响应逻辑——把服务器返回的304状态码替换成200,同时直接返回本地缓存的数据,这是Foundation框架为简化开发者流程做的封装。如果要拿到真实的304状态码,你需要切换到代理模式处理请求,而非使用便捷的completion handler方法。

具体实现步骤如下:

  1. 实现URLSessionDataDelegate协议
    你需要实现协议里的几个关键方法,用来捕获原始响应、处理数据接收以及请求完成后的逻辑。

  2. 创建带代理的URLSession实例
    保持默认的useProtocolCachePolicy(这也是URLSessionConfiguration的默认策略,可省略显式设置),初始化绑定代理的Session:

    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
    
  3. 在代理方法中捕获真实状态码
    在didReceiveResponse方法里,你能直接拿到服务器返回的原始HTTP响应,包括304状态码:

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
        guard let httpResponse = response as? HTTPURLResponse else {
            completionHandler(.allow)
            return
        }
        
        // 这里就能拿到真实的状态码了
        let realStatusCode = httpResponse.statusCode
        print("服务器返回的真实状态码: \(realStatusCode)")
        
        if realStatusCode == 304 {
            // 304表示缓存有效,需要自行从URLCache读取缓存数据
            if let cachedResponse = session.configuration.urlCache?.cachedResponse(for: dataTask.currentRequest!) {
                // 处理缓存的cachedResponse.data
                print("使用本地缓存数据")
            }
            // 304没有响应体,直接取消数据接收即可
            completionHandler(.cancel)
        } else {
            // 其他状态码正常处理,允许接收响应数据
            completionHandler(.allow)
        }
    }
    
  4. 处理非304场景的数据接收
    实现didReceive data方法来收集正常响应的数据:

    var receivedData = Data()
    
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        receivedData.append(data)
    }
    
  5. 处理请求完成逻辑
    在didCompleteWithError方法里完成后续的结果处理:

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        if let error = error {
            print("请求出错: \(error.localizedDescription)")
            return
        }
        
        // 在这里处理receivedData(非304场景)或缓存的数据(304场景)
    }
    

关键提示

  • 代理模式下Foundation不会自动处理304到200的转换,你能完全掌控原始响应状态。
  • 收到304时服务器不会返回响应体,必须自行从URLCache读取对应的缓存内容。
  • URLSession会自动在有缓存的请求中添加Etag和If-None-Match头,无需手动处理。

内容的提问来源于stack exchange,提问作者Chamitha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:36:48