【问题标题】:How to send http post request with an Avro file?如何使用 Avro 文件发送 http post 请求?
【发布时间】:2020-01-17 15:27:10
【问题描述】:

我有一个烧瓶 api,它期望在 Avro 中发出一个发布请求。问题是我不确定如何发送 Avro 请求来测试它。 api使用fastavro.reader(io.BytesIO(request.data))读取数据

我尝试过使用邮递员: 在将 Content-Type 定义为“avro/binary”的标头中 但是看起来不可能 https://github.com/postmanlabs/postman-app-support/issues/4435

我也试过 curl:

curl -X POST -H "Content-Type: avro/binary" --data "{"city": "ALA",
"number_of_points": 42, "transport": "CAR", "subtype": "PURCHASE"}"
"http://localhost:8080/invocations"

然而 fastavro 返回以下错误:

文件“fastavro/_read.pyx”,第 725 行,在 fastavro._read.file_reader 中。init

ValueError: 无法读取标头 - 它是 avro 文件吗?

资源:

https://github.com/fastavro/fastavro

https://avro.apache.org/

【问题讨论】:

  • 您是否在您链接的那个问题线程中按照reply 尝试过-H "Content-Type: application/vnd.kafka.avro.v2+json"?编辑:事实上,我进一步阅读,有人建议这不适用于“通用 avro 有效载荷”——尽管值得一试。
  • 是的,我试过了。同样的错误:ValueError: cannot read header - 它是 avro 文件吗?
  • 目标实际上是上传avro 文件,而不是将有效负载指定为curl 的--data 参数,还是等价的? --data arg 是否仅用于您的示例,或者您可以以这种格式指定它是否至关重要?
  • 这只是示例。这就是我的计划所期望的。如何上传 avro 文件?
  • 另外,您是否可以控制 API 代码...澄清一下,我已经生成了一个带有 the fastavro example code 的文件,这导致了一个文件 like this。这就是你需要提供 API 的东西吗,如果是的话,我有答案。

标签: rest postman avro


【解决方案1】:

好的,所以我假设您有一个有效的 .avro 文件,根据 fastavro 文档中的 example

这将成为一个简单的案例,将其作为标准文件上传到 Flask。因此,与其从request.data 获取数据,不如这样做:

from fastavro import reader
from flask import Flask, request
app = Flask(__name__)

# This is really basic and could use some validation
@app.route('/invocations', methods=['POST'])
def upload():
    if request.method == 'POST':
        file = request.files['file']
        for record in reader(file):
                print (record)
        return 'uploaded'

然后您可以使用 curl 将文件提交到端点:

curl -i -X POST -F 'file=@out.avro' "http://localhost:5000/invocations" -H 'ContentType: multipart/form-data'

这应该会在服务器控制台上产生如下内容:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
{'station': '011990-99999', 'time': 1433269388, 'temp': 0}
{'station': '011990-99999', 'time': 1433270389, 'temp': 22}

如果你想使用 requests 库提交,你可以这样做:

import requests

def upload(filename):
    headers={'ContentType': 'multipart/form-data'}
    with open(filename,'rb') as f:
        files = {'file': f}
        url='http://localhost:5000/invocations'
        r = requests.post(url, files=files)
        print (r.content, r.status_code)

upload('out.avro')

【讨论】:

  • 我认为我的 avro 文件格式不正确。反正我会给你支票的。谢谢!!
  • @italo 没问题,虽然我很好奇这是否最终对你有用,所以请更新:-)