代码之家  ›  专栏  ›  技术社区  ›  Joe

将XML文件发送到Python3中的REST API

  •  2
  • Joe  · 技术社区  · 7 年前

    我正在尝试使用 requests 图书馆

    我需要向API传递一个大的XML文件——在Linux中使用curl可以很容易地做到这一点,但我需要一种pythonic方法来做到这一点。

    在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文件,它将失败。

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

    感谢您的帮助!

    2 回复  |  直到 7 年前
        1
  •  2
  •   Brennen Sprimont    7 年前

    (将评论讨论转化为答案)

    与没有良好文档或错误报告服务的web服务器交互总是一件痛苦的事。

    但是,如果您有一种有效的方法 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
  •  1
  •   Joe    7 年前

    好吧,这需要很多尝试和错误来找出正确的部分,但我终于找到了答案@BrennenSprimont的回答对理解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或通过浏览器不同,请求不希望这样。在这种情况下,它希望将值作为字典传递,而不使用equals符号。

    下面是我用来测试和使用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)