Nginx は、クライアントの識別に適した uuid を生成するように構成できます。新しいクライアントからリクエストを受信すると、リクエストを上流のオリジン サーバーに転送する前に、2 つの形式で uuid を追加します。
- Base64 の uuid を持つ Cookie (例
CgIGR1ZfUkeEXQ2YAwMZAg==
) - 16 進数の uuid を含むヘッダー (例:
4706020A47525F56980D5D8402190303
)
16 進表現を 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 ビットのリトル エンディアン符号なし整数の配列にマップします。各 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 ビットのビッグエンディアンの符号なし整数の配列として扱い、(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"
network_seq
Base64 文字列にエンコードします。
Base64.encode64(network_seq).strip
#=> "CgIGR1ZfUkeEXQ2YAwMZAg=="
私の大まかな理解は、ビッグ エンディアンがネットワーク通信の標準的なバイト順であるのに対し、ホスト マシンではリトル エンディアンがより一般的であるということです。nginx が、変換するためにバイト オーダーを切り替える必要がある 2 つの形式を提供する理由はわかりません。
.unpack("VVVV")
また、との.pack("NNNN")
手順がどのように機能するかわかりません。にG\x06\x02\n
なる\n\x02\x06G
のはわかりますが、そこにたどり着くまでの手順がわかりません。たとえば、 の最初の 8 桁に注目するとhex_str
、なぜ do.pack(H*)
と を.unpack("VVVV")
生成するのか:
"4706020A" -> "G\x06\x02\n" -> 167904839
base-10 に直接変換すると、次のようになります。
"4706020A".to_i(16) -> 1191576074
? 私がこれを尋ねているという事実は、これらすべての変換で正確に何が起こっているのかを明確にする必要があることを示しています:)