Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set SoapClient HTTP content type to application/soap+xml

Tags:

php

soap

I need to change the content type from "text/xml; charset=utf-8" to "application/soap+xml; charset=utf-8".

I'm sending a request from PHP to another server (Oracle server) using SoapClient class that exist by default in PHP. I'm using PHP v7.0.10.

As per SoapClient documentation I should just set the soap_version inside the options array to SOAP_1_2 and it will change the content type but it doesn't do that.

SOAP Request

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:pub="http://xmlns.oracle.com/oxp/service/PublicReportService">
    <soap:Header/>
    <soap:Body>
        <pub:runReport>
            <pub:reportRequest>
                <pub:reportAbsolutePath>/Human Capital Management/Workforce Management/Human Resources Dashboard/Fusion User Information.xdo</pub:reportAbsolutePath>
                <pub:sizeOfDataChunkDownload>-1</pub:sizeOfDataChunkDownload>
            </pub:reportRequest>
        </pub:runReport>
    </soap:Body>
</soap:Envelope>

PHP Code

$WSDL = "https://example.com/xmlpserver/services/ExternalReportWSSService?WSDL";

    $soap_options = array(
        'uri' => 'http://www.w3.org/2003/05/soap-envelope',
        'style' => SOAP_RPC,
        'use' => SOAP_ENCODED,
        'soap_version' => SOAP_1_2,
        'cache_wsdl' => WSDL_CACHE_NONE,
        'connection_timeout' => 30,
        'trace' => true,
        'encoding' => 'UTF-8',
        // 'exceptions' => true,
        'location' => $WSDL,
        'login' => '---',
        'password' => '---'
    );

    try {
        $soap_client = new SoapClient(NULL, $soap_options);
        $result = $soap_client->__doRequest($soap_request, $WSDL, "run", NULL);
        $clean_xml = str_ireplace(['SOAP-ENV:', 'SOAP:', 'env:'], '', $result);
        $xml = simplexml_load_string($clean_xml);
        var_dump($xml);
    } catch (Exception $e) {
        echo $e;
    }

Last request header shows

POST /xmlpserver/services/ExternalReportWSSService?WSDL HTTP/1.1
Host: example.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/7.0.10
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 510
Authorization: Basic ---

I've tried to set the content type by so many ways and every one of them failed

Update & Solution

<?php

    $soap_request = <<<XML
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:pub="http://xmlns.oracle.com/oxp/service/PublicReportService">
    <soap:Header/>
    <soap:Body>
        <pub:runReport>
            <pub:reportRequest>
                <pub:reportAbsolutePath>/Human Capital Management/Workforce Management/Human Resources Dashboard/Fusion User Information.xdo</pub:reportAbsolutePath>
                <pub:sizeOfDataChunkDownload>-1</pub:sizeOfDataChunkDownload>
            </pub:reportRequest>
        </pub:runReport>
    </soap:Body>
</soap:Envelope>
XML;

$WSDL = "https://example.com/xmlpserver/services/ExternalReportWSSService?WSDL";
    $user = "---";
    $password = "---";
$ch = curl_init(); 
    curl_setopt($ch, CURLOPT_HEADER,         false);
    curl_setopt($ch, CURLOPT_URL,            $WSDL);
    curl_setopt($ch, CURLOPT_FAILONERROR,    true); 
    curl_setopt($ch, CURLOPT_HTTPHEADER,     Array(
        'Content-Type: application/soap+xml; charset=utf-8', 
        'SOAPAction: "run"',
        'Accept: text/xml',
        'Cache-Control: no-cache',
        'Pragma: no-cache',
        'Content-length: '. strlen($soap_request),
        'User-Agent: PHP-SOAP/7.0.10'
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_USERPWD,        $user.":".$password);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ch, CURLOPT_TIMEOUT,        30);
    curl_setopt($ch, CURLOPT_POSTFIELDS,     $soap_request);
    $response = curl_exec($ch); 
    if (empty($response)) { 
        throw new SoapFault('CURL error: '.curl_error($ch), curl_errno($ch)); 
    } 
    curl_close($ch);
    var_dump($response);
?>
like image 981
hamada147 Avatar asked Oct 17 '18 01:10

hamada147


People also ask

How do you set Content-Type in SOAP request?

1 Content-Type. The Content-Type header for SOAP requests and responses specifies the MIME type for the message and is always text/xml. It may also specify the character encoding used for the XML body of the HTTP request or response. This follows the text/xml part of the header values.

What is the default Content-Type for SOAP responses?

The HTTP Content-Type of the SOAP request or SOAP response. The default is "text/xml".

How can we make a SOAP call using SoapClient class in PHP?

php // Create Contact class class Contact { public function __construct($id, $name) { $this->id = $id; $this->name = $name; } } // Initialize WS with the WSDL $client = new SoapClient("http://localhost:10139/Service1.asmx?wsdl"); // Create Contact obj $contact = new Contact(100, "John"); // Set request params $params = ...

Why XML is used in SOAP?

SOAP uses XML to package the data passed to a method, or received as a response. SOAP itself is nothing more than a set of rules that define how to describe method calls and return values using XML syntax. XML merely describes data, without consideration for the way that the data is processed or presented.

What is content type in SOAP request?

Content-Type. The Content-Type header for a SOAP request and response defines the MIME type for the message and the character encoding (optional) used for the XML body of the request or response.

What is a SOAP message in XML?

A SOAP message is an ordinary XML document containing the following elements: An Envelope element that identifies the XML document as a SOAP message. A Header element that contains header information. A Body element that contains call and response information. A Fault element containing errors and status information.

What is a SOAP request in Java?

Java implementations of SOAP usually provide a specific binding for the JMS (Java Messaging System) protocol. The Content-Type header for a SOAP request and response defines the MIME type for the message and the character encoding (optional) used for the XML body of the request or response.

What is the default encoding of a SOAP message?

A SOAP message has no default encoding. The required SOAP Body element contains the actual SOAP message intended for the ultimate endpoint of the message. Immediate child elements of the SOAP Body element may be namespace-qualified.


1 Answers

From SoapClient manual:

The stream_context option is a resource for context.

You can set HTTP headers in your newly created stream context

$stream_context_opts = array(
    'http'=>array(
        'method'=>"POST",
        'header'=> "Content-Type: application/soap+xml; charset=utf-8\r\n"
    )
);

$soap_stream_context = stream_context_create($stream_context_opts);


 $soap_options = array(
    'uri' => 'http://www.w3.org/2003/05/soap-envelope',
    'style' => SOAP_RPC,
    'use' => SOAP_ENCODED,
    'soap_version' => SOAP_1_2,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'connection_timeout' => 30,
    'trace' => true,
    'encoding' => 'UTF-8',
    'stream_context' => $soap_stream_context,
    // 'exceptions' => true,
    'location' => $WSDL,
    'login' => '---',
    'password' => '---'
);

There is another way to do this by making a child class and override __doRequest method,

class MySoapClient extends SoapClient { 
    public function __construct($wsdl, $options = array()) {
        parent::__construct($wsdl, $options); 
    }
    public function __doRequest($request,$location,$action,$version,$one_way = 0) { 
        $handle = curl_init(); 
        curl_setopt($handle, CURLOPT_HEADER, false); 
        curl_setopt($handle, CURLOPT_URL, $location); 
        curl_setopt($handle, CURLOPT_FAILONERROR, true); 
        curl_setopt($handle, CURLOPT_HTTPHEADER, Array('Content-Type: application/soap+xml; charset=utf-8') ); 
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); 
        curl_setopt($handle, CURLOPT_POSTFIELDS, $request); 
        $response = curl_exec($handle); 
        if (empty($response)) { 
            throw new SoapFault('CURL error: '.curl_error($handle),curl_errno($handle)); 
        } 
        curl_close($handle); 
        return $response;
    } 
}
like image 99
Abdul-Hameed Riad Avatar answered Nov 06 '22 21:11

Abdul-Hameed Riad