簡體   English   中英

如何在 Flask 中設置響應頭?

[英]How do I set response headers in 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>

有任何想法嗎?

你可以很容易地做到這一點:

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

看看flask.Responseflask.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

使用 Flask 的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 本身轉換為響應對象,因此向其添加標頭變得棘手。 可以調用此函數而不是使用返回值,您將獲得一個可用於附加標頭的響應對象。

這就是在我的 Flask 應用程序中添加我的頭文件的方式,它工作得很好

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

這對我有用

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

我們可以使用 Flask 應用程序上下文使用flask.g在 Python Flask 應用程序中設置響應頭

這種使用flask.g在 Flask 應用程序上下文中設置響應頭的方式是線程安全的,可用於從任何應用程序文件設置自定義和動態屬性,如果我們從任何幫助類設置自定義/動態響應頭,這將特別有用,也可以從任何其他文件(比如中間件等)訪問,這個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)

根據文檔,您可以從視圖函數中與響應一起返回標頭。

如果返回元組,元組中的項目可以提供額外信息。 此類元組必須采用(response, status)(response, headers)(response, status, headers) 狀態值將覆蓋狀態代碼,標題可以是附加標題值的列表或字典。

例如:

@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": "*"}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM