简体   繁体   English

@use_kwargs 更改响应内容

[英]@use_kwargs changes response content

I notice that @use_kwargs in flask-apispec changes the response content-type.我注意到flask-apispec @use_kwargs了响应内容类型。 In the following "hello world" example, The use of @use_kwargs changes the response content-type from text/html to application/json .在以下“hello world”示例中, @use_kwargs的使用将响应内容类型从text/html更改为application/json I find it a bit surprising since the flask-apispec doc doesn't mention it and I wouldn't expect injecting args also changes the response type:我觉得这有点令人惊讶,因为flask-apispec 文档没有提到它,而且我不希望注入 args 也会改变响应类型:

from flask import Flask
from flask_apispec import use_kwargs
from marshmallow import fields

app = Flask(__name__)

@app.route('/')
@use_kwargs({'email': fields.Str()}, location="query")
def hello_world(**kwargs):
    return 'Hello, World!

curl -v http://127.0.0.1:5000/\?email\=abc shows the response curl -v http://127.0.0.1:5000/\?email\=abc显示响应

> GET /?email=abc HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.64.1
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 16
< Server: Werkzeug/1.0.1 Python/3.8.2
< Date: Tue, 12 Jan 2021 06:09:25 GMT
<
"Hello, World!"

Note that the Content-Type: application/json and value hello world is quoted.注意Content-Type: application/json和 value hello world被引用了。 However, without the line of @use_kwargs , the response is of Content-Type: text/html and the content hello world is not quoted:但是,如果没有@use_kwargs行,则响应是Content-Type: text/html并且内容hello world没有被引用:

~ curl -v http://127.0.0.1:5000/\?email\=abc
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> GET /?email=abc HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.64.1
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 13
< Server: Werkzeug/1.0.1 Python/3.8.2
< Date: Tue, 12 Jan 2021 06:09:42 GMT
<
* Closing connection 0
Hello, World!%

What is the rationale of changing the response?改变响应的基本原理是什么? How can I set the response content type of "text/html" even with the use of @use_kwargs ?即使使用@use_kwargs ,如何设置“text/html”的响应内容类型? Thank you !谢谢 !

Update:更新:

Just add a bit more details on the answer given by @Diego Miguel: The effect of changing content is caused by the logic in Wrapper.只需在@Diego Miguel 给出的答案上添加更多细节:更改内容的效果是由Wrapper 中的逻辑引起的。 call 称呼

    def __call__(self, *args, **kwargs):
        response = self.call_view(*args, **kwargs)
        if isinstance(response, werkzeug.Response):
            return response
        rv, status_code, headers = unpack(response)
        mv = self.marshal_result(rv, status_code)
        response = packed(mv, status_code, headers)
        return flask.current_app.make_response(response)

marshal_result calls flask.jsonify which makes a Response object with "application/json" mimetype and also introduces an extra level of quotation of the "hello world" example above. marshal_result调用flask.jsonify ,它使用“application/json”mimetype 生成 响应object 并且还引入了上面“hello world”示例的额外引用级别。

I'm not entirely sure why using @use_kwargs changes the content-type.我不完全确定为什么使用@use_kwargs会改变内容类型。 By looking at the source code , it seems to return a dict , judging by this function (that is called by activate ).通过查看源代码,它似乎返回了一个dict ,由这个function (由activate调用)判断。 So my best guess is that Flask when executing app.route jsonifys that dict , as that the default behaviour .所以我最好的猜测是 Flask 在执行app.route时会 jsonify 那个dict ,因为这是 默认行为 At that point, the content-type is changed to application/json .此时, content-type更改为application/json However, hello_world is executed after use_kwargs , finally returning a string, that is, "Hello World.".但是hello_worlduse_kwargs之后执行,最后返回一个字符串,即“Hello World.”。

In any case, I don't think this behaviour is actually intended by flask-apispec .无论如何,我认为这种行为实际上并不是flask-apispec

You can change the content-type of your response (and any other field), creating a Flask.Response object with make_reponse and then setting its content-type to "text/html" (however, this is set by default when passing a string to make_response so it's not necessary):您可以更改响应的content-type (和任何其他字段),使用 make_reponse 创建Flask.Response make_reponse ,然后将其content-type设置为"text/html" (但是,这是在传递字符串时默认设置的make_response所以没有必要):

from flask import Flask, make_response
from flask_apispec import use_kwargs
from marshmallow import fields

app = Flask(__name__)

@app.route('/')
@use_kwargs({'email': fields.Str()}, location="query")
def hello_world(**kwargs):
    response = make_response("Hello World!")
    response.content_type = 'text/html'  # can be omitted
    return response

Output of curl -v http://127.0.0.1:5000/\?email\=abc : Output 的curl -v http://127.0.0.1:5000/\?email\=abc

> GET /?email=abc HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html
< Content-Length: 13
< Server: Werkzeug/1.0.1 Python/3.9.1
< Date: Tue, 12 Jan 2021 19:08:05 GMT
< 
Hello World!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法使用带有 webargs use_kwargs 的棉花糖架构验证字典列表 - 错误 422 无法处理的实体 - Unable to validate list of dicts using marshmallow Schema with webargs use_kwargs - Error 422 Unprocessable Entity OpenAPI 3 python-flask:如何在响应中使用多种内容类型 - OpenAPI 3 python-flask: how to use multiple content types in response 使用flask-mongoengine字段kwarg的正确方法是什么? - What is the correct way to use flask-mongoengine field kwargs? 如何在Flask的url_for方法中使用kwargs - How to use kwargs in Flask's url_for method Flask Sql-Alchemy - 有没有办法在 order_by 方法中使用 **kwargs 或 *args? [等候接听] - Flask Sql-Alchemy - is there a way to use **kwargs or *args in the order_by method? [on hold] 根据 Flask 中请求的内容类型更改响应 - Change response based on content type of request in Flask mongoengine无法使用集合作为回应 - mongoengine cannot use collection in response 这个包装器 function 中的 **kwargs 有什么好处? - What is the benefit of **kwargs in this wrapper function? 测试服务器的响应,当响应在文件和 json 之间变化时 - Testing response of server, when the response changes between file and json 使用HTTP响应标头中的Content-Length在Flask中提供静态文件 - Serving static files in Flask with Content-Length in HTTP response header
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM