ฉันจะตั้งค่าส่วนหัวการตอบกลับใน Flask ได้อย่างไร?


109

นี่คือรหัสของฉัน:

@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>

ความคิดใด ๆ ?

คำตอบ:


103

คุณสามารถทำได้อย่างง่ายดาย:

@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

การสังเกตส่วนหัว 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

28

การใช้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)

บางครั้งจำเป็นต้องตั้งค่าส่วนหัวเพิ่มเติมในมุมมอง เนื่องจากมุมมองไม่จำเป็นต้องส่งคืนอ็อบเจ็กต์การตอบสนอง แต่สามารถส่งคืนค่าที่ถูกแปลงเป็นอ็อบเจ็กต์การตอบสนองโดย Flask เองจึงเป็นเรื่องยุ่งยากที่จะเพิ่มส่วนหัวเข้าไป สามารถเรียกใช้ฟังก์ชันนี้แทนการใช้ return และคุณจะได้รับวัตถุตอบกลับซึ่งคุณสามารถใช้เพื่อแนบส่วนหัวได้


คุณสามารถส่งคำขอใน args: flask.pocoo.org/docs/0.10/api/#flask.Flask.make_response
tokland

7

นี่คือวิธีที่เพิ่มส่วนหัวของฉันในแอปพลิเคชันขวดของฉันและทำงานได้อย่างสมบูรณ์แบบ

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

6

งานนี้สำหรับฉัน

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

3
นอกจากนี้ยังมีสัญกรณ์return Response(headers={'Access-Control-Allow-Origin':'*'})ที่ดูสะอาดกว่าสำหรับฉัน
Hermann

0

เราสามารถตั้งค่าส่วนหัวการตอบสนองในแอปพลิเคชัน Python Flask โดยใช้บริบทแอปพลิเคชัน Flask โดยใช้ flask.g

วิธีการตั้งค่าส่วนหัวการตอบสนองในบริบทแอปพลิเคชัน Flask โดยใช้flask.gเธรดปลอดภัยและสามารถใช้เพื่อตั้งค่าแอตทริบิวต์แบบกำหนดเองและไดนามิกจากไฟล์แอปพลิเคชันใด ๆ ซึ่งจะมีประโยชน์อย่างยิ่งหากเราตั้งค่าส่วนหัวการตอบสนองแบบกำหนดเอง / ไดนามิกจากคลาสตัวช่วยใด ๆ ที่สามารถ นอกจากนี้ยังสามารถเข้าถึงได้จากไฟล์อื่น ๆ (เช่นมิดเดิลแวร์ ฯลฯ ) ซึ่งflask.gเป็นแบบโกลบอลและใช้ได้สำหรับเธรดคำขอนั้นเท่านั้น

สมมติว่าฉันต้องการอ่านส่วนหัวการตอบกลับจากการเรียก api / http อื่นที่ถูกเรียกจากแอปนี้หรือไม่จากนั้นแยกข้อมูลใด ๆ และตั้งเป็นส่วนหัวการตอบกลับสำหรับแอปนี้

รหัสตัวอย่าง: ไฟล์: 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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.