我尝试在我的项目中使用 falcon 包。问题是我没有找到从 HTTP 发布请求中获取正文数据的方法。
我使用了示例中的代码,但req.stream.read()没有按预期返回 JSON。
代码是:
raw_json = req.stream.read()
result.json(raw_json, encoding='utf-8')
resp.body = json.dumps(result_json, encoding='utf-8')
如何获取 POST 数据?
谢谢你的帮助
我尝试在我的项目中使用 falcon 包。问题是我没有找到从 HTTP 发布请求中获取正文数据的方法。
我使用了示例中的代码,但req.stream.read()没有按预期返回 JSON。
代码是:
raw_json = req.stream.read()
result.json(raw_json, encoding='utf-8')
resp.body = json.dumps(result_json, encoding='utf-8')
如何获取 POST 数据?
谢谢你的帮助
in falcon 2, if you work with json type, use req.media
for example:
import falcon
from json import dumps
class Resource(object):
def on_post(self, req, resp, **kwargs):
result = req.media
# do your job
resp.body = dumps(result)
api = falcon.API()
api.add_route('/test', Resource())
对问题的深入研究导致了github 上的以下链接问题。它指出 falcon 框架至少在其 0.3 版和使用 Python 2 时不会将“发布”的数据解析为字符串,如果它们被恰当地转义的话。我们可以使用有关您尝试通过 POST 请求发送哪些数据以及以何种格式发送的更多信息,例如作为简单文本发送,或者使用 Header Information Content-Type:application/json,或者如果它的通过 HTML 表单。
虽然从问题中不清楚确切的问题,但我仍然可以建议尝试使用bounded_stream而不是stream:
raw_json = req.bounded_stream.read()
result.json(raw_json, encoding='utf-8')
resp.body = json.dumps(result_json, encoding='utf-8')
对于官方文档,建议使用bounded_stream不确定条件,例如 Content-Length undefined 或 0,或者完全缺少标头信息。
bounded_stream在官方falcon 文档中描述如下 。
流的类文件包装器,用于规范不同 WSGI 服务器使用的本机输入对象之间的某些差异。特别是,bounded_stream 知道主体的预期 Content-Length,并且永远不会阻止越界读取,假设客户端在将数据传输到服务器时不会停止。
Falcon 接收 HTTP 请求数据作为由 WSGI 包装器传递的缓冲区对象,该包装器从客户端接收数据,并且出于性能原因,它可能没有在数据之上运行正确的解析以转换为更可用的数据结构。
非常感谢 Ryan(和 Prateek Jain)的回答。
解决办法就是把app.req_options.auto_parse_form_urlencoded=True. 例如:
import falcon
class ThingsResource(object):
def on_post(self, req, resp):
value = req.get_param("value", required=True)
#do something with value
app = falcon.API()
app.req_options.auto_parse_form_urlencoded=True
things = ThingsResource()
app.add_route('/things', things)
您要查找的字段名称有些混乱,但它是req.media:
返回请求流的反序列化形式。调用时,它将尝试使用 Content-Type 标头以及通过配置的媒体类型处理程序反序列化请求流
falcon.RequestOptions。
如果请求是 JSON,则req.media已经包含一个 python dict。
我在 falcon 框架的 request.py 中添加了更改,以解析 application/x-www-form-urlencoded 和 multipart/from-data。我提出了拉取请求 - https://github.com/falconry/falcon/pull/1236但它尚未合并到 master 中。检查这个 - https://github.com/branelmoro/falcon
我添加了新代码来解析 POST、PUT 和 DELETE application/x-www-form-urlencoded 和 multipart/form-data。文本字段将在 req.form_data 字典中可用,上传文件缓冲流将在 req.files 字典中可用。
我希望这将有助于分别访问 POST 和 GET 参数,我们也将能够上传文件。更改的好处是它不会将整个上传的文件加载到内存中。
下面是展示如何使用 POST、PUT 和 DELETE application/x-www-form-urlencoded 和 multipart/form-data 的示例代码:
import falcon
class Resource(object):
def on_post(self, req, resp):
# req.form_data will return dictionary of text field names and their values
print(req.form_data)
# req.form_data will return dictionary of file field names and
# their buffer class FileStream objects as values
print(req.files)
# support we are uploading a image.jpg in `pancard` file field then
# req.files["pancard"] will be FileStream buffer object
# We can use set_max_upload_size method to set maximum allowed
# file size let say 1Mb = 1*1024*1024 bytes for this file
req.files["pancard"].set_max_upload_size(1*1024*1024)
# We can use uploadto method to upload file on required path (Note: absolute filepath is required)
# This method returns boolean - `True` on successful upload
# and if upload is unsuccessful then it returns `False` and sets error on failure.
path = "/tmp/" + req.files["pancard"].name
response = req.files["pancard"].uploadto("/tmp/" + path)
print(response)
# Once file is uploaded sucessfully, we can check it's size
print(req.files["pancard"].size)
# If file is not uploaded sucessfully, we can check it's error
print(req.files["pancard"].error)
resp.body = "Done file upload"
resp.status = falcon.HTTP_200
# falcon.API instances are callable WSGI apps
app = falcon.API()
things = Resource()
# things will handle post requests to the '/post_path' URL path
app.add_route('/post_path', things)
如果您有任何疑问,请告诉我。
到目前为止...对我来说 bounded_stream.read() 和 stream.read() 都将发布的数据作为 str 类型获取。到目前为止,我只找到了解决这个问题的一种方法:
def on_post(self, req, resp):
posted_data = json.loads(req.stream.read())
print(str(type(posted_data)))
print(posted_data)
收到发布的数据后,将字符串加载到 json dict 是我唯一能想到的解决方案
有一种从正文获取媒体的示例方法。我用来在 post 方法中获取正文:
def on_post(req,resp)
arguments = {}
# get body media on post method
body = req.get_media()
if 'something' in body:
arguments['something'] = body['something']
发送正文内容类型 Media-Type 并打印 resp 或在代码中使用,但如果要发送 JSON 正文,您的代码应涵盖提供 JSON 参数。
如果您有任何疑问,请告诉我。
这是我在设计 API 时使用的东西。
import falcon
import json
class VerifierResource():
def on_post(self, req, resp):
credentials = json.loads(req.stream.read())
if credentials['username'] == USER \
and credentials['passwd'] == PASSWORD:
resp.body = json.dumps({"status": "verified"})
else:
resp.body = json.dumps({"status": "invalid"})
api = falcon.API()
api.add_route('/verify', VerifierResource())
这将返回一个带有相应响应正文的序列化 JSON。