url合法性需按rfc 3986分段校验:先验scheme(http/https/ftp等后跟://),再析出host(支持ipv4、ipv6[::1]或合规域名)、port(1–65535)、path(含%编码须双十六进制);仅正则粗筛会漏判非法用例。

URL字符串是否合法,不能只靠正则粗筛
单纯用 std::regex 匹配 ^https?:// 这类简单模式,会漏掉大量非法但能通过的输入,比如 http://..、https://@example.com、http:///path。C++ 标准库不提供 URL 解析器,必须依赖 RFC 3986 的语义规则做分段校验。
用 std::string_view 拆解 scheme、host、port、path 各段再分别验证
先检查是否有合法 scheme(仅限 http、https、ftp 等常见协议,且后跟 ://),再定位 host 起始与结束位置——注意 host 可能含 IPv4、IPv6(如 [::1])、或域名(需满足 DNS label 规则:不能以 - 开头/结尾,不能连续两个 -,每段 ≤63 字符)。port 若存在,必须是纯数字且在 1–65535 范围内。
- 用
find和rfind定位://、第一个/、@、:、[、],避免越界访问 - IPv6 host 必须被方括号包裹,且方括号必须成对出现;未包裹的冒号直接视为非法
-
path允许为空,但若存在,首字符为/并非强制(http://a.b/c合法,http://a.b也合法)
常见错误路径及对应检测点
这些输入常被误判为合法:
-
http://—— 缺少 host,应在://后至少有一个非/、非?、非#字符 -
https://[::1:2001]—— IPv6 地址格式错误,方括号内必须是合法 IPv6 字面量(可用inet_pton(AF_INET6, ...)辅助验证) -
ftp://user:pass@host:99999/path—— port 超出65535,应拒绝 -
http://-example.com—— host 的 DNS label 以-开头,违反 RFC
要不要用第三方库?liburl 或 cpp-netlib 太重,轻量方案更实用
如果项目已用 Boost,boost::urls(v1.79+)可直接 parse 并检查 result.error() == boost::urls::error_code();否则不建议引入完整网络库。一个折中做法是复用系统级工具逻辑:调用 getaddrinfo() 验证 host 是否可解析(仅适用于带 host 的 URL),但要注意它不校验 scheme 或 path。真正健壮的判断必须组合多层检查——scheme 格式 + host 结构 + port 范围 + path 编码合法性(如 % 后必须跟两位十六进制)。
最易被忽略的是百分号编码校验:https://a.b/c%zz 中的 %zz 不合法,但很多简易实现直接跳过。只要 URL 含 %,就得确保后续两个字符都是十六进制数字。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











