繁体   English   中英

将带有 XML 字符串的 cURL 命令转换为 python 请求

[英]Converting cURL command with XML string to python request

我曾经使用此 cURL 命令将 XML 字符串发送到我的防火墙的 API:

curl -k https://192.1.1.1:90/APIController -F "reqxml=<myfile.xml"

现在,我想在 python 中执行此操作。 由于 XML 字符串将以编程方式创建,因此我不提供 XML 文件,而是提供 XML 字符串。 这是我现在的代码:

#!/usr/bin/env python
import requests

def xml_string():
    return '''
    reqxml=<?xml version="1.0" encoding="UTF-8"?>
    <Request>
        <Login>
            <Username>admin</Username>
            <Password>admin</Password>
        </Login>
        <Set>
        … further markup …
        </Set>
    </Request>
    '''

def send_xml():
  response = requests.post(
    "https://192.1.1.1:90/APIController",
    headers={"Content-Type": "application/xml"},
    data=xml_string(),
    verify=False
    )
  print(response.status_code)


send_xml()

output 的详细命令curl -k -v https://192.1.1.1:90/APIController -F "reqxml=<testcategory.xml" .

* Trying 192.1.1.1...
* TCP_NODELAY set
* Connected to 192.1.1.1 (192.1.1.1) port 90 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=NA …
*  start date: Aug  1 00:00:00 2010 GMT
*  expire date: Dec 31 23:59:59 2030 GMT
*  issuer: C=NA …
*  SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway.
> POST /APIController HTTP/1.1
> Host: 192.1.1.1:90
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 796
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------20be8a5c28d38998
> 
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Sun, 26 Apr 2020 10:07:59 GMT
< Server: xxxx
< X-Frame-Options: SAMEORIGIN
< Strict-Transport-Security: max-age=31536000
< X-Content-Type-Options: nosniff
< Content-Type: text/xml;  charset=UTF-8
< Cache-Control: max-age=2592000
< Expires: Tue, 26 May 2020 10:07:59 GMT
< Transfer-Encoding: chunked
< 
<?xml version="1.0" encoding="UTF-8"?>
<Response APIVersion="1702.1" IPS_CAT_VER="1">
  <Login>
    <status>Authentication Successful</status>
  </Login>
  <Status code="200">Configuration applied successfully.</Status>
</Response>
* Connection #0 to host 192.1.1.1 left intact

但是尽管返回的状态码是 200,该命令对防火墙没有影响,没有更改任何设置。 为什么 python 代码不能按预期工作?

编辑:我发现,在触发上述 python 代码时,完全忽略了 XML 字符串。 也许 PHP 中的这个工作代码可以解释一下?

<?php

$xml = '<?xml version="1.0" encoding="UTF-8"?>
<Request>
    <Login>
        <Username>admin</Username>
        <Password>admin</Password>
    </Login>
    <Set>
    …
    </Set>
</Request>';
$url = "https://192.1.1.1:90/APIController";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, "reqxml=" . $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
echo '<pre>';
echo htmlentities($data);
echo '</pre>';
if (curl_errno($ch)) {
print curl_error($ch);
} else {
curl_close($ch);
}
?>

您最好的选择是使用更改实际设置的工具/应用程序比较通过线路发送的内容,并与您的 python 请求请求进行比较。 如果您的远程主机接受普通的 HTTP,请使用它并启动 wireshark/tcpdump

- -编辑

  1. 尝试使用 requests 库将内容作为文件发布。

xml_content = '''<?xml version="1.0" encoding="UTF-8"?>
<Request>
    <Login>
        <Username>admin</Username>
        <Password>admin</Password>
    </Login>
    <Set>
    …
    </Set>
</Request>
'''
url = "https://192.1.1.1:90/APIController"

files = {'file': ('reqxml', xml_content)}
r = requests.post(url, files=files)

简单来说,您可以尝试直接通过 python 执行curl命令。 将 xml 字符串存储到文件中。xml

import os
os.system('curl -k https://192.1.1.1:90/APIController -F "reqxml=<<path to file.xml>"')

(更新)或

根据您的curl命令 output 以及php代码,看起来内容类型是作为multipart/form-data 也许您可以尝试使用相同的Content-type: application/x-www-form-urlencoded并将有效负载转换为"reqxml=" + "base64 encoded xml data"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM