Как установить заголовки ответов в Flask?

Это мой код:

@app.route('/hello', methods=["POST"])
def hello():
    resp = make_response()
    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

но я все равно не могу это сделать. Пожалуйста, помогите.

ИЗМЕНИТЬ

если я скручиваю URL с запросом POST следующим образом:

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>

Любые идеи?

Ответы

Ответ 1

Вы можете сделать это довольно легко:

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

Посмотрите flask.Response и flask.make_response()

Но что-то говорит мне, что у вас есть другая проблема, потому что after_request тоже должен был правильно ее обработать.

ИЗМЕНИТЬ
Я просто заметил, что вы уже используете make_response, который является одним из способов сделать это. Как я уже говорил, after_request тоже должен был работать. Попробуйте нажать конечную точку через завиток и посмотреть, что представляют собой заголовки:

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

Отмечаем заголовок Access-Control-Allow-Origin.

РЕДАКТИРОВАТЬ 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

Ответ 2

Используйте 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

Из флеш-документы,

flask.make_response (* args)

Иногда в представлении необходимо установить дополнительные заголовки. Поскольку представлениям не нужно возвращать объекты ответа, но они могут возвращать значение, которое преобразуется в объект ответа самим фляксом, становится сложным добавлять к нему заголовки. Эта функция может быть вызвана вместо использования возврата, и вы получите объект ответа, который вы можете использовать для прикрепления заголовков.

Ответ 3

Эта работа для меня

from flask import Flask
from flask import Response

app = Flask(__name__)

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

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