【问题标题】:Send XML file to REST API in Python3在 Python3 中将 XML 文件发送到 REST API
【发布时间】:2018-05-11 20:45:15
【问题描述】:

我正在尝试使用 requests 库与 REST API 进行交互。

我需要将一个大型 XML 文件传递​​给 API - 我可以在 Linux 中使用 curl 轻松完成此操作,但我想要一种 Python 方式来执行此操作。

在 curl 中,我的语法如下所示:

curl -k https://10.244.1.2:4444/webconsole/APIController? -F "reqxml=MYxml.xml"

注意:-k 标志只是忽略 ssl 错误

到目前为止,这是我想出的:

import requests    
url = r'https://10.244.1.2:4444/webconsole/APIController?reqxml='    
x = open('MYxml.xml', 'r').read()

q = requests.post(url, data=x, verify=False)    
print(q.text)

如果我将 q 变量更改为:q = requests.post(url + x, verify=False) 然后该命令将起作用。但是,对于较长的 XML 文件,它将失败。

我看过这两个相关的帖子:FirstSecond 但这些建议看起来就像我的语法,除非我遗漏了一些明显的东西

感谢任何帮助!

【问题讨论】:

  • 我看不出请求语法有什么问题。你能描述一下网络服务器吗?在黑暗中尝试一下,Web 服务器可能会期待一个“Content-Type”xml 标头,而 curl 会自动添加它。使用 -v(详细日志记录)再次执行 curl 命令并查看请求标头。
  • API 是 Sophos XG 防火墙。它的文档非常稀疏,所以我不确定标题。我会尝试 curl 建议。感谢您的提示
  • @BrennenSprimont 所以我可以看到 curl 正在添加 multipart/form-data 作为内容类型。我尝试将其添加到查询中,但没有运气。
  • 为了它,尝试添加一个“application/xml”表单类型。比如:q = requests.post(url, data=x, verify=False, headers={"Content-Type":"application/xml"})
  • @BrennenSprimont 在发布之前我已经尝试过这些标题。我也以为会这样。

标签: python-3.x rest api python-requests


【解决方案1】:

(将 cmets 讨论转化为答案)

与没有良好文档或错误报告服务的 Web 服务器交互总是很痛苦。

但是,如果您有一个有效的方法(curl 命令),那么您就可以涉足了。 curl 有一个 -v 标志,可用于查看与有效负载一起发送的标头。

此外,查看您的 curl 命令,您正在发送整个文件。然而,您的 python 脚本正在将数据读入文本字符串并将其发送出去。

如果 Web 服务器接受 XML 数据,您可能只需要添加 XML 内容类型标头并查看是否有效:

q = requests.post(url, data=x, verify=False, headers={"Content-Type":"application/xml"})

否则,如果 Web 服务器只接受文件/表单,则您必须将文件作为二进制对象打开(这更类似于工作 curl 命令):

# Create a dictionary of files to post with your file in it.
x_files = {"file": ("file", open('MYxml.xml', 'rb'))}
...
q = requests.post(url, files=x_files, verify=False, headers={"Content-Type":"multipart/form-data"})

如果上述方法都不起作用并且您仍然感到困惑,请转储工作 curl 请求中的所有标头并将它们编辑到您的答案中,其中必须包含其他内容。

祝你好运

【讨论】:

    【解决方案2】:

    好的,这需要大量的试验和错误才能在这里找出正确的部分,但我终于弄明白了。 @Brennen Sprimont 的回答对于理解 cURL 的作用非常有帮助。

    正如他所指出的 - cURL 实际上是在发送一个完整的文件,而我最初的请求不是。

    我的第一个线索来自我发现的一个网站,该网站将 cURL 命令转换为 python - Link

    当我将 cURL 命令放入该站点时,它会将此作为结果的一部分返回:

    data = {'reqxml' : (None, open(xml_file, 'rb'))}注意:在我的问题中,我使用了 'x',但在这里我使用了 'data' 作为该变量

    None 参数在我的原始文件中丢失了 - 我现在也在阅读二进制文件。

    我的下一个主要问题是我传递文件的方式 - 当我从浏览器执行此操作时,语法是:

    https://<ipaddress><port>/webconsole/APIController?reqxml=<Login></Login>

    这里我们可以看到属性reqxml=定义的数据

    在 cURL 中如下所示:

    curl -k https://10.244.1.2:4444/webconsole/APIController? -F "reqxml=MYxml.xml"

    我们可以在 url 中而不是在文件中传递属性

    我犯的最后一个错误是尝试使用“=”符号传递reqxml 属性。与 cURL 或通过浏览器不同,请求不希望这样。在这种情况下,它希望将值作为不带等号的字典传递。

    下面是我用来测试和使用 Sophos XG v17 的一个小功能

    data_file = 'Myxml.xml'
    ipaddress = '10.244.1.2'
    
    def api_call(api_ip, xml_file):
        api_url = r'https://{}:4444/webconsole/APIController?'.format(api_ip)
        data = {'reqxml' : (None, open(xml_file, 'rb'))}
        r = requests.post(api_url, files=data, verify=False)   
        print(r.text)
    
    api_call(ipaddress, data_file)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 2021-11-16
      • 1970-01-01
      • 2020-11-14
      • 1970-01-01
      相关资源
      最近更新 更多