我正在尝试使用RobotFramework发送POST请求,其中请求的主体是XML .

这是一个Sample Robot文件:

*** Settings ***
Library    REST

*** Variables ***
${SERVER_URL}    https://www.w3schools.com/xml/tempconvert.asmx

*** Test Cases ***
CL 1
    [Tags]    TC-CL
#    Send SOAP via POST    <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">" <soap:Body>" <FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/">" <Fahrenheit>100</Fahrenheit>" </FahrenheitToCelsius>" </soap:Body>"</soap:Envelope>
#    Send SOAP via POST    <?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> <soap:Body> <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\" <Fahrenheit>100</Fahrenheit> </FahrenheitToCelsius> </soap:Body></soap:Envelope>
#    Send SOAP via POST    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap:Body>\n <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\n <Fahrenheit>100</Fahrenheit>\n </FahrenheitToCelsius>\n </soap:Body>\n</soap:Envelope>
    Send SOAP via POST    <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/"><Fahrenheit>100</Fahrenheit></FahrenheitToCelsius></soap:Body></soap:Envelope>


*** Keywords ***
Send SOAP via POST
    [Arguments]         ${body}
    SET HEADERS    {"SOAPAction": "https://www.w3schools.com/xml/FahrenheitToCelsius","Content-Type": "text/xml","Cache-Control": "no-cache"}

    ${resp}=    POST    ${SERVER_URL}    data=${body}
    Log    ${resp}  repr=true

当您运行此代码时,我收到错误:

This is not a JSON string:
"data=<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/
soap/envelope/"><soap:Body><FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/"><Fahrenheit>100</Fahrenheit></FahrenheitToCelsius></soap:Body></soap:Envelope>"

仅供参考:“通过POST发送SOAP”的注释版本是我尝试解决问题的不同方式 .

下面是使用请求确保我的 endpoints 工作的示例python代码(一旦我解决了那个讨厌的“这不是一个JSON字符串问题”:

import requests

url = "https://www.w3schools.com/xml/tempconvert.asmx"

payload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n  <soap:Body>\r\n   <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\r\n     <Fahrenheit>100</Fahrenheit>\r\n   </FahrenheitToCelsius>\r\n  </soap:Body>\r\n</soap:Envelope>"
payload = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> <soap:Body> <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\" <Fahrenheit>100</Fahrenheit> </FahrenheitToCelsius> </soap:Body></soap:Envelope>"
payload = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/"><Fahrenheit>100</Fahrenheit></FahrenheitToCelsius></soap:Body></soap:Envelope>'
headers = {
    'SOAPAction': "\"https://www.w3schools.com/xml/FahrenheitToCelsius\"",
    'Content-Type': "text/xml",
    'Cache-Control': "no-cache",
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)

问题似乎在RESTInstance代码here

抛出错误的最初问题(参见下面的注释行):

@keyword
def post(self, endpoint, body=None, timeout=None, allow_redirects=None,
         validate=True, headers=None):
    """Make a ``POST`` request call to a specified ``endpoint``.
    Example:
    POST "Mr Potato" to endpoint and ensure status code is 201
    | `POST`    | /users          | { "id": 11, "name": "Mr Potato" } |
    | `Integer` | response status | 201                               |
    """
    endpoint = self._input_string(endpoint)
    request = deepcopy(self.request)
    request['method'] = "POST"
    request['body'] = self.input(body)  # <== ERROR THROWS HERE
    if allow_redirects is not None:
        request['allowRedirects'] = self._input_boolean(allow_redirects)
    if timeout is not None:
        request['timeout'] = self._input_timeout(timeout)
    validate = self._input_boolean(validate)
    if headers:
        request['headers'].update(self._input_object(headers))
    return self._request(endpoint, request, validate)['response']

根本问题是_request代码强制body在requests.requests调用的json参数中使用(也就是基于导入的客户端),请参阅下面相同文件中的代码片段:

def _request(self, endpoint, request, validate=True):
    if endpoint.endswith('/'):
        endpoint = endpoint[:-1]
    if not endpoint.startswith(('http://', 'https://')):
        base_url = self.request['scheme'] + "://" + self.request['netloc']
        if not endpoint.startswith('/'):
            endpoint = "/" + endpoint
        endpoint = urljoin(base_url, self.request['path']) + endpoint
    request['url'] = endpoint
    url_parts = urlparse(request['url'])
    request['scheme'] = url_parts.scheme
    request['netloc'] = url_parts.netloc
    request['path'] = url_parts.path
    try:
        response = client(request['method'], request['url'],
                          params=request['query'],
                          json=request['body'],    #<== ROOT CAUSE HERE
                          headers=request['headers'],
                          proxies=request['proxies'],
                          cert=request['cert'],
                          timeout=tuple(request['timeout']),
                          allow_redirects=request['allowRedirects'],
                          verify=request['sslVerify'])

使用请求库发送XML时,您需要使用 body= 而不是 json=