rest - 使用 flask-restful 批处理 API 请求

标签 rest flask flask-restful

我正在使用 flask-restful 构建一个 REST API,我想启用的一件事是批量请求资源的能力,类似于 Facebook Graph 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 中复制它。这看起来效率很低,我不得不认为有更好的方法。是否有更简单和/或更好的方法来从请求处理程序中针对我自己的应用程序发出请求?

最佳答案

您可以只使用 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)

关于rest - 使用 flask-restful 批处理 API 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26414379/

相关文章:

javascript - 如何从 chrome 扩展 POST 到 flask-security 端点?

python - 如何将嵌套属性编码到架构?

flask-restful - 如何在flask-restful中指定参数是可选的

java - Spring boot Rest controller - 将表单编码的主体转换为 POJO

android - 改造 - 在字符串中获取响应错误

json - 在grails 2.3.x中使用Rest API JSON

rest - 深度对象路由的 Web API 最佳实践

使用 Flask 和 MySQL 的 Python 在不活动一段时间后超时

python - Flask 如何在每个请求开始时启动一个新的 SQLAlchemy 事务?