Chrome用のspdyプロキシサーバーを構築していました。
プロキシ リクエストが Chrome から送信された場合、通常は 3 つのフレームを受け取ります。
- SETTINGS フレーム (正しく解析されます)
- https' CONNECT リクエストの SYN_STREAM フレーム (正しく解析されます)
- 名前/値ブロックを解凍できなかった別の SYN_STREAM フレーム (データの解凍中にエラー -3: ヘッダー チェックが正しくありません)
最後のフレームは、名前/値ブロックも含む最初の SYN_STREAM を解析できたため、非常に奇妙でした。
私は丸 2 日間問題を解決しようとしていて、spdy のバージョンを 2 から 3 に切り替えましたが、それでも解決できませんでした。
これが私の解凍関数です(Python 3.3):
def decompress(buf):
decompressor = zlib.decompressobj(zdict=DICT3)
# DICT3 is the dictionary of spdy3 to decompress NV block
return decompressor.decompress(buf)
ログの完全な例を次に示します。
(1)2014-01-06 14:44:55,070 proxy DEBUG: [49036176] on_read b'\x80\x03\x00\x04\x00\x00\x00\x14\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x03\xe8\x00\x00\x00\x07\x00\xa0\x00\x00\x80\x03\x00\x01\x00\x00\x00\xbf\x00\x00\x00\x01\x00\x00\x00\x00\x00\x008\xea\xe3\xc6\xa7\xc2\x02e%\x10\xb6\x82\x16\x08\\\xc0\xd4U\x90X\xa9\x97\x0c.&\xd8\xad\xe0\x89\x99\xdd\xd9\xdf\xcf\xcf\xd59\x04\xac\xb8 \x11\\l\xf1\x01\x04PbNfAb\xa5^r~\xae\x95\x89\x891@\x00\x81\x12\xb3\x15\xf6\x84\x8d\x9a\xa1r|\xf3\xab2sr\x12\xf5M\xf5\x0c\x144\xc23\xf3R\xf2\xcb\x8b\x15\xfcB\x14\xcc\xf4\x0c\xad\x15\xc2\xfd\xc3\xcdL4\x811\x06\x8c\xdf\xf0\xd4$\xef\xcc\x12}Scs=c3\x05\ro\x8f\x10_\x1f\x1d\x85\x9c\xcc\xecT\x05\xf7\xd4\xe4\xec|M\x05\xe7\x0c`\x89\x96\xaaol\xa8g\xa0ghfj\xa0g\x06L\x0b\x89i\x89E\x99P]\x00\x00\x00\x00\xff\xff\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x03\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
(2)2014-01-06 14:44:55,071 proxy DEBUG: [49036176] >-- <SETTINGS SETTINGS_MAX_CONCURRENT_STREAMS=1000 SETTINGS_INITIAL_WINDOW_SIZE=10485760 [20]>
(3)2014-01-06 14:44:55,073 proxy DEBUG: [49036176] >-- <SYN_STREAM #1->#0 [191]:host: alipay.com :method: CONNECT :version: HTTP/1.1 :path: alipay.com:443 user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 >
(4)2014-01-06 14:44:55,074 proxy DEBUG: [49036176] error Error -3 while decompressing data: incorrect header check
(5)2014-01-06 14:44:55,074 proxy DEBUG: [49036176] zlib.e b'\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x03\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
(6)2014-01-06 14:45:25,070 proxy DEBUG: [49036176] on_read b'\x80\x03\x00\x03\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x05\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x05\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff\x80\x03\x00\x03\x00\x00\x00\x08\x00\x00\x00\x03\x00\x00\x00\x05'
(7)2014-01-06 14:45:25,072 proxy DEBUG: [49036176] >-- <RST_STREAM #1 [8]CANCEL>
少し説明させてください:
(1) プロキシは、3 つの spdy フレームを含むソケットから raw バイトを受信しました
(2) SETTINGS フレームが (1) のバイトから解析された
b'\x80\x03\x00\x04\x00\x00\x00\x14\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x03\xe8\x00\x00\x00\x07\x00\xa0\x00\x00
(3) SYN_STREAM フレームも解析された
b'\x80\x03\x00\x01\x00\x00\x00\xbf\x00\x00\x00\x01\x00\x00\x00\x00\x00\x008\xea\xe3\xc6\xa7\xc2\x02e%\x10\xb6\x82\x16\x08\\\xc0\xd4U\x90X\xa9\x97\x0c.&\xd8\xad\xe0\x89\x99\xdd\xd9\xdf\xcf\xcf\xd59\x04\xac\xb8 \x11\\l\xf1\x01\x04PbNfAb\xa5^r~\xae\x95\x89\x891@\x00\x81\x12\xb3\x15\xf6\x84\x8d\x9a\xa1r|\xf3\xab2sr\x12\xf5M\xf5\x0c\x144\xc23\xf3R\xf2\xcb\x8b\x15\xfcB\x14\xcc\xf4\x0c\xad\x15\xc2\xfd\xc3\xcdL4\x811\x06\x8c\xdf\xf0\xd4$\xef\xcc\x12}Scs=c3\x05\ro\x8f\x10_\x1f\x1d\x85\x9c\xcc\xecT\x05\xf7\xd4\xe4\xec|M\x05\xe7\x0c`\x89\x96\xaaol\xa8g\xa0ghfj\xa0g\x06L\x0b\x89i\x89E\x99P]\x00\x00\x00\x00\xff\xff'
(4) 解析を続行すると、別の SYN_STREAM に遭遇しました。
b'\x80\x03\x00\x01\x00\x00\x00)\x00\x00\x00\x03\x00\x00\x00\x00`\x00\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
しかし、どういうわけか名前/値ブロック部分が解凍できません
6 ~ 8 バイトは残りのデータの長さを示します (長さ:'\x00\x00)'=41)。末尾は '\x00\x00\xff\xff' であるため、フレームを正しく分割する必要がありました。
「長さバイト」の後、圧縮された名前/値ブロックの前に、さらに 10 バイトあります。
(5) エラーがキャプチャされ、トラブル フレームのバイトがリストされました。実際の圧縮された名前/値ブロックのバイトは次のとおりです。
b'\xa2\xcc\x87\x00\x01\x94\x98\x93Y\x90X\xa9\x97\x9c\x9fkebb\x0c\x10@\x83\xd3\x87\x00\x00\x00\x00\xff\xff'
(6/7) chrome からしばらく応答がないので、(3)の SYN_STREAM リクエストをキャンセルするために RST_STREAM フレームを送信しました (これで問題ありません)。
解凍機能の問題点は何ですか?
または、2番目のSYN_STREAMのNVブロックを解凍する方法を知っている人はいますか?
ありがとう!
編集:
ログの完全な例を追加します。
@Mark のおかげで、.flush() が呼び出されていないことがわかりましたが、主なエラーは「不正なヘッダー」でした)