可以将Nginx配置为生成uuid suitable for client identification。在收到来自新客户端的请求后,它会在将请求上游转发到源服务器之前以两种形式附加一个uuid:
CgIGR1ZfUkeEXQ2YAwMZAg==
)4706020A47525F56980D5D8402190303
)我想将十六进制表示转换为Base64等价物。我有一个Ruby的工作解决方案,但我没有完全掌握底层的机制,尤其是字节顺序的切换:
hex_str = "4706020A47525F56980D5D8402190303"
将hex_str
作为一系列高半字节(最重要的4位优先)二进制数据处理,生成(ASCII编码)字符串表示:
binary_seq = [hex_str].pack("H*")
# 47 (71 decimal) -> "G"
# 06 (6 decimal) -> "\x06" (non-printable)
# 02 (2 decimal) -> "\x02" (non-printable)
# 0A (10 decimal) -> "\n"
# ...
#=> "G\x06\x02\nGR_V\x98\r]\x84\x02\x19\x03\x03"
将binary_seq
映射到32位 little-endian 无符号整数的数组。每4个字符(4个字节= 32位)映射到一个整数:
data = binary_seq.unpack("VVVV")
# "G\x06\x02\n" -> 167904839 (?)
# "GR_V" -> 1449087559 (?)
# "\x98\r]\x84" -> 2220690840 (?)
# "\x02\x19\x03\x03" -> 50534658 (?)
#=> [167904839, 1449087559, 2220690840, 50534658]
将data
视为32位 big-endian 无符号整数的数组,生成(ASCII编码)字符串表示形式:
network_seq = data.pack("NNNN")
# 167904839 -> "\n\x02\x06G" (?)
# 1449087559 -> "V_RG" (?)
# 2220690840 -> "\x84]\r\x98" (?)
# 50534658 -> "\x03\x03\x19\x02" (?)
#=> "\n\x02\x06GV_RG\x84]\r\x98\x03\x03\x19\x02"
在Base64字符串中编码network_seq
:
Base64.encode64(network_seq).strip
#=> "CgIGR1ZfUkeEXQ2YAwMZAg=="
我粗略地理解,big-endian是网络通信的标准字节顺序,而little-endian在主机上更常见。为什么nginx提供了两种需要切换字节顺序来转换的形式,我不确定。
我也不了解.unpack("VVVV")
和.pack("NNNN")
步骤的工作原理。我可以看到G\x06\x02\n
变为\n\x02\x06G
,但我不明白到达那里的步骤。例如,关注hex_str
的前8位数,为什么.pack(H*)
和.unpack("VVVV")
会产生:
"4706020A" -> "G\x06\x02\n" -> 167904839
而直接转换为base-10会产生:
"4706020A".to_i(16) -> 1191576074
?我问这个事实表明我需要澄清所有这些转换中到底发生了什么:)