我尝试在我的项目中使用falcon包。问题是我没有找到从HTTP post请求中获取正文数据的方法。
我使用了示例中的代码,但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数据?
感谢您的帮助
答案 0 :(得分:5)
对问题的深入研究导致了以下linked issue on github。它指出falcon框架至少在其0.3版本中使用并且与Python 2一起工作并没有解析数据' POSTed'作为字符串,如果他们适当地逃脱。我们可以使用有关您尝试通过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,或者标题信息是否完全丢失。
bound_stream 在官方falcon documentation中描述如下。
类似于文件的包装器,用于规范不同WSGI服务器使用的本机输入对象之间的某些差异。特别是,bounded_stream知道正文的预期Content-Length,并且永远不会阻止越界读取,假设客户端在将数据传输到服务器时没有停止。
Falcon接收HTTP请求数据作为缓冲区对象,由WSGI包装器传递,它从客户端接收数据,并且它可能无法在数据之上运行正确的解析以转换为更有用的数据结构表现原因。
答案 1 :(得分:1)
我在falcon框架中添加了request.py中的更改,以解析application / x-www-form-urlencoded和multipart / from-data。 我已经提出了拉取请求 - https://github.com/falconry/falcon/pull/1236但它还没有合并到主人。 检查一下 - 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)
如果您有任何疑问,请告诉我。
答案 2 :(得分:1)
非常感谢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)
答案 3 :(得分:1)
您要查找的字段的名称有些混乱,但它是req.media:
返回请求流的反序列化形式。调用时,它将尝试使用Content-Type标头以及通过
falcon.RequestOptions
配置的media-type处理程序来反序列化请求流。
如果请求为JSON,则req.media
已包含python字典。
答案 4 :(得分:0)
到目前为止,对我来说,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中是我唯一能想到的解决方案
答案 5 :(得分:0)
在 falcon 2 中,如果您使用 json 类型,请使用req.media
例如:
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())
答案 6 :(得分:0)
这是我在设计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。