Ruby 将nginx uuid从十六进制转换为Base64:字节顺序是如何涉及的?

Ruby 将nginx uuid从十六进制转换为Base64:字节顺序是如何涉及的?,ruby,nginx,binary,endianness,nibble,Ruby,Nginx,Binary,Endianness,Nibble,Nginx可以配置为生成一个。在接收到来自新客户端的请求后,它会以两种形式附加uuid,然后将请求向上游转发到源服务器: Base64中带有uuid的cookie(例如,CgIGR1ZfUkeEXQ2YAwMZAg==) uuid为十六进制的标头(例如4706020A47525F56980D5D8402190303) 我想将十六进制表示形式转换为Base64等效形式。我在Ruby中有一个可行的解决方案,但我没有完全掌握底层机制,尤其是字节顺序的切换: hex_str = "4706020A4

Nginx可以配置为生成一个。在接收到来自新客户端的请求后,它会以两种形式附加uuid,然后将请求向上游转发到源服务器:

  • Base64中带有uuid的cookie(例如,
    CgIGR1ZfUkeEXQ2YAwMZAg==
  • uuid为十六进制的标头(例如
    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"
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"
将二进制映射到32位小尾数无符号整数数组。每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]
数据
视为32位大端无符号整数数组,生成(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"
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字符串中编码
网络\u seq

Base64.encode64(network_seq).strip

#=> "CgIGR1ZfUkeEXQ2YAwMZAg=="
我的粗略理解是,big-endian是网络通信的标准字节顺序,而little-endian在主机上更常见。为什么nginx提供了两种需要切换字节顺序才能转换的形式,我不确定

我也不明白
.unpack(“vvv”)
.pack(“NNNN”)
步骤是如何工作的。我可以看到
G\x06\x02\n
变成了
\n\x02\x06G
,但我不理解达到这个目的的步骤。例如,专注于
hex_str
的前8位,为什么
.pack(H*)
.unpack(“vvv”)
会产生:

"4706020A" -> "G\x06\x02\n" -> 167904839
而直接转换为base-10会产生:

"4706020A".to_i(16) -> 1191576074

??我这样问的事实表明,我需要澄清在所有这些转换中到底发生了什么:)

您看过WebServerUid gem吗?我不知道它是否解决了您的问题,但自述文件确实提到cookie是十六进制字符串中“完全相同数据的Base64编码、endianness反转版本”。源代码的注释非常好:@jordan是的,实际上这就是我开始了解如何实现它的地方。这是相当好的评论,但我想我需要进一步细分,看看我的知识差距到底在哪里。