【发布时间】:2020-12-26 17:21:52
【问题描述】:
显然 Safari 在发送 POST 数据时会将 Unicode 标准化,而所有其他主流浏览器只是发送它们所提供的内容。
规范化似乎是在数据通过网络发送之前发生的,并且对数据使用normalize() 不起作用(Safari 强制执行 NFC,无论提供什么)。
当请求带有重音字符的文件名时,这会成为一个问题,该字符在 NFC 和 NFD 格式中具有不同的代码点。解释基本上归结为Unicode equivalence 中的“组合字符”与“预组合字符”。
话虽如此,假设一个 API 不会在后端进行自己的规范化,并且需要一个字符串数组(文件名),那么在使用 Safari 时是否可以在前端发送正确的文件名?
Unicode 规范化问题的一个例子:
const str = 'Rosé'
const nfc = str.normalize()
const nfd = str.normalize('NFD')
console.log(nfc === nfd) // false
console.log(nfc.codePointAt(3)) // 233
console.log(nfd.codePointAt(3)) // 101
console.log(nfc.codePointAt(4)) // undefined
console.log(nfd.codePointAt(4)) // 769
一个最小的、可重现的例子:
请注意 Chrome 和 Safari 之间的控制台日志差异。
const isCorrectForm = (path, form) => path === path.normalize(`NF${form}`)
const fetchData = async() => {
const sourcePathC = '\u00e9'; // "é"
const sourcePathD = '\u0065\u0301'; // "é"
await fetch('https://httpbin.org/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
pathsFormC: [sourcePathC],
pathsFormD: [sourcePathD]
}),
})
.then((response) => response.json())
.then((data) => {
const responseData = JSON.parse(data.data);
const responsePathC = responseData.pathsFormC[0];
const responsePathD = responseData.pathsFormD[0];
console.log({
isSourcePathCFormC: isCorrectForm(sourcePathC, 'C'),
isSourcePathDFormD: isCorrectForm(sourcePathD, 'D'),
isResponsePathCFormC: isCorrectForm(responsePathC, 'C'),
isResponsePathDFormD: isCorrectForm(responsePathD, 'D'),
});
});
}
fetchData();
【问题讨论】:
-
Héhé 似乎我自己在编辑问题时被这个困住了:我首先从 Firefox(我的主浏览器)尝试,然后从 Safari 尝试查看它是否确实可重现,并从该 Safari 发布。 ..
-
也许这个简单的更改可以工作,但无法在 Safari 上进行测试。 jsfiddle.net/ez1u37qg
标签: javascript rest post unicode safari