如何通过短链接获取完整URL?iOS端百度地图短链接解析方案
解析百度地图短链接获取完整URL(iOS实现)
嘿,这个需求我之前处理过类似的短链接解析场景,其实核心逻辑就是追踪HTTP重定向——百度的短链接本质是返回302跳转响应,浏览器会自动跟进跳转拿到最终URL,咱们在iOS里手动实现这个逻辑就搞定了。下面给你两种可行的Swift方案:
方案1:通过URLSession代理追踪重定向
这种方式适合需要监听每一步跳转的场景,能灵活控制跳转流程:
import UIKit class ShortLinkResolver: NSObject, URLSessionDataDelegate { func resolveBaiduShortLink(_ shortURL: URL, completion: @escaping (URL?) -> Void) { let sessionConfig = URLSessionConfiguration.default // 初始化带代理的URLSession let session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main) var request = URLRequest(url: shortURL) // 模拟移动端浏览器的User-Agent,避免被百度拦截 request.setValue("Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1", forHTTPHeaderField: "User-Agent") // 把回调闭包存在taskDescription里,方便代理方法调用 let task = session.dataTask(with: request) task.taskDescription = "\(completion)" task.resume() } // 监听重定向事件,拿到跳转后的目标URL func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { if let finalURL = request.url { // 拿到目标URL后停止继续跳转 completionHandler(nil) // 调用回调返回结果 if let completion = task.taskDescription as? ((URL?) -> Void) { completion(finalURL) } } else { // 如果还有后续跳转,继续跟进 completionHandler(request) } } // 请求完成的兜底处理(无重定向或出错时) func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { if let error = error { print("短链接解析失败:\(error.localizedDescription)") if let completion = task.taskDescription as? ((URL?) -> Void) { completion(nil) } return } // 如果没有重定向,返回原URL if let responseURL = task.response?.url { if let completion = task.taskDescription as? ((URL?) -> Void) { completion(responseURL) } } else { if let completion = task.taskDescription as? ((URL?) -> Void) { completion(nil) } } } } // 使用示例 let resolver = ShortLinkResolver() if let shortURL = URL(string: "https://j.map.baidu.com/YwUSO") { resolver.resolveBaiduShortLink(shortURL) { finalURL in guard let url = finalURL else { print("解析失败") return } print("拿到的完整URL:\(url)") // 这里可以处理你的业务逻辑,比如打开地图、存储URL等 } }
方案2:轻量HEAD请求获取Location头
如果不需要监听跳转过程,用HEAD请求只获取响应头会更高效,避免下载不必要的响应体:
import UIKit func resolveBaiduShortLinkLightweight(_ shortURL: URL, completion: @escaping (URL?) -> Void) { var request = URLRequest(url: shortURL) request.httpMethod = "HEAD" // 仅请求响应头,更轻量 // 同样需要设置浏览器UA request.setValue("Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1", forHTTPHeaderField: "User-Agent") let task = URLSession.shared.dataTask(with: request) { _, response, error in DispatchQueue.main.async { if let error = error { print("请求出错:\(error.localizedDescription)") completion(nil) return } // 检查是否是3xx重定向响应 guard let httpResponse = response as? HTTPURLResponse, (300...399).contains(httpResponse.statusCode), let locationString = httpResponse.allHeaderFields["Location"] as? String, let finalURL = URL(string: locationString) else { // 无重定向或解析失败时返回原URL completion(shortURL) return } completion(finalURL) } } task.resume() } // 使用示例 if let shortURL = URL(string: "https://j.map.baidu.com/YwUSO") { resolveBaiduShortLinkLightweight(shortURL) { url in print("最终完整URL:\(url ?? shortURL)") } }
关键注意事项
- User-Agent必须设置:百度短链接服务会拦截非浏览器标识的请求,所以一定要模拟移动端浏览器的UA,否则可能返回403或者不触发跳转。
- 处理多次重定向:如果遇到短链接嵌套跳转的情况,可以在方案1里循环跟进,或者在方案2里递归调用解析方法,直到拿到非3xx响应的URL。
- 网络权限:确保你的App已经在
Info.plist中配置了网络权限(NSAppTransportSecurity不需要额外配置,因为百度短链接是HTTPS协议)。 - 错误处理:一定要处理网络异常、短链接无效、无跳转头等边缘情况,避免崩溃或逻辑异常。
内容的提问来源于stack exchange,提问作者damu
相关产品推荐
相关产品推荐

