URLSession重定向时willPerformHTTPRedirection未调用如何获取跳转地址
问题根因
你遇到的willPerformHTTPRedirection不触发的核心问题是:你使用了dataTask(with:completionHandler:)带闭包的便捷构造方法,这种情况下URLSession会优先走闭包回调逻辑,默认不会触发代理的重定向方法。系统会自动完成所有重定向流程,直到拿到最终响应后才会调用你传入的闭包,所以你在闭包中拿到的已经是重定向完成后的200响应,自然看不到307状态码和对应的Location头。
两种解决方案
方案1:完全走代理回调(适合需要自定义重定向逻辑的场景)
移除dataTask的completionHandler参数,完全通过代理方法接收请求回调,就能正常触发重定向代理:
// 原来的dataTask写法替换为无闭包版本 session?.dataTask(with: requestHeader).resume()
补充实现对应的代理方法即可:
extension ViewController: URLSessionTaskDelegate, URLSessionDataDelegate { // 重定向回调,可直接获取重定向地址 func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { print("重定向地址:\(request.url?.absoluteString ?? "")") // 传nil表示禁止继续重定向,传request表示允许继续重定向 completionHandler(nil) } // 接收响应头回调 func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) { if let httpRes = response as? HTTPURLResponse { print("状态码:\(httpRes.statusCode)") if let location = httpRes.value(forHTTPHeaderField: "Location") { print("Location头:\(location)") } } completionHandler(.allow) } // 接收返回数据 func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { // 处理响应数据 } // 请求完成回调 func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { // 处理请求完成逻辑 } }
方案2:禁用自动重定向(适合仅需要获取原始3xx响应的场景)
不需要修改现有请求写法,只需要在初始化URLSession时修改配置,禁止系统自动执行重定向,即可在原有的completionHandler中直接拿到307响应和Location头:
let config = URLSessionConfiguration.default // 设置允许的最大重定向次数为0,禁止所有自动重定向 config.httpMaximumRedirectsAllowed = 0 session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
修改后你原有闭包中的打印逻辑就能直接输出307状态码和对应的Location值。
内容的提问来源于stack exchange,提问作者thesuffering
相关产品推荐
相关产品推荐

