SwiftUI中发起HTTP请求时遭遇「Unsupported URL」错误
我在SwiftUI中开发了一款应用,尝试通过URLSession向外部服务器发起HTTP请求以获取JSON数据,但始终遭遇「Unsupported URL」错误。我已反复检查URL格式,确认其无误。
我的代码示例如下:
struct GroupsResponse: Decodable { let results: [Groups] } struct Groups: Decodable { let Id: Int let Descriere: String } private func fetchGroupsFromAPI() async throws -> [Groups] { let url = URL(string: "http://orar.usarb.md/api/access/getGroups")! var request = URLRequest(url: url) request.httpMethod = "POST" let (data, _) = try await URLSession.shared.data(for: request) let decoded = try JSONDecoder().decode(GroupsResponse.self, from: data) print(decoded) return decoded.results } private func button(_ title: String, color: Color) -> some View { Button(action: { Task { do { let movies = try await fetchGroupsFromAPI() print(movies) } catch { print(error) } } }) { Text(title) .frame(height: 40) .frame(maxWidth: .infinity) .background(color.opacity(0.5)) .foregroundColor(.black) } } }
触发请求时得到的错误信息为:
Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSLocalizedDescription=unsupported URL, NSErrorFailingURLStringKey=/api/access/getGroups, NSErrorFailingURLKey=/api/access/getGroups, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <39D779DF-E734-4D65-8722-23F3843FB2D9>.<3>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <39D779DF-E734-4D65-8722-23F3843FB2D9>.<3>, NSUnderlyingError=0x600000c68390 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}}
根据接口文档要求,该请求需使用POST而非GET方法。我已修改Info.plist文件、重建项目并调整代码结构,但问题仍未解决。请问我遗漏了什么?该如何修复此错误?
1. 排查服务器重定向问题
从错误日志看,最终请求的URL缺失了域名,变成了/api/access/getGroups,大概率是服务器返回了相对路径的重定向地址,URLSession无法自动解析相对URL导致报错。可以先用curl命令测试接口行为:
curl -X POST http://orar.usarb.md/api/access/getGroups -v
如果确认是重定向问题,需要手动处理:创建URLSession时关闭自动重定向,然后在响应中手动拼接完整URL:
let config = URLSessionConfiguration.default config.httpShouldHandleRedirects = false let session = URLSession(configuration: config) // 发起请求后,检查响应状态码是否为3xx,手动拼接重定向URL let (data, response) = try await session.data(for: request) if let httpResponse = response as? HTTPURLResponse, (300...399).contains(httpResponse.statusCode), let redirectUrlString = httpResponse.allHeaderFields["Location"] as? String { guard let redirectUrl = URL(string: redirectUrlString, relativeTo: url) else { throw NSError(domain: "RedirectError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的重定向地址"]) } // 使用redirectUrl重新发起请求 let redirectRequest = URLRequest(url: redirectUrl) let (finalData, _) = try await session.data(for: redirectRequest) // 解析finalData }
2. 避免URL强制解包
不要用!强制解包URL(string:),添加校验逻辑提前发现无效URL:
guard let url = URL(string: "http://orar.usarb.md/api/access/getGroups") else { throw NSError(domain: "InvalidURL", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求地址"]) }
3. 确认ATS配置正确
再次检查Info.plist中的App Transport Security配置,确保允许该域名的HTTP请求:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>usarb.md</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict> </dict>
4. 补充POST请求必要参数
部分POST接口要求必须携带请求体(即使是空的),尝试添加请求体和Content-Type头:
request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = "{}".data(using: .utf8)
5. 排除URLSession配置干扰
如果项目中自定义了URLSession配置,先改用默认的URLSession.shared测试,排除自定义配置(如代理、缓存策略)带来的问题。
内容的提问来源于stack exchange,提问作者Pogor Cristian

