在发送 POST 数据时阻止 Safari 规范化 Unicode?

jab*_*tta 6 javascript unicode safari rest post

显然,Safari 在发送 POST 数据时对 Unicode 进行了规范化,而所有其他主要浏览器只发送它们所提供的内容。

规范化似乎发生在数据通过网络发送之前,并且对数据使用normalize()不起作用(Safari 强制执行 NFC,无论它提供什么)。

当请求带有重音字符的文件名时,这会成为一个问题,它在 NFC 和 NFD 格式中具有不同的代码点。解释基本上归结为Unicode 等价中的“组合字符”与“预组合字符” )。

话虽如此,鉴于 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
Run Code Online (Sandbox Code Playgroud)

一个最小的、可重现的例子:

请注意 Chrome 和 Safari 之间的控制台日志差异。

const isCorrectForm = (path, form) => path === path.normalize(`NF${form}`)

const fetchData = async() => {
  const sourcePathC = '\u00e9'; // "é"
  const sourcePathD = '\u0065\u0301'; // "e?"

  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();
Run Code Online (Sandbox Code Playgroud)

小智 1

也许这是一个简单的解决方案。我说也许是因为这没有在 Safari 上进行测试(不幸的是)。

\n

\r\n
\r\n
const isCorrectForm = (path, form) => path === path.normalize(`NF${form}`)\n\nconst fetchData = async() => {\n  const sourcePathC = encodeURIComponent(\'\\u00e9\'); // "\xc3\xa9"\n  const sourcePathD = encodeURIComponent(\'\\u0065\\u0301\'); // "e\xcc\x81"\n\n  console.log(sourcePathC, sourcePathD);\n\n  await fetch(\'https://httpbin.org/post\', {\n      method: \'POST\',\n      headers: {\n        \'Content-Type\': \'application/json\'\n      },\n      body: JSON.stringify({\n        pathsFormC: [sourcePathC],\n        pathsFormD: [sourcePathD]\n      }),\n    })\n    .then((response) => response.json())\n    .then((data) => {\n      const responseData = JSON.parse(data.data);\n      const responsePathC = decodeURIComponent(responseData.pathsFormC[0]);\n      const responsePathD = decodeURIComponent(responseData.pathsFormD[0]);\n\n      console.log(responsePathC, responsePathD);\n\n      console.log({\n        isSourcePathCFormC: isCorrectForm(sourcePathC, \'C\'),\n        isSourcePathDFormD: isCorrectForm(sourcePathD, \'D\'),\n        isResponsePathCFormC: isCorrectForm(responsePathC, \'C\'),\n        isResponsePathDFormD: isCorrectForm(responsePathD, \'D\'),\n      });\n    });\n}\n\nfetchData();
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n