3

私はフラスコ レストフルで REST API を構築しています。有効にしたいことの 1 つは、Facebook グラフ API のしくみと同様に、リクエスト リソースをバッチ処理する機能です。

curl \
    -F 'access_token=…' \
    -F 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/friends?limit=50"}]' \
    https://graph.facebook.com

次に、ステータスコードと結果で解決された各リクエストの配列を返します。

[
    { "code": 200, 
      "headers":[
          { "name": "Content-Type", 
            "value": "text/javascript; charset=UTF-8" }
      ],
      "body": "{\"id\":\"…\"}"},
    { "code": 200,
      "headers":[
          { "name":"Content-Type", 
            "value":"text/javascript; charset=UTF-8"}
      ],
      "body":"{\"data\": [{…}]}}
]

リクエストをループして、自分のアプリに対して urlopen を呼び出すだけで、flask-restful でこれを再現できました。これは非常に非効率的で、もっと良い方法があると考えなければなりません。リクエスト ハンドラ内から自分のアプリケーションに対してリクエストを行うための、より簡単で優れた方法はありますか?

4

2 に答える 2

1

次のように、Flask だけを使用して、バッチで送信された個々の要求を実行できます。

バッチリクエスト

[
    {
        "method" : <string:method>,
        "path"   : <string:path>,
        "body"   : <string:body>
    },
    {
        "method" : <string:method>,
        "path"   : <string:path>,
        "body"   : <string:body>
    }
]

バッチレスポンス

[
    {
        "status"   : <int:status_code>,
        "response" : <string:response>
    },
    {
        "status"   : <int:status_code>,
        "response" : <string:response>
    }
]

サンプルコード

def _read_response(response):
    output = StringIO.StringIO()
    try:
        for line in response.response:
            output.write(line)

        return output.getvalue()

    finally:
        output.close()

@app.route('/batch', methods=['POST'])
def batch(username):
    """
    Execute multiple requests, submitted as a batch.

    :statuscode 207: Multi status
    """
    try:
        requests = json.loads(request.data)
    except ValueError as e:
        abort(400)

    responses = []

    for index, req in enumerate(requests):
        method = req['method']
        path = req['path']
        body = req.get('body', None)

        with app.app_context():
            with app.test_request_context(path, method=method, data=body):
                try:
                    # Can modify flask.g here without affecting flask.g of the root request for the batch

                    # Pre process Request
                    rv = app.preprocess_request()

                    if rv is None:
                        # Main Dispatch
                        rv = app.dispatch_request()

                except Exception as e:
                    rv = app.handle_user_exception(e)

                response = app.make_response(rv)

                # Post process Request
                response = app.process_response(response)

        # Response is a Flask response object.
        # _read_response(response) reads response.response and returns a string. If your endpoints return JSON object,
        # this string would be the response as a JSON string.
        responses.append({
            "status": response.status_code,
            "response": _read_response(response)
        })

    return make_response(json.dumps(responses), 207, HEADERS)
于 2015-05-01T18:13:18.520 に答える