Flask'ta yanıt başlıklarını nasıl ayarlayabilirim?


106

Bu benim kodum:

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

Ancak, tarayıcıdan sunucuma bir istekte bulunduğumda şu hatayı alıyorum:

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

Bu yaklaşımı da istekten "sonra" yanıt başlıklarını ayarlayarak denedim:

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

Nafile. Ben de aynı hatayı alıyorum. Rota işlevinde yanıt başlıklarını ayarlamanın bir yolu var mı? Bunun gibi bir şey ideal olacaktır:

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

ama bunu yapacak bir yol bulamıyorum. Lütfen yardım et.

DÜZENLE

URL'yi şöyle bir POST isteği ile kıvırırsam:

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

Bu yanıtı alıyorum:

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>

Herhangi bir fikir?

Yanıtlar:


102

Bunu oldukça kolay bir şekilde yapabilirsiniz:

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

Bak flask.Response ve ) (flask.make_response

Ama bir şey bana senin başka bir sorunun olduğunu söylüyor, çünkü after_requestonu da doğru şekilde çözmeliydin.

DÜZENLE
Sadece make_responsebunu yapmanın yollarından biri olan zaten kullandığınızı fark ettim . Daha önce de söylediğim after_requestgibi, işe yaramalıydı. Uç noktayı curl ile vurmayı deneyin ve başlıkların ne olduğunu görün:

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

Görmelisin

> 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 başlığına dikkat edin.

DÜZENLEME 2
Şüphelendiğim gibi, 500 alıyorsunuz, bu yüzden başlığı düşündüğünüz gibi ayarlamıyorsunuz. app.debug = TrueUygulamayı başlatmadan önce eklemeyi deneyin ve tekrar deneyin. Sorunun temel nedenini gösteren bazı çıktılar almalısınız.

Örneğin:

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

En alttaki güzel biçimlendirilmiş bir html hata sayfası verir (curl komutu için yararlıdır)

Traceback (most recent call last):
...
  File "/private/tmp/min.py", line 8, in home
    user.weapon = boomerang
NameError: global name 'boomerang' is not defined

27

make_responseFlask kullanımı gibi bir şey

@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

Cep şişesi belgelerinden ,

flask.make_response (* args)

Bazen bir görünümde ek başlıklar ayarlamak gerekir. Görünümlerin yanıt nesneleri döndürmesi gerekmediğinden, ancak Flask'ın kendisi tarafından bir yanıt nesnesine dönüştürülen bir değer döndürebildiğinden, ona başlık eklemek zorlaşır. Bu işlev bir dönüş kullanmak yerine çağrılabilir ve başlık eklemek için kullanabileceğiniz bir yanıt nesnesi alırsınız.


İstekleri args içinde gönderebilirsiniz: flask.pocoo.org/docs/0.10/api/#flask.Flask.make_response
tokland

6

Bu benim için çalışıyor

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':'*'})Bana daha temiz görünen notasyon da var.
Hermann

5

Bu, başlıklarımı şişe uygulamama nasıl ekledi ve mükemmel çalıştı

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

0

Python Flask uygulamasında yanıt başlıklarını Flask uygulama bağlamını kullanarak ayarlayabiliriz. flask.g

Kullanarak Flask uygulama bağlamında yanıt başlıklarını ayarlamanın bu yolu flask.giş parçacığı açısından güvenlidir ve herhangi bir uygulama dosyasından özel ve dinamik öznitelikleri ayarlamak için kullanılabilir; bu, özellikle herhangi bir yardımcı sınıftan özel / dinamik yanıt başlıkları ayarlıyorsak yararlıdır ayrıca başka bir dosyadan da erişilebilir (örneğin ara yazılım vb.), bu flask.ggeneldir ve yalnızca bu istek iş parçacığı için geçerlidir.

Yanıt başlığını bu uygulamadan çağrılan başka bir api / http çağrısından okumak ve ardından herhangi birini ayıklamak ve bu uygulama için yanıt başlıkları olarak ayarlamak isteyip istemediğimi söyleyin.

Örnek Kod: dosya: 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)

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

Ara yazılımın ana sınıftan çağrılması

dosya : 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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.