PackageGenerator icon indicating copy to clipboard operation
PackageGenerator copied to clipboard

Content-Type not being set

Open nei opened this issue 7 years ago • 6 comments

I'm consuming an API that requires content-type = application/soap+xml; charset=utf-8 on the request.

On my generated service class I've specified:

$this->setHttpHeader('Content-Type', 'application/soap+xml; charset=utf-8');
$this->setHttpHeader('Test', 'xxxxxxxxx');
$this->setHttpHeader('Test2', 'yyyyyyy');

Then I get this error from the api

Response Validation Exception: Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'.

On the AbstractSoapClientBase class, method setHttpHeader I can see all these three headers being set properly using

var_dump(stream_context_get_options(static::getSoapClient()->_stream_context));

The request actually end up with my new headers but failed back to the default Content-Type:

User-Agent: Nei
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://v12finance.com/Services/ApplicationGateway/1.1/IApplicationGatewayWebService/GetRetailerFinanceProducts"
Content-Length: 567
Test: xxxxxxxxx
Test2: yyyyyyy

I have no idea about this since I've not found any reference for content-type on the code. Any clue how to set the content-type?

nei avatar Jun 07 '17 15:06 nei

content-type is set by the SoapClient, the "only" solution is to "manually" send the request "yourself" using a curl request overridding the __doRequest method.

In order to override the __doRequest, you can take example at this project https://github.com/WsdlToPhp/PackageEws365

let me know if you need further information

mikaelcom avatar Jun 07 '17 20:06 mikaelcom

any feedback is appreciated as I know that other users faced this issue and it would be good know the best way/practice to work around this, thx 😉

mikaelcom avatar Jun 07 '17 20:06 mikaelcom

You don't need to extend the SoapClient class.

The content type is indeed defined by the SoapClient but is determined by the soap_version. The default is SOAP_1_1 which sets the content type as text/xml, but if you use SOAP_1_2 it is set to application/soap+xml.

You can do this by add 'wsdl_soap_version' to your constructors options.

For example, building on a generated tutorial.php

require_once __DIR__ . '/vendor/autoload.php';
$options = array(
  \WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_URL => 'http://..../MyWsdl.wsdl',
  \WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_CLASSMAP => ClassMap::get(),
  'wsdl_soap_version' => SOAP_1_2,
);
$is = new \ServiceType\Is($options);
if ($is->MyCallBack(new \StructType\MyCallBack()) !== false) {
  print_r($is->getResult());
} else {
  print_r($is->getLastError());
}

jowan avatar Mar 13 '18 16:03 jowan

Thanks for this precision!

Nonetheless, if the server requires a specific content-type, which is are, you can't unless you send the request with your own implementation using curl for example

mikaelcom avatar Mar 14 '18 08:03 mikaelcom

Yes that is true. And yes, extend the SoapClient and __doRequest. I would like to see an example if you have one.

jowan avatar Mar 14 '18 09:03 jowan

The override of the SoapClient class instance is demonstrated in the PackageEws365 project especially in the dedicated SoapClient class

mikaelcom avatar Mar 14 '18 13:03 mikaelcom