是否有 Javascript 等同于 urllib.quote 和 urllib.unquote?
Is there a Javascript equivalent to urllib.quote and urllib.unquote?
根据这个 answer 几年前给出的相同问题,Javascript 中的 encodeURIComponent(str) 应该等同于 urllib.quote(str, safe='~() *!.\'') Python。通过扩展,我猜到 decodeURIComponent(str) 将等同于 urllib.unquote(str).
根据我的经验,情况并非如此。我正在编写一些网络代码以从 Python 服务器与网站上的客户端进行通信,但我得到了不同的结果。
我正在生成一个唯一 ID 并使用与以下代码几乎相同的内容通过 TCP 发送它:
import urllib
import struct
import random
def sendID():
id = random.SystemRandom().getrandbits(128)
upper = id >> 64
lower = id & 0xFFFFFFFFFFFFFFFF
packed = struct.pack('<B2Q', 0x00, upper, lower)
encoded = urllib.quote(packed, safe='~()*!.\'')
# the below line is just sending it over an already established TCP connection
# the code is irrelevant as I already this is working as expected
sendtoclient(encoded)
客户端在以下 websocket 对象回调中收到消息:
this.websocket.onmessage = function (msg) {
console.log(msg.data);
var sType = bufferpack.unpack('<B', decodeURIComponent(msg.data).substring(0, 1));
console.log(sType);
};
这应该解码 msg.data 字符串并将 sType 设置为打包数据的第一个 'part'(在本例中为 0x00)。
我遇到的问题是这些功能没有按我的预期运行。在 JSFiddle 和 Python 命令行中进行一些测试后,我得到了 encode/decodeURIComponent 和 urllib.quote/unquote 函数的不同结果。 encodeURIComponent 只是给我一个与 'equivalent' urllib.quote 不同的结果,而 decodeURIComponent 导致格式错误的 URI 错误。
这可以在下面显示的示例中看到:
>>> import random
>>> import urllib
>>> import struct
>>> id = random.SystemRandom().getrandbits(128)
>>> upper = id >> 64
>>> lower = id & 0xFFFFFFFFFFFFFFFF
>>> packed = struct.pack('<B2Q', 0x00, upper, lower)
>>> encoded = urllib.quote(packed, safe='~()*!.\'')
>>> id
79837607446780471980532690349264559028L
>>> upper
4328005371992213727L
>>> lower
4092443888854326196L
>>> packed
'\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'
>>> encoded
'%00%DF%08%94%7F%F4)%10%3C%B4%5Ba%C2%08H%CB8'
然而,当我分别在 'packed' 和 'encoded' 上使用 encodeURIComponent 和 decodeURIComponent 时,我得到了不同的编码值并且解码会引发错误。 Javascript 后面的输出如下所示。
console.log(encodeURIComponent('\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'))
console.log(decodeURIComponent('%00%DF%08%94%7F%F4)%10%3C%B4%5Ba%C2%08H%CB8'));
%00%C3%9F%08%C2%94%7F%C3%B4)%10%3C%C2%B4%5Ba%C3%82%08H%C3%8B8
(index):50 Uncaught URIError: URI malformed
JSFiddle snippet with the above Javascript code for your convenience.
所以最后,我的实际问题是:上面使用的函数(quote/unquote 和 encode/decodeURIComponent)实际上是等价的吗?如果不能,有人可以建议代码更改或其他 libraries/functions 可以达到我的预期(客户端和服务器端的 encoded/decoded 和 packed/unpacked 值相同)?
在使用我的示例代码并阅读了一些关于类似问题的其他资源后,我发现 'packed' 字符串是使用 'latin-1' 字符集编码的,并且 urllib.quote无法正常工作。
下面我从我的 python 解释器中包含了相同的示例,并添加了一些额外的行,表明通过正确的编码函数 urllib.quote/unquote 和 encode/decodeURIComponent 实际上是处理 utf-8 时等效。
>>> import random
>>> import urllib
>>> import struct
>>> id = random.SystemRandom().getrandbits(128)
>>> upper = id >> 64
>>> lower = id & 0xFFFFFFFFFFFFFFFF
>>> packed = struct.pack('<B2Q', 0x00, upper, lower)
>>> encoded = urllib.quote(packed, safe='~()*!.\'')
>>> id
79837607446780471980532690349264559028L
>>> upper
4328005371992213727L
>>> lower
4092443888854326196L
>>> packed
'\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'
>>> encoded
'%00%DF%08%94%7F%F4)%10%3C%B4%5Ba%C2%08H%CB8'
>>> packed.decode('latin-1')
u'\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'
>>> packed.decode('latin-1').encode('utf-8')
'\x00\xc3\x9f\x08\xc2\x94\x7f\xc3\xb4)\x10<\xc2\xb4[a\xc3\x82\x08H\xc3\x8b8'
>>> urllib.quote(packed.decode('latin-1').encode('utf-8'), safe='~()*!.\'')
'%00%C3%9F%08%C2%94%7F%C3%B4)%10%3C%C2%B4%5Ba%C3%82%08H%C3%8B8'
输出
'%00%C3%9F%08%C2%94%7F%C3%B4)%10%3C%C2%B4%5Ba%C3%82%08H%C3%8B8'
匹配
的输出
encodeURIComponent('\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8')
在 Javascript.
根据这个 answer 几年前给出的相同问题,Javascript 中的 encodeURIComponent(str) 应该等同于 urllib.quote(str, safe='~() *!.\'') Python。通过扩展,我猜到 decodeURIComponent(str) 将等同于 urllib.unquote(str).
根据我的经验,情况并非如此。我正在编写一些网络代码以从 Python 服务器与网站上的客户端进行通信,但我得到了不同的结果。
我正在生成一个唯一 ID 并使用与以下代码几乎相同的内容通过 TCP 发送它:
import urllib
import struct
import random
def sendID():
id = random.SystemRandom().getrandbits(128)
upper = id >> 64
lower = id & 0xFFFFFFFFFFFFFFFF
packed = struct.pack('<B2Q', 0x00, upper, lower)
encoded = urllib.quote(packed, safe='~()*!.\'')
# the below line is just sending it over an already established TCP connection
# the code is irrelevant as I already this is working as expected
sendtoclient(encoded)
客户端在以下 websocket 对象回调中收到消息:
this.websocket.onmessage = function (msg) {
console.log(msg.data);
var sType = bufferpack.unpack('<B', decodeURIComponent(msg.data).substring(0, 1));
console.log(sType);
};
这应该解码 msg.data 字符串并将 sType 设置为打包数据的第一个 'part'(在本例中为 0x00)。
我遇到的问题是这些功能没有按我的预期运行。在 JSFiddle 和 Python 命令行中进行一些测试后,我得到了 encode/decodeURIComponent 和 urllib.quote/unquote 函数的不同结果。 encodeURIComponent 只是给我一个与 'equivalent' urllib.quote 不同的结果,而 decodeURIComponent 导致格式错误的 URI 错误。
这可以在下面显示的示例中看到:
>>> import random
>>> import urllib
>>> import struct
>>> id = random.SystemRandom().getrandbits(128)
>>> upper = id >> 64
>>> lower = id & 0xFFFFFFFFFFFFFFFF
>>> packed = struct.pack('<B2Q', 0x00, upper, lower)
>>> encoded = urllib.quote(packed, safe='~()*!.\'')
>>> id
79837607446780471980532690349264559028L
>>> upper
4328005371992213727L
>>> lower
4092443888854326196L
>>> packed
'\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'
>>> encoded
'%00%DF%08%94%7F%F4)%10%3C%B4%5Ba%C2%08H%CB8'
然而,当我分别在 'packed' 和 'encoded' 上使用 encodeURIComponent 和 decodeURIComponent 时,我得到了不同的编码值并且解码会引发错误。 Javascript 后面的输出如下所示。
console.log(encodeURIComponent('\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'))
console.log(decodeURIComponent('%00%DF%08%94%7F%F4)%10%3C%B4%5Ba%C2%08H%CB8'));
%00%C3%9F%08%C2%94%7F%C3%B4)%10%3C%C2%B4%5Ba%C3%82%08H%C3%8B8 (index):50 Uncaught URIError: URI malformed
JSFiddle snippet with the above Javascript code for your convenience.
所以最后,我的实际问题是:上面使用的函数(quote/unquote 和 encode/decodeURIComponent)实际上是等价的吗?如果不能,有人可以建议代码更改或其他 libraries/functions 可以达到我的预期(客户端和服务器端的 encoded/decoded 和 packed/unpacked 值相同)?
在使用我的示例代码并阅读了一些关于类似问题的其他资源后,我发现 'packed' 字符串是使用 'latin-1' 字符集编码的,并且 urllib.quote无法正常工作。
下面我从我的 python 解释器中包含了相同的示例,并添加了一些额外的行,表明通过正确的编码函数 urllib.quote/unquote 和 encode/decodeURIComponent 实际上是处理 utf-8 时等效。
>>> import random
>>> import urllib
>>> import struct
>>> id = random.SystemRandom().getrandbits(128)
>>> upper = id >> 64
>>> lower = id & 0xFFFFFFFFFFFFFFFF
>>> packed = struct.pack('<B2Q', 0x00, upper, lower)
>>> encoded = urllib.quote(packed, safe='~()*!.\'')
>>> id
79837607446780471980532690349264559028L
>>> upper
4328005371992213727L
>>> lower
4092443888854326196L
>>> packed
'\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'
>>> encoded
'%00%DF%08%94%7F%F4)%10%3C%B4%5Ba%C2%08H%CB8'
>>> packed.decode('latin-1')
u'\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8'
>>> packed.decode('latin-1').encode('utf-8')
'\x00\xc3\x9f\x08\xc2\x94\x7f\xc3\xb4)\x10<\xc2\xb4[a\xc3\x82\x08H\xc3\x8b8'
>>> urllib.quote(packed.decode('latin-1').encode('utf-8'), safe='~()*!.\'')
'%00%C3%9F%08%C2%94%7F%C3%B4)%10%3C%C2%B4%5Ba%C3%82%08H%C3%8B8'
输出
'%00%C3%9F%08%C2%94%7F%C3%B4)%10%3C%C2%B4%5Ba%C3%82%08H%C3%8B8'
匹配
的输出encodeURIComponent('\x00\xdf\x08\x94\x7f\xf4)\x10<\xb4[a\xc2\x08H\xcb8')
在 Javascript.