codememo

Bottle Py: jQuery AJAX 요청에 대한 CORS 활성화

tipmemo 2023. 8. 1. 20:33
반응형

Bottle Py: jQuery AJAX 요청에 대한 CORS 활성화

Bottle Web Framework에서 웹 서비스의 RESTful API를 작업하고 있으며 jQuery AJAX 호출로 리소스에 액세스하고 싶습니다.

REST 클라이언트를 사용하면 리소스 인터페이스가 의도한 대로 작동하고 GET, POST, ... 요청을 적절하게 처리합니다.그러나 jQuery AJAX POST 요청을 보낼 때 결과 OPTIONS 사전 비행 요청은 '405: Method not allowed'로 거부됩니다.

http://bottlepy.org/docs/dev/recipes.html#using-the-hooks-plugin 에서 설명한 것처럼 Bottle 서버에서 CORS를 활성화하려고 했지만 OPTIONS 요청에 대해 after_request 후크가 호출되지 않습니다.

다음은 제 서버의 발췌본입니다.

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 사전 비행 요청이 처리되도록 하려면 어떻게 해야 합니까?

후크 대신 핸들러를 설치합니다.

제가 과거에 이것을 보완하는 두 가지 방법이 있습니다: 데코레이터 또는 보틀 플러그인.둘 다 보여드릴 테니 둘 중 하나(또는 둘 다)가 귀하의 요구에 적합한지 결정하시면 됩니다.두 경우 모두 일반적인 개념은 핸들러가 응답을 클라이언트로 다시 전송하기 전에 가로채서 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)

다음은 CORS 핸들러를 전체적으로 설치하기 위한 on @ron.ro thman의 방법 #2의 사소한 개선 사항입니다.그의 방법은 당신이 그것을 지정하도록 요구합니다.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'

```

그리고 당신은 실제로 이것을 사용해야 하지 않나요?

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

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>

언급URL : https://stackoverflow.com/questions/17262170/bottle-py-enabling-cors-for-jquery-ajax-requests

반응형