簡體   English   中英

Bottle Py:為jQuery AJAX請求啟用CORS

[英]Bottle Py: Enabling CORS for jQuery AJAX requests

我正在使用Bottle Web Framework上的Web服務的RESTful API,並希望通過jQuery AJAX調用來訪問資源。

使用REST客戶端,資源接口可按預期工作並正確處理GET,POST,...請求。 但是,當發送jQuery AJAX POST請求時,最終的OPTIONS預檢請求被簡單地拒絕為“ 405:不允許使用方法”。

我試圖在Bottle服務器上啟用CORS-如此處所述: http : //bottlepy.org/docs/dev/recipes.html#using-the-hooks-plugin但是after_request鈎子永遠不會為OPTIONS請求調用。

這是我的服務器的摘錄:

from bottle import Bottle, run, request, response
import simplejson as json

app = Bottle()

@app.hook('after_request')
def enable_cors():
    print "after_request hook"
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
    response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'

@app.post('/cors')
def lvambience():
    response.headers['Content-Type'] = 'application/json'
    return "[1]"

[...]

jQuery AJAX調用:

$.ajax({
    type: "POST",
    url: "http://192.168.169.9:8080/cors",
    data: JSON.stringify( data ),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data){
        alert(data);
    },
    failure: function(err) {
        alert(err);
    }
});

服務器僅記錄405錯誤:

192.168.169.3 - - [23/Jun/2013 17:10:53] "OPTIONS /cors HTTP/1.1" 405 741

$ .post確實可以工作,但是不能發送PUT請求會破壞RESTful服務的目的。 那么,如何允許處理OPTIONS飛行前請求?

安裝處理程序而不是掛鈎。

我過去有兩種互補的方式:裝飾器或Bottle插件。 我將向您展示兩者,您可以決定它們中的一個(或兩者)是否滿足您的需求。 在這兩種情況下,通常的想法是:處理程序在將響應發送回客戶端之前先對其進行攔截,然后插入CORS標頭,然后繼續返回響應。

方法1:按路由安裝(裝飾器)

僅在某些路由上運行處理程序時,最好使用此方法。 只需裝飾要執行的每條路線即可。 這是一個例子:

import bottle
from bottle import response

# the decorator
def enable_cors(fn):
    def _enable_cors(*args, **kwargs):
        # set CORS headers
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
        response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'

        if bottle.request.method != 'OPTIONS':
            # actual request; reply with the actual response
            return fn(*args, **kwargs)

    return _enable_cors


app = bottle.app()

@app.route('/cors', method=['OPTIONS', 'GET'])
@enable_cors
def lvambience():
    response.headers['Content-type'] = 'application/json'
    return '[1]'

app.run(port=8001)

方法2:全局安裝(瓶插件)

如果希望處理程序在所有或大多數路由上執行,則最好使用此方法。 您只需定義一次Bottle插件 ,Bottle就會在每條路線上自動為您調用; 無需在每一個上指定一個裝飾器。 (請注意,您可以使用路由的skip參數來避免針對每個路由使用此處理程序。)以下示例與上述示例相對應:

import bottle
from bottle import response

class EnableCors(object):
    name = 'enable_cors'
    api = 2

    def apply(self, fn, context):
        def _enable_cors(*args, **kwargs):
            # set CORS headers
            response.headers['Access-Control-Allow-Origin'] = '*'
            response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
            response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'

            if bottle.request.method != 'OPTIONS':
                # actual request; reply with the actual response
                return fn(*args, **kwargs)

        return _enable_cors


app = bottle.app()

@app.route('/cors', method=['OPTIONS', 'GET'])
def lvambience():
    response.headers['Content-type'] = 'application/json'
    return '[1]'

app.install(EnableCors())

app.run(port=8001)

這是@ ron.rothman的方法2(用於全局安裝CORS處理程序)的一個小改進。 他的方法要求您指定在聲明的每條路線上都接受OPTIONS方法。 此解決方案為所有OPTIONS請求安裝一個全局處理程序。

@bottle.route('/<:re:.*>', method='OPTIONS')
def enable_cors_generic_route():
    """
    This route takes priority over all others. So any request with an OPTIONS
    method will be handled by this function.

    See: https://github.com/bottlepy/bottle/issues/402

    NOTE: This means we won't 404 any invalid path that is an OPTIONS request.
    """
    add_cors_headers()

@bottle.hook('after_request')
def enable_cors_after_request_hook():
    """
    This executes after every route. We use it to attach CORS headers when
    applicable.
    """
    add_cors_headers()

def add_cors_headers():
    if SOME_CONDITION:  # You don't have to gate this
        bottle.response.headers['Access-Control-Allow-Origin'] = '*'
        bottle.response.headers['Access-Control-Allow-Methods'] = \
            'GET, POST, PUT, OPTIONS'
        bottle.response.headers['Access-Control-Allow-Headers'] = \
            'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'

```

考慮讓您的Web服務器(而不是Bottle)設置標題。

不確定這是否適用於您的情況,但是我已經通過在Apache中為我的Bottle應用程序設置CORS標頭解決了過去項目中的問題。 它易於配置,使我的Python代碼保持整潔,高效。

信息可從許多來源獲得 ,但是如果您使用的是Apache,則這是我的配置(或多或少):

<Location "/cors">
    Header set Access-Control-Allow-Headers "Origin, Content-Type"
    Header set Access-Control-Allow-Methods "POST, GET, OPTIONS"
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Request-Headers "Origin, Content-Type"
</Location>

您還不應該使用這個嗎?

response.set_header('Access-Control-Allow-Origin', '*')
response.add_header('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS')

暫無
暫無

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

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