備忘録:pythonマルチスレッド pasteサーバ redirectでエラー発生の場合の対処
python bottleフレームワークでは内部のマルチスレッドhttpサーバでpasteサーバが使われるケースが多い。しかし、redirect処理を行った際にエラーが吐かれてしまうという問題に遭遇しました。処理自体は問題なく動作するのですがやはり気になります。この問題を解決するためにpasteサーバ関連で呼び出されるライブラリーのコードをトレースして原因がわかりました。この記事はその備忘録として残します。
実際に起きてるエラーはこんな感じ。
そもそも20行目の「TypeError: a bytes-like object is required, not ‘str’」これが勘違いのもとだった。よくある関数returnでHTMLテンプレートに返す際にencodeやdecode処理でutf-8に変換しないと駄目な場合があります。これが抜けているのかな!?と思いきや全く違うところに問題があった。
pasteサーバでredirect処理した場合に発生するエラー出力結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Traceback (most recent call last): File "/usr/local/lib/python3.5/site-packages/paste/httpserver.py", line 1085, in process_request_in_thread self.finish_request(request, client_address) File "/usr/local/lib/python3.5/socketserver.py", line 354, in finish_request self.RequestHandlerClass(request, client_address, self) File "/usr/local/lib/python3.5/socketserver.py", line 681, in __init__ self.handle() File "/usr/local/lib/python3.5/site-packages/paste/httpserver.py", line 459, in handle BaseHTTPRequestHandler.handle(self) File "/usr/local/lib/python3.5/http/server.py", line 422, in handle self.handle_one_request() File "/usr/local/lib/python3.5/site-packages/paste/httpserver.py", line 454, in handle_one_request self.wsgi_execute() File "/usr/local/lib/python3.5/site-packages/paste/httpserver.py", line 309, in wsgi_execute self.wsgi_write_chunk('') File "/usr/local/lib/python3.5/site-packages/paste/httpserver.py", line 167, in wsgi_write_chunk self.wfile.write(chunk) File "/usr/local/lib/python3.5/socket.py", line 593, in write return self._sock.send(b) TypeError: a bytes-like object is required, not 'str' |
python3になってからstringsは文字コードの扱いがUnicodeに変わりました。しかしネットワーク上での通信はbyte stringになる必要があり、よく使われるライブラリーではこのUnicodeへの対応がきっちり済んでいるため問題が生じるケースが少ないのですが稀にpython2.x時代からpython3ソースコード対応が中途半端なものがあります。つまり移行が完全にできていないケースだったようです。幸いにも原因は15行目のこれ「self.wsgi_write_chunk(”)」が原因であることにすぐに気がつけた。つまりhttpプロトコルのメッセージヘッダ項目やメッセージボディが空っぽの場合にきちんと処理ができなくて20行目のエラーになってしまうというものです。
まとめると、redirectの処理はメッセージヘッダの一部項目が空であるため、ライブラリーが誤って20行目のエラーを吐き出してしまう。これを回避するためにredirectへ具体的なレスポンスコードを指定してあげることでメッセージヘッダ項目が空になることを防ぐ。
リダイレクト レスポンスコード
- 301 Moved Permanently
- 302 Found(Moved Temporary
- 303 See Other
- 307 Temporary Redirect
redirectの際にレスポンスコード301を入れて空になるのを防いだところエラーが消えた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from bottle import Bottle,template,request,redirect from paste import debug,httpserver as web app = Bottle() @app.route('/test') def index(): return "hello in the world!" @app.route('/') def index(): redirect('/test',301) #redirect('/test') <----これだと上記の20行目のエラーがでる web.serve(app, host='0.0.0.0', port=8080) |