How to duplicate a curl XML request using HTTP API?

I am working on a plugin that posts an XML request to a vendor’s shipping API to get shipping quotes. The XML is stored in a string called $xml. I can post the XML request successfully with curl using these parameters:

$curl = curl_init( $this->settings['api_url'] );
curl_setopt( $curl, CURLOPT_HEADER, 0 );
curl_setopt( $curl, CURLOPT_POST, 1 );
curl_setopt( $curl, CURLOPT_TIMEOUT, 45 );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, 0 );
curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 0 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $xml );
$result = curl_exec( $curl );
curl_close( $curl );

My question is, how can I do the same thing with WordPress HTTP API? I want to maximize compatibility for those that may not have curl on their servers.

Here is the HTTP API attempt I have made:

$result = wp_remote_post(
    $this->settings['api_url'],
    array(
        'method'      => 'POST',
        'timeout'     => 45,
        'redirection' => 5,
        'httpversion' => '1.1',
        'headers'     => array(
            'Content-Type' => 'text/xml'
        ),
        'body'        => array(
            'postdata'     => $xml
        ),
        'sslverify'   => 'false'
    )
);

I have tried changing the body to just:

'body' => array( $xml ),

I have tried converting the $xml to a php associative array with simple xml and json.

With all of my attempts, I keep getting back an error in my vendor’s response: “Content is not allowed in prolog.” It would seem that the XML is either not being posted properly or HTTP API is maybe including a Byte Order Mark (BOM).

Hoping someone can help. Thanks.

2 Answers
2

I tried some more trial and error and managed to get it to work by simply putting $xml as the body without specifying it as an array. The function reference says, “Post data should be sent in the body as an array,” so I’m not sure why it worked.

Here is the working code in case it helps someone else:

// Sends the xml request to the API
$result = wp_remote_post(
    $this->settings['api_url'],
    array(
        'method'      => 'POST',
        'timeout'     => 45,
        'redirection' => 5,
        'httpversion' => '1.1',
        'headers'     => array(
            'Content-Type' => 'text/xml'
        ),
        'body'        => $xml,
        'sslverify'   => 'false'
    )
);

Leave a Comment