Làm cách nào để đặt tiêu đề phản hồi trong Flask?


98

Đây là mã của tôi:

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

Tuy nhiên, khi tôi thực hiện yêu cầu từ trình duyệt tới máy chủ của mình, tôi gặp lỗi này:

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

Tôi cũng đã thử cách tiếp cận này, đặt tiêu đề phản hồi "sau" yêu cầu:

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

Không có con xúc xắc. Tôi nhận được lỗi tương tự. Có cách nào để chỉ đặt tiêu đề phản hồi trong hàm định tuyến không? Một cái gì đó như thế này sẽ là lý tưởng:

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

nhưng tôi không thể tìm thấy anyway để làm điều này. Xin vui lòng giúp đỡ.

BIÊN TẬP

nếu tôi cuộn url với yêu cầu ĐĂNG như vậy:

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

Tôi nhận được phản hồi này:

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>

Bất kỳ ý tưởng?

Câu trả lời:


96

Bạn có thể làm điều này khá dễ dàng:

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

Nhìn vào flask.Responseflask.make_response ()

Nhưng một cái gì đó cho tôi biết bạn có một vấn đề khác, bởi vì after_requestlẽ ra phải xử lý nó một cách chính xác.

CHỈNH SỬA
Tôi chỉ nhận thấy rằng bạn đã sử dụng make_responseđó là một trong những cách để làm điều đó. Như tôi đã nói trước đây, after_requestlẽ ra cũng phải hoạt động. Hãy thử đánh điểm cuối qua cuộn tròn và xem tiêu đề là gì:

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

Bạn nên thấy

> 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

Ghi nhận tiêu đề Access-Control-Allow-Origin.

CHỈNH SỬA 2
Như tôi đã nghi ngờ, bạn đang nhận được 500 nên bạn không đặt tiêu đề như bạn nghĩ. Hãy thử thêm app.debug = Truetrước khi bạn khởi động ứng dụng và thử lại. Bạn sẽ nhận được một số kết quả hiển thị cho bạn nguyên nhân gốc rễ của vấn đề.

Ví dụ:

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

Cung cấp trang lỗi html được định dạng độc đáo, với trang này ở cuối (hữu ích cho lệnh 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

24

Sử dụng make_responseFlask một cái gì đó như

@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

Từ tài liệu bình ,

flask.make_response (* args)

Đôi khi cần phải đặt các tiêu đề bổ sung trong một chế độ xem. Bởi vì các khung nhìn không phải trả về các đối tượng phản hồi nhưng có thể trả về một giá trị được chính Flask chuyển đổi thành một đối tượng phản hồi, nên việc thêm tiêu đề vào nó sẽ trở nên khó khăn. Hàm này có thể được gọi thay vì sử dụng trả về và bạn sẽ nhận được một đối tượng phản hồi mà bạn có thể sử dụng để đính kèm tiêu đề.


Bạn có thể gửi yêu cầu trong args: flask.pocoo.org/docs/0.10/api/#flask.Flask.make_response
tokland

5

Công việc này cho tôi

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()

2
Ngoài ra còn có ký hiệu return Response(headers={'Access-Control-Allow-Origin':'*'})trông sạch hơn đối với tôi.
Hermann

4

Đây là cách thêm tiêu đề của tôi vào ứng dụng bình của tôi và nó hoạt động hoàn hảo

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

0

Chúng ta có thể đặt tiêu đề phản hồi trong ứng dụng Python Flask bằng ngữ cảnh ứng dụng Flask bằng flask.g

Cách đặt tiêu đề phản hồi trong ngữ cảnh ứng dụng Flask flask.gnày là an toàn cho chuỗi và có thể được sử dụng để đặt các thuộc tính tùy chỉnh & động từ bất kỳ tệp ứng dụng nào, điều này đặc biệt hữu ích nếu chúng tôi đang đặt tiêu đề phản hồi tùy chỉnh / động từ bất kỳ lớp trợ giúp nào, điều đó có thể cũng được truy cập từ bất kỳ tệp nào khác (chẳng hạn như phần mềm trung gian, v.v.), tệp này flask.glà toàn cầu và chỉ hợp lệ cho chuỗi yêu cầu đó.

Giả sử tôi muốn đọc tiêu đề phản hồi từ một lệnh gọi api / http khác đang được gọi từ ứng dụng này, sau đó trích xuất bất kỳ & đặt nó làm tiêu đề phản hồi cho ứng dụng này.

Mã mẫu: tệp: 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)

tập tin: 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)

Gọi phần mềm trung gian từ lớp chính

tập tin : 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.