【问题标题】:How do I forward responses from microservices back to the client?如何将微服务的响应转发回客户端?
【发布时间】:2020-12-31 04:08:50
【问题描述】:

TL/DR:在烧瓶端点内,我正在向不同的端点发出请求,我想返回该请求的响应。响应是文件附件,如何正确返回该响应? response.content 不会剪切它(在浏览器中显示文件二进制文件而不是下载文件)


详情如下:


我一直在网上寻找解决方案,但我似乎找不到任何有同样问题的人,这可能表明我可能会解决这个问题。这是细分:

我有一个运行一些烧瓶微服务的后端,其中一个是与前端交互的主网关。我的应用程序的一部分涉及用户访问返回文件下载的特定链接。通过一些研究,我发现使用 send_file()send_from_directory() 在烧瓶中执行此操作非常简单。我面临的问题是我已将所有与文件存储相关的活动放入其自己的微服务中,但我无法弄清楚如何将从该微服务获得的响应从网关“转发”回客户端。

所以本质上,我有:

filestorage_service:app.py:

# flask stuff: imports, app config, etc

@app.route('/get', methods=['GET'])
def get_file():
    filename = request.form.get('filename')

    try:
        return send_from_directory("<some_base_dir>", filename=filename, as_attachment=True)

    except FileNotFoundError:
        return "Error: File not found", 400

网关:app.py:

# flask stuff: imports, app config, etc

@app.route('/get-file/<filename>', methods=['GET'])
@cross_origin()
def get_file(filename):
    data = {
        'filename': filename
    }

    res = requests.get("<filestorage_service_url>" + "/get", data=data)
    
    # now what??
    

我该如何返回res?简单地输入return res 会产生错误,返回res.content 实际上会在浏览器中显示图像二进制文件。我应该进入完全代理模式并从头开始重建整个响应,还是有更简单的方法我错过了?

【问题讨论】:

    标签: python flask microservices


    【解决方案1】:

    我设法获得了您的应用程序的精简版本来做您想做的事。

    import os
    
    import requests
    from flask import Flask, send_from_directory, Response
    
    app = Flask(__name__)
    
    # Storage service
    @app.route('/get', methods=['GET'])
    def get_file():
        filename = 'somefile.txt'
    
        try:
            return send_from_directory(os.getcwd(), filename=filename, as_attachment=True)
    
        except FileNotFoundError:
            return "Error: File not found", 400
    
    # Front end
    @app.route('/getfile', methods=['GET'])
    def get_file_1():
        res = requests.get("http://127.0.0.1:5000" + "/get",)  # call storage
        return Response(
            res.content,  # content fromthe storage service has the file data
            headers=dict(res.headers)  # headers need to copied to start download
        )
    
    
    app.run(debug=True)
    

    您需要做的就是确保从您要转发的响应中复制内容和标头。重要的标头是 Content-DispositionContent-TypeContent-Length 标头。文件内容本身在response.content

    【讨论】:

    • 解决了。所以它一直是标题。我想我错过了什么。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    相关资源
    最近更新 更多