LoginSignup
1
0

More than 3 years have passed since last update.

requests を GAE python2.7 で使うと IncompleteRead でこける話

Last updated at Posted at 2019-06-17

謎の ChunkedEngcodingError

Google App Engine Standard Environment (Python 2.7) で line_bot_sdk を使って LINE Bot を動かしていると、ときどき以下のような例外を吐きます。

ChunkedEncodingError: ('Connection broken: IncompleteRead(2 bytes read)', IncompleteRead(2 bytes read))

返答を投げ終わった後のレスポンスのパースで落ちているため、メッセージ送信自体は正常に完了しているので、無視しても良いのですが、どうにも気持ち悪いので、原因を調査してみました。

原因

  • GAE では httplib が urlfetch で再実装されている。
  • line_bot_sdk が使っている requests が使っている urllib3 には、下位層が httplib のインスタンスだったときだけ http の chunked encoding を自前で解決するコードが含まれている。
  • しかし、urlfetch で再実装された GAE の httplib は chunked encoding を自前でデコードしてしまう。
  • urllib3 で chunked encoding を二重にデコードしようとして例外が発生する。

エラーの中身

IncompleteRead(2 bytes read) と出ている中身をデバッグ出力してみたところ、 '{}' でした。
LINE Messaging API のサーバは、普段は chunked encoding を使わないのですが、まれに chunked encoding で返信を返してくるようで、その時だけエラーが発生していたようです。
複数端末から同時アクセス発生時にのみ起こる気がしますので、複数リクエストが被ってコネクションをkeepaliveで使いまわした時だけとか、そういう話な気がしてますが、そこまでは追っていません。

解決方法

類似した内容をディスカッションしている urllib3 の issue では、以下のパッチが提案されています。

urllib3 の問題なのに requests のレイヤで対応しているのが微妙に気持ち悪いですが、とりあえず同じパッチを当てれば、chunked encoding の問題は発生しなくなります。

(本質的には、urllib3/response.py で self.raw の httplib の中身が GAE 版だと判別できたら self.chunked を True にしないというのが正しい対処のはずです)

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0