题干与适用场景
一个 Service Worker 需要只拦截同源的图片和文档路由,并提取租户与资源 ID。请用 URLPattern 设计匹配器,说明组件边界、捕获组、大小写和不支持浏览器的降级。
URLPattern 提供标准化的 URL 模式匹配器,能分别匹配协议、主机、端口、路径、查询和片段,并返回命名或编号捕获组。它适合路由分发、Service Worker 缓存和边缘规则,但匹配成功不等于权限通过,也不能替代规范化与授权检查。
面试官考察点
重点包括:按 URL 组件而不是整串文本匹配、通配符与分组语法、相对模式的 baseURL、各组件默认大小写规则、捕获结果的可信边界,以及跨浏览器兼容和模式编译失败处理。
澄清问题
先确认只允许哪些协议、主机和端口,路径是否区分大小写,查询参数是否参与匹配,以及租户和资源 ID 是否必须完整匹配。再确认运行在页面、Service Worker 还是 Worker,目标浏览器支持范围,以及匹配结果是否会影响缓存或安全决策。
30 秒回答框架
“我会把协议、主机和端口写成固定组件,只在路径中使用命名捕获组提取租户和资源 ID,并用 baseURL 明确相对模式的解析基准。模式编译时立即捕获语法错误,运行时先检查完整 URL 和同源约束,再使用结果驱动缓存或路由。URLPattern 只是匹配器,不提供授权;不支持的浏览器使用 URL 解析加经过测试的有限回退,避免用正则复制完整 URL 语义。”
分步骤深入解答
第一步:按组件构造模式
URLPattern 可以接收包含 protocol、hostname、port、pathname、search 和 hash 的对象,也可以接收 URL 风格字符串。安全敏感的路由应明确协议和主机,不要只匹配路径后接受任意来源。
第二步:使用命名捕获组
路径中的命名组可以从 exec() 结果读取,便于把租户和资源 ID 映射到业务字段。捕获组只说明字符串符合模式,仍需检查字符集、长度和业务存在性。
const assetPattern = new URLPattern({
protocol: "https",
hostname: "cdn.example.com",
pathname: "/tenant/:tenantId/assets/:assetId.:ext",
});
const match = assetPattern.exec(request.url);
const assetId = match?.pathname.groups.assetId;第三步:明确通配符和分隔边界
通配符匹配的是特定组件中的字符,不应假设它会跨越路径分隔符或自动覆盖查询。需要匹配层级时显式写出每一段,并测试空值、额外斜杠和编码字符。
第四步:理解 baseURL 与相对模式
相对模式需要 baseURL 才能确定协议、主机等组件。不同环境使用不同 baseURL 会得到不同匹配器,因此应把基准 URL 固定在构造处,并在测试中覆盖开发、预览和生产域名。
第五步:处理大小写和规范化
各 URL 组件的大小写规则并不相同;主机名通常按不区分大小写处理,而路径等组件可能区分大小写。不要先把整条 URL 统一转小写,否则可能改变资源路径或签名输入。
第六步:把匹配与授权分开
URLPattern 不验证租户是否属于当前用户,也不检查资源是否可读。匹配后仍需执行同源、认证、授权、缓存隔离和响应内容类型检查,尤其不能把捕获的租户 ID 当作可信身份。
第七步:编译错误与运行时性能
模式在构造时解析;非法语法应在启动或注册阶段失败,而不是等请求到来才发现。复用已编译实例,避免为每个请求重新构造;高流量路径仍需通过真实 URL 分布测量匹配成本。
第八步:设计兼容回退
不支持 URLPattern 的环境可以使用 new URL() 逐组件检查,但只实现业务实际需要的有限模式。不要用一个宽泛正则复制协议、主机、编码和查询解析;回退逻辑必须与原生匹配器共享同一组用例。
高质量示例答案
我会构造固定 https、固定 CDN 主机和显式路径组件的 URLPattern,用命名组提取租户与资源 ID。Service Worker 收到请求后先执行完整 URL 匹配,再检查同源、认证和缓存分区;捕获结果只当作未验证字符串,继续做长度、字符集和资源权限检查。模式在初始化时编译并捕获语法错误,实例在请求间复用。相对模式的 baseURL 固定为部署域名,测试覆盖大小写、编码斜杠、额外查询和不同环境。旧浏览器使用 URL 的有限逐组件回退,禁止用宽泛正则替代完整 URL 语义。
常见误区
只匹配 pathname 就认为请求同源
任意协议或主机都可能通过同一路径。安全敏感匹配器必须固定来源组件,并在运行时再次检查请求来源。
把捕获组当作已验证 ID
捕获组只证明形状匹配。仍需验证字符集、长度、租户归属、资源存在性和访问权限。
用小写化或正则简化所有 URL
组件大小写和编码语义不同。整串小写可能破坏路径和签名,宽泛正则也容易跨越分隔符或遗漏查询规则。
延伸追问与参考答案
如何避免开发域名的 baseURL 泄漏到生产?
把 baseURL 作为部署配置在初始化时注入,启动时校验允许的协议和主机,并在构建与端到端测试中固定生产域名。不要从用户可控 URL 推导安全匹配器的基准。
模式需要支持可选扩展名怎么办?
用规范允许的可选分组表达,并分别测试有扩展名、无扩展名、额外点号和编码字符。捕获结果为空时仍要选择明确的内容类型和缓存策略。
URLPattern 与路由库如何共存?
让 URLPattern 负责边缘或 Service Worker 的快速筛选,让应用路由库负责完整导航和参数验证。两者共享一组 URL 契约测试,避免同一路径在不同层得到不同解释。