Swift基于URLComponents校验可访问远程服务器的有效Web地址方案咨询
结论
你当前的实现无法完全覆盖「检测可访问万维网远程服务器的有效Web地址」的需求,存在多处逻辑遗漏,可优化空间如下:
现有实现的问题
- 缺少
host校验:类似https:///foo这类无主机地址的字符串,URLComponents可以正常解析,scheme也符合要求,但没有主机地址根本无法访问远程服务器,你的现有代码会将这类错误地址判定为有效。 - scheme校验区分大小写:URL的scheme本身是不区分大小写的,
HTTPS://example.com是合法地址,但你的代码会因为scheme值为大写HTTPS判定为无效。 - 存在隐式依赖:代码中用到的
WebSchemes枚举没有在扩展中定义,一旦枚举的rawValue不符合预期,整个校验逻辑会直接失效。 - 不兼容常规无scheme输入:如果用户输入的是
www.example.com这类省略了scheme的常用Web地址,你的代码会直接返回nil,不符合普通用户的输入习惯(如果你的业务场景要求必须显式带scheme可忽略此问题)。
可优化点
- 增加
host非空校验,直接过滤无主机地址 - scheme校验改为大小写不敏感匹配,避免误杀合法地址
- 可增加无scheme场景的兜底逻辑,自动补全
https://后二次解析,兼容普通用户输入 - 如果需要严格排除本地/内网地址,可额外过滤
localhost、回环IP、内网保留段IP - 注意:格式校验只能保证字符串符合RFC3986标准的HTTP/HTTPS URL规则,无法保证地址实际可访问,如需确认服务可达,必须额外发送网络请求(如HEAD请求)验证连通性
优化后参考代码
import Foundation extension String { /// 返回合法的HTTP/HTTPS远程服务器URL,不符合则返回nil var validWebURL: URL? { // 优先解析原字符串 if let url = parseAsWebURL(self) { return url } // 兜底:尝试加https://前缀后二次解析,适配无scheme输入 let prefixedString = "https://" + self return parseAsWebURL(prefixedString) } private func parseAsWebURL(_ string: String) -> URL? { guard let components = URLComponents(string: string), let scheme = components.scheme?.lowercased(), (scheme == "http" || scheme == "https"), components.host != nil, // 必须有主机地址 let url = components.url else { return nil } // 可选:过滤本地地址,不需要可以删掉 guard !["localhost", "127.0.0.1", "::1"].contains(components.host?.lowercased() ?? "") else { return nil } return url } }
内容的提问来源于stack exchange,提问作者Adam Dahan
相关产品推荐
相关产品推荐

