Bagaimana cara mengatur header respon di Flask?


103

Ini kode saya:

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

Namun, ketika saya membuat permintaan dari browser ke server saya, saya mendapatkan kesalahan ini:

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

Saya juga mencoba pendekatan ini, menyetel header tanggapan "setelah" permintaan:

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

Tidak ada dadu. Saya mendapatkan kesalahan yang sama. Adakah cara untuk menyetel header respons di fungsi rute? Sesuatu seperti ini akan ideal:

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

tetapi saya tidak dapat menemukan cara untuk melakukan ini. Tolong bantu.

EDIT

jika saya menggulung url dengan permintaan POST seperti ini:

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

Saya mendapatkan tanggapan ini:

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>

Ada ide?

Jawaban:


98

Anda dapat melakukan ini dengan mudah:

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

Lihat flask.Response dan flask.make_response ()

Tetapi sesuatu memberitahu saya bahwa Anda memiliki masalah lain, karena after_requestseharusnya menanganinya dengan benar juga.

EDIT
Saya baru saja melihat Anda sudah menggunakan make_responseyang merupakan salah satu cara untuk melakukannya. Seperti yang saya katakan sebelumnya, after_requestseharusnya berhasil juga. Cobalah mencapai titik akhir melalui curl dan lihat apa tajuknya:

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

Kamu harus lihat

> 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

Memperhatikan header Access-Control-Allow-Origin.

EDIT 2
Seperti yang saya duga, Anda mendapatkan 500 sehingga Anda tidak mengatur header seperti yang Anda duga. Coba tambahkan app.debug = Truesebelum Anda memulai aplikasi dan coba lagi. Anda harus mendapatkan beberapa keluaran yang menunjukkan kepada Anda akar penyebab masalahnya.

Sebagai contoh:

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

Memberikan halaman kesalahan html yang diformat dengan baik, dengan ini di bagian bawah (membantu untuk perintah 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

25

Penggunaan make_responseFlask seperti itu

@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

Dari flask docs ,

flask.make_response (* args)

Terkadang perlu untuk mengatur header tambahan dalam sebuah tampilan. Karena tampilan tidak harus mengembalikan objek respons tetapi bisa mengembalikan nilai yang diubah menjadi objek respons oleh Flask itu sendiri, maka menjadi sulit untuk menambahkan header ke dalamnya. Fungsi ini dapat dipanggil daripada menggunakan kembali dan Anda akan mendapatkan objek respons yang dapat Anda gunakan untuk melampirkan header.


Anda dapat mengirim permintaan di args: flask.pocoo.org/docs/0.10/api/#flask.Flask.make_response
tokland

5

Ini bekerja untuk saya

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
Ada juga notasi return Response(headers={'Access-Control-Allow-Origin':'*'})yang menurut saya lebih bersih.
Hermann

4

Beginilah cara menambahkan header saya di aplikasi labu saya dan itu bekerja dengan sempurna

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

0

Kita dapat mengatur header respon dalam aplikasi Python Flask menggunakan konteks aplikasi Flask menggunakan flask.g

Cara menyetel header respons dalam konteks aplikasi Flask menggunakan flask.gthread safe dan dapat digunakan untuk menyetel atribut kustom & dinamis dari file aplikasi mana pun, ini sangat membantu jika kita menyetel header respons kustom / dinamis dari kelas helper mana pun, yang dapat juga dapat diakses dari file lain (katakanlah seperti middleware, dll), ini flask.gbersifat global & valid untuk utas permintaan itu saja.

Katakanlah jika saya ingin membaca header respons dari panggilan api / http lain yang dipanggil dari aplikasi ini, lalu ekstrak apa pun & setel sebagai header respons untuk aplikasi ini.

Kode Sampel: 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)

mengajukan: 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)

Memanggil middleware dari kelas utama

file: 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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.