如何在 Flask 中设置响应头?

这是我的暗号:

@app.route('/hello', methods=["POST"])
def hello():
resp = make_response(render_template('hello.html'))
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp

但是,当我从浏览器向服务器发出请求时,我会得到这个错误:

XMLHttpRequest cannot load http://localhost:5000/hello.
No 'Access-Control-Allow-Origin' header is present on the requested resource.

我还尝试了这种方法,在请求之后设置响应头:

@app.after_request
def add_header(response):
response.headers['Access-Control-Allow-Origin'] = '*'
return response

没戏。我得到了同样的错误。有没有办法只在路由函数中设置响应头?像这样的事情将是理想的:

@app.route('/hello', methods=["POST"])
def hello(response): # is this a thing??
response.headers['Access-Control-Allow-Origin'] = '*'
return response

但是我找不到任何方法来做这件事,请帮帮我。

剪辑

如果我像这样使用 POST 请求卷曲 URL:

curl -iX POST http://localhost:5000/hello

我得到的回答是:

HTTP/1.0 500 INTERNAL SERVER ERROR
Content-Type: text/html
Content-Length: 291
Server: Werkzeug/0.9.6 Python/2.7.6
Date: Tue, 16 Sep 2014 03:58:42 GMT


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request.  Either the server is overloaded or there is an error in the application.</p>

有什么想法吗?

232683 次浏览

你可以很容易地做到这一点:

@app.route("/")
def home():
resp = flask.Response("Foo bar baz")
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp

看看 酒瓶,请回答Make _ response ()

但是有些东西告诉我你有另一个问题,因为 after_request也应该正确地处理它。

剪辑
我刚刚注意到你已经在使用 make_response了,这是其中一种方法。就像我之前说的,after_request也应该起作用。尝试通过 curl 命中端点,看看头部是什么:

curl -i http://127.0.0.1:5000/your/endpoint

你应该看看

> curl -i 'http://127.0.0.1:5000/'
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 11
Access-Control-Allow-Origin: *
Server: Werkzeug/0.8.3 Python/2.7.5
Date: Tue, 16 Sep 2014 03:47:13 GMT

注意访问控制-允许-起源标头。

编辑2
正如我怀疑的那样,你得到了500分,所以你没有像你想的那样设置头球。在启动应用程序之前尝试添加 app.debug = True,然后再试一次。您应该会得到一些显示问题根源的输出。

例如:

@app.route("/")
def home():
resp = flask.Response("Foo bar baz")
user.weapon = boomerang
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp

提供一个格式很好的 html 错误页面,底部有这个(对 curl 命令很有帮助)

Traceback (most recent call last):
...
File "/private/tmp/min.py", line 8, in home
user.weapon = boomerang
NameError: global name 'boomerang' is not defined

这对我有用

from flask import Flask
from flask import Response


app = Flask(__name__)


@app.route("/")
def home():
return Response(headers={'Access-Control-Allow-Origin':'*'})


if __name__ == "__main__":
app.run()

使用 make_response的烧瓶

@app.route("/")
def home():
resp = make_response("hello") #here you could use make_response(render_template(...)) too
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp

来自 烧瓶医生,

Make _ response (* args)

有时需要在视图中设置其他标题。因为视图不必返回响应对象,但是可以返回一个由 Flask 本身转换成响应对象的值,所以向它添加头部变得很棘手。可以调用这个函数而不是使用返回,您将获得一个响应对象,您可以使用它来附加标题。

这是如何添加我的头在我的烧瓶应用程序,它完美地工作

@app.after_request
def add_header(response):
response.headers['X-Content-Type-Options'] = 'nosniff'
return response

我们可以使用 flask.g在 PythonFlask 应用程序中使用 Flask 应用程序上下文设置响应头

这种在 Flask 应用程序上下文中使用 flask.g设置响应头的方法是线程安全的,可以用来设置来自任何应用程序文件的自定义和动态属性,如果我们正在设置来自任何助手类的自定义/动态响应头,也可以从任何其他文件(比如中间件等)访问,这种 flask.g是全局的,只对该请求线程有效。

假设我想读取从这个应用程序调用的另一个 api/http 调用的响应头,然后解压缩任何 & 设置为这个应用程序的响应头。

示例代码: file: helper.py

import flask
from flask import request, g
from multidict import CIMultiDict
from asyncio import TimeoutError as HttpTimeout
from aiohttp import ClientSession


def _extract_response_header(response)
"""
extracts response headers from response object
and stores that required response header in flask.g app context
"""
headers = CIMultiDict(response.headers)
if 'my_response_header' not in g:
g.my_response_header= {}
g.my_response_header['x-custom-header'] = headers['x-custom-header']




async def call_post_api(post_body):
"""
sample method to make post api call using aiohttp clientsession
"""
try:
async with ClientSession() as session:
async with session.post(uri, headers=_headers, json=post_body) as response:
responseResult = await response.read()
_extract_headers(response, responseResult)
response_text = await response.text()
except (HttpTimeout, ConnectionError) as ex:
raise HttpTimeout(exception_message)

档案: middleware.py

import flask
from flask import request, g


class SimpleMiddleWare(object):
"""
Simple WSGI middleware
"""


def __init__(self, app):
self.app = app
self._header_name = "any_request_header"


def __call__(self, environ, start_response):
"""
middleware to capture request header from incoming http request
"""
request_id_header = environ.get(self._header_name)
environ[self._header_name] = request_id_header


def new_start_response(status, response_headers, exc_info=None):
"""
set custom response headers
"""
# set the request header as response header
response_headers.append((self._header_name, request_id_header))
# this is trying to access flask.g values set in helper class & set that as response header
values = g.get(my_response_header, {})
if values.get('x-custom-header'):
response_headers.append(('x-custom-header', values.get('x-custom-header')))
return start_response(status, response_headers, exc_info)


return self.app(environ, new_start_response)

从主类调用中间件

档案: main.py

from flask import Flask
import asyncio
from gevent.pywsgi import WSGIServer
from middleware import SimpleMiddleWare


app = Flask(__name__)
app.wsgi_app = SimpleMiddleWare(app.wsgi_app)

根据文档 ,您可以从视图函数返回头文件和响应。

如果返回一个元组,元组中的项可以提供额外的 这些元组必须采用 (response, status)格式, 状态值 将覆盖状态代码,标头可以是列表或字典 额外的标头值。

例如:

@app.route('/hello', methods=["POST"])
def hello():
return flask.make_response(), {"Access-Control-Allow-Origin": "*"}

或者:

@app.route('/hello', methods=["POST"])
def hello():
return {"foo": "bar"}, 200, {"Access-Control-Allow-Origin": "*"}