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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 00:45:04