プロジェクトでHTTP REST APIを使用してファイルストレージを使用する作業を実装するのに1回かかりました。 このプロジェクトはpythonで開発されており、さらにhttplib2ライブラリを使用してhttpクライアントが既に実装されているため、httpクライアントの機能を拡張し、同じライブラリを介してファイルストレージを操作することが決定されました。 サーバーへのファイルのアップロード中に問題が発生しました。 最初のPUT要求が実行され、その後のすべての要求は実行を拒否され
ます-500 Internal Server Error 。
Wiresharkを見ると、最初の要求の後、サーバーが
接続を送信していることがわかります。応答ヘッダーで
キープアライブし、5秒後に接続を閉じます。 簡単です-これはサーバーに設定されたキープアライブタイムアウトです。

そして、これはクライアント上でどのように見えるかです:
httplib2のデバッグログを含めます。
httplib2.debuglevel = 4
クライアントでPUTリクエストを実行します。
res = rq.request(url, 'PUT', mediafile, h) connect: (system.restfs.test, 9990) ************ send: 'PUT /domain/p.city/sounds/test_folder/12.wav HTTP/1.1\r\nHost: system.restfs.test:9990\r\nContent-Length: 13864\r\ncontent-type: audio/x-wav\r\naccept-encoding: gzip, deflate\r\nuser-agent: Python-httplib2/0.8 (gzip)\r\n\r\n' send: <open file '/home/mixo/\xd0\x97\xd0\xb0\xd0\xb3\xd1\x80\xd1\x83\xd0\xb7\xd0\xba\xd0\xb8/12.wav', mode 'r' at 0x7fca638c4db0> sendIng a read()able reply: 'HTTP/1.1 201 Created\r\n' header: connection: keep-alive header: server: Cowboy header: date: Fri, 11 Dec 2015 05:14:09 GMT header: content-length: 0 header: content-type: audio/x-wav
繰り返されるPUT要求:
res = rq.request(url, 'PUT', mediafile, h) send: 'PUT /domain/p.city/sounds/test_folder/12.wav HTTP/1.1\r\nHost: system.restfs.test:9990\r\nContent-Length: 13864\r\ncontent-type: audio/x-wav\r\naccept-encoding: gzip, deflate\r\nuser-agent: Python-httplib2/0.8 (gzip)\r\n\r\n' send: <open file '/home/mixo/\xd0\x97\xd0\xb0\xd0\xb3\xd1\x80\xd1\x83\xd0\xb7\xd0\xba\xd0\xb8/12.wav', mode 'r' at 0x7f167a933030> sendIng a read()able reply: '' connect: (system.restfs.test, 9990) ************ send: 'PUT /domain/p.city/sounds/test_folder/12.wav HTTP/1.1\r\nHost: system.restfs.test:9990\r\nContent-Length: 13864\r\ncontent-type: audio/x-wav\r\naccept-encoding: gzip, deflate\r\nuser-agent: Python-httplib2/0.8 (gzip)\r\n\r\n' send: <open file '/home/mixo/\xd0\x97\xd0\xb0\xd0\xb3\xd1\x80\xd1\x83\xd0\xb7\xd0\xba\xd0\xb8/12.wav', mode 'r' at 0x7f167a933030> sendIng a read()able reply: 'HTTP/1.1 500 Internal Server Error\r\n' header: connection: keep-alive header: server: Cowboy header: date: Fri, 11 Dec 2015 05:26:27 GMT header: content-length: 0 header: content-type: audio/x-wav
ここでは、httplib2がサーバーによって規定されているように、接続を再確立せず、応答を受信せずに同じソケットに新しい要求を送信し、接続が再確立されて2番目の要求を送信します。 ただし、この繰り返し要求はサーバーによって処理されなくなり、エラー500が返されます。

同時に、2つのリクエストのWiresharkログを比較すると、接続を再インストールした後、ファイルが送信されず、リクエストが中断されて完全に送信されていないことがわかります。
すぐに、
接続を設定するために選択されました
:一時的な解決策として、サーバー上の応答のヘッダーを
閉じます。 このオプションは機能していることがわかりました。あなたが正しい軌道に乗っており、解決策が近いと感じてうれしいです。
しかし、私が思ったほど近くはありませんでした。 httplibソースコード(httplib2を拡張)を調べた後、より単純なソリューションが選択され、httplibのプルリクエストが作成されました。
プルリクエストの詳細なレビュー中に、サポートのスタッフとともに、問題はhttplibライブラリとhttplib2ライブラリのジャンクションにあることが判明しました。
- httplibはリクエストを送信し、BODYのファイルを読み取ります。
- httplib2はサーバーへの接続を再確立し、要求を再度送信しますが、ファイルは既に読み取られており、カーソルはファイルの最後にあります。
リクエストを再送信する場合は、ファイルの読み取りを再度開始する必要があります。 犯人を選択して
実行し、予防策を選択することは残っています。 httplibライブラリでは、ファイルを送信するときに、オブジェクトにread()メソッドがある場合、そのオブジェクトを読み取って転送できると想定されています。 同じオブジェクトにtell()およびseek()メソッドがあり、カーソルをファイルの先頭に戻すと仮定することもできます。 もしそうなら、このロジックはまだhttplib2でレンダリングする必要があります。 その結果、httplib2用の
pull-requestが作成されました。 現時点では、見つかった問題には最終的な解決策はありませんが、勝利のフィナーレに持ち込みたいという大きな要望があります。
この投稿がお役に立てば幸いです。 ご清聴ありがとうございました。