内容提要
前端开发中的大小写敏感问题:HTTP Header 名不区分大小写,HTTP/2 要求转小写;HTTP Method 区分大小写且须大写;URL 的协议和域名不区分大小写,路径、查询和片段区分;Cookie 名区分大小写;邮箱域名不区分大小写,用户名取决于服务商;HTML 标签和普通属性不区分大小写,data- 属性须小写;CSS 选择器语法不区分大小写;Git 默认忽略文件名大小写,建议关闭该配置并用 git mv 重命名。
延伸解读
规范与实现之间的差异
文章多次指出,规范与实际实现并不总是一致。例如 HTTP Header 名称按 RFC 7230 不区分大小写,但 HTTP/2 要求编码前转小写;XHR 标准未要求转小写,浏览器底层网络库却会处理。URL 路径按规范区分大小写,实际却取决于服务器文件系统。这提醒开发者不能只依赖规范文本,还要关注运行时行为。
浏览器与服务器行为差异带来的调试成本
文章通过 Chrome 和 Safari 的抓包实验说明,请求头大小写转换发生在底层网络库而非 XHR 本身,Safari 控制台展示甚至可能不准确。响应头经 getAllResponseHeaders 获取时会被 Blink 转小写,HTTP/2 下大写头字段还会导致解析失败。这类差异不易从代码直接看出,排查时需要借助抓包工具和 netlog-viewer 等底层手段。
文件系统与 Git 配置的跨平台风险
文章指出 Windows 的 NTFS/FAT 和 macOS 的 APFS/HFS+ 默认大小写不敏感但保留大小写,Linux 的 ext3/ext4 则敏感。Git 默认忽略文件名大小写,若有人在敏感系统上提交了仅大小写不同的文件,其他平台可能无法正常拉取。建议关闭 core.ignorecase 并用 git mv 重命名,条件允许时可将文件系统改为大小写敏感。
容易忽略的例外规则
文章列举了几处反直觉的例外:HTML 标签和普通属性不区分大小写,但 data- 属性必须小写;CSS 选择器语法不区分大小写,属性名和属性值是否区分则取决于文档语言;Cookie 名称区分大小写,尽管 RFC 6265 并未明说;邮箱域名不区分大小写,用户名是否区分取决于服务商。这些例外容易在跨语言或跨协议场景中引发隐蔽问题。
Q&A
HTTP Header 名称区分大小写吗?HTTP/2 有什么特殊要求?
HTTP Header 名称不区分大小写(RFC 7230)。但 HTTP/2 因为头部压缩,要求编码前必须转成小写(RFC 7540),大多数客户端和服务端也会默认将 Header 名称统一改为小写。
HTTP Method 区分大小写吗?如果传入小写会怎样?
HTTP Method 区分大小写,且必须为大写(RFC 7230)。但浏览器内核(如 Blink)会将小写 Method 规范化为大写,例如 ajax.open("get", ...) 会被转成 GET。
URL 中哪些部分区分大小写?路径是否一定区分?
URL 的协议(scheme)和域名(host)不区分大小写,浏览器会自动转小写;path、query、fragment 按规范区分大小写。但 path 实际是否区分取决于 Web 服务器底层文件系统,例如 IIS 或部署在 Windows/macOS 默认文件系统上的 Apache 可能不区分。
Cookie 的名称区分大小写吗?
Cookie 的名称区分大小写。虽然早期 RFC 2109 规定不区分,但该规范已被废弃,最新 RFC 6265 未明确说明,默认视为区分,主流浏览器 Chrome 和 Firefox 的实现也都是区分大小写的。
HTML5 标签和属性名区分大小写吗?data- 属性有什么特殊要求?
HTML5 标签名和普通属性名不区分大小写(如 <!DOCTYPE html> 可写成 <!doctype html>)。但 data- 属性是例外,必须全部小写,不能包含大写字母。
Git 默认忽略文件名大小写吗?如何避免大小写导致的问题?
Git 默认不区分文件名大小写。建议关闭该配置:git config --global core.ignorecase false,并在重命名时使用 git mv --force 旧名 新名,避免在大小写不敏感的系统上出现文件冲突。