Werkzeugでは werkzeug.wrappers.Response
を使ってレスポンスオブジェクトを生成する際、 Response('Hello world')
のようにコンストラクタの引数にレスポンスボディを渡します。
ただ、Responseオブジェクト生成後にレスポンスボディを修正する方法を知りたかったため、いろいろ試した時のメモです。
目次
環境
- Python 3.6.6
- Werkzeug 0.14.1
コンストラクタでレスポンスボディを指定
以下のWerkzeugアプリの中の index_handler()
メソッドにて、コンストラクタでレスポンスボディを指定しています。
ルーティングにいろいろと書かれていますが、後から追加しますので、今は置いておきます。
from werkzeug.exceptions import HTTPException from werkzeug.routing import Map, Rule from werkzeug.wrappers import Request, Response class Application: def __init__(self): self.url_map = Map([ Rule('/', endpoint='index', methods=['GET']), Rule('/response', endpoint='response', methods=['GET']), Rule('/data', endpoint='data', methods=['GET']), Rule('/set_data', endpoint='set_data', methods=['GET']), ]) def dispatch_request(self, request): adapter = self.url_map.bind_to_environ(request.environ) try: endpoint, values = adapter.match() return getattr(self, f'{endpoint}_handler')(request, **values) except HTTPException as e: return e def index_handler(self, request): return Response('Hello world') def wsgi_app(self, environ, start_response): request = Request(environ) response = self.dispatch_request(request) return response(environ, start_response) def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response) if __name__ == '__main__': from werkzeug.serving import run_simple app = Application() run_simple('0.0.0.0', 5000, app, use_debugger=True, use_reloader=True)
起動して localhost:5000/
にcurlでアクセスすると
$ curl --include http://localhost:5000/ HTTP/1.0 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 12 Server: Werkzeug/0.14.1 Python/3.6.6 Date: Mon, 15 Oct 2018 13:19:56 GMT Hello world
Hello worldが返ってきます。
response属性で差し替えるのはNG
Werkzeugのドキュメントを見ると response
属性があります。
http://werkzeug.pocoo.org/docs/0.14/wrappers/#werkzeug.wrappers.BaseResponse.response
これを
def response_handler(self, request): response = Response('Hello world\n') response.response = 'update response body\n' return response
のようにして使えば、一見レスポンスを差し替えられそうです。
ただ、実際には
$ curl --include http://localhost:5000/response HTTP/1.0 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 12 Server: Werkzeug/0.14.1 Python/3.6.6 Date: Mon, 15 Oct 2018 13:22:44 GMT update respo
と、Content-LengthヘッダがHello worldの時に計算した時のままなため、レスポンスボディが欠けています。
また、サーバのログを見ると
Warning: response iterable was set to a string. This appears to work but means that the server will send the data to the client char, by char. This is almost never intended behavior, use response.data to assign strings to the response object. _warn_if_string(self.response)
が残されており、response属性を使うのはダメそうです。
dataプロパティも不適切
次に、エラーメッセージにある data
プロパティを使ってみます。
def data_handler(self, request): response = Response('Hello world\n') response.data = 'update response body\n' return response
curlでアクセスしてみます。
$ curl --include http://localhost:5000/data HTTP/1.0 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 21 Server: Werkzeug/0.14.1 Python/3.6.6 Date: Mon, 15 Oct 2018 13:25:52 GMT update response body
Content-Lengthが再計算され、レスポンスボディの欠けもありません。
また、サーバのログにも先ほどのエラーは出力されていません。
ただ、ドキュメントを見ると、
A descriptor that calls get_data() and set_data(). This should not be used and will eventually get deprecated.
http://werkzeug.pocoo.org/docs/0.14/wrappers/#werkzeug.wrappers.BaseResponse.data
とあるため、dataプロパティを使うのもよくなさそうです。
set_data() メソッドを使うのが良さそう
最後に set_data()
メソッドを使います。
ドキュメントにも
Sets a new string as response. The value set must either by a unicode or bytestring. If a unicode string is set it’s encoded automatically to the charset of the response (utf-8 by default).
http://werkzeug.pocoo.org/docs/0.14/wrappers/#werkzeug.wrappers.BaseResponse.set_data
と書かれており、これを使うのが良さそうです。
def set_data_handler(self, request): response = Response('Hello world\n') response.set_data('update response body\n') return response
と実装します。
curlでアクセスしてみます。
$ curl --include http://localhost:5000/set_data HTTP/1.0 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 21 Server: Werkzeug/0.14.1 Python/3.6.6 Date: Mon, 15 Oct 2018 13:30:48 GMT update response body
とレスポンスが返り、サーバのログにもエラーが出ていませんでした。
ソースコード
GitHubに上げました。 response_body
ディレクトリ以下が今回のコードです。
werkzeug-sample/response_body at master · thinkAmi-sandbox/werkzeug-sample