new url() 是唯一按标准解析协议的可靠方式,需 trim() 后校验 protocol 是否为 http: 或 https:,正则易误判且不验证协议合法性,后端必须二次校验并同样 trim()。

pattern 属性不校验协议头,只做字符串匹配
HTML 的 pattern 属性本身不理解“协议”概念,它只是把你的正则当作纯字符串去比对。比如 pattern="https?://.*" 看似能拦住没协议的网址,但实际会放行 ftp://x、http:///example.com,甚至 xyz://a——只要开头恰好匹配上你写的字面模式。它不验证协议是否被浏览器支持,也不检查斜杠数量或域名结构。
更关键的是:pattern 只在 type="text"、type="url" 等少数类型中生效;而 type="url" 自带的原生校验会和 pattern 并存,iOS Safari 常直接忽略 pattern,导致行为不可控。
new URL() 才真正解析协议,但要求绝对 URL
new URL() 是目前唯一按 WHATWG 标准解析协议、主机、路径的可靠方式。它会严格拒绝 /api、./page、www.example.com(缺协议)这类输入,并在协议非法时抛出 TypeError。
实操要点:
- 必须先调用
.trim(),否则" https://a.com "直接报错 - 只接受绝对 URL,相对路径需额外逻辑判断(比如手动补
https://再试) - 不捕获空格、BOM、零宽字符等隐形干扰,所以前端校验前务必清理输入
示例函数:
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
function isValidUrlWithProtocol(s) {
try {
const url = new URL(s.trim());
return url.protocol === 'http:' || url.protocol === 'https:';
} catch (_) {
return false;
}
}
正则强行匹配协议头容易漏判或误判
手写正则如 ^https?://[^\s/$.?#].[^\s]*$ 表面看能卡住协议,但问题很多:
- 放行
https://localhost:3000和https://例.com(它们协议合法,但可能不符合业务域名白名单) - 不处理 Unicode IDN 域名(如
https://中文.中国),现代浏览器支持,但旧正则常崩 - 无法区分
http://和https://的语义差异,比如某些接口强制 HTTPS - 若后端没做二次校验,攻击者可绕过前端直接发
javascript:alert(1)这类伪协议
真正需要协议控制的场景(如只允许 HTTPS),应优先用 new URL() + url.protocol 判断,而不是依赖正则锚点。
后端必须重验 protocol,且不能信前端任何输出
前端所有校验都可被禁用 JS、改 DOM 或 curl 绕过。后端收到 URL 字符串后:
- PHP 必须用
filter_var($url, FILTER_VALIDATE_URL),再检查parse_url($url, PHP_URL_SCHEME)是否为https - Python 应用
urllib.parse.urlparse(),确认.scheme in ('http', 'https'),且.netloc非空 - Node.js 同样走
new URL()并捕获异常,不能只靠正则test()
最易被忽略的一点:后端也得 trim()。带首尾空格的字符串传给 new URL() 会直接 throw,不是返回 false——很多后端同学忘了这步,导致 500 错误而非友好提示。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










