php - SoapServer behind Symfony 3 controller not calling wrapped method -
overview
i'm trying put soap server inside symfony controller described here: http://symfony.com/doc/current/controller/soap_web_service.html.
i'm using php2wsdl generate wsdl (after having failed create valid 1 hand!). have service class bunch of methods exposed via soap. , symfony controller shovel post data soapserver
instance , barf out yukky xml response client.
but i'm pretty sure soapserver
not calling methods on service class. can see soapserver::getfunctions
php2wsdl @soap
annotated methods have been registered soapserver
instance, nothing methods supposed seems happening; no logging, not throw new \exception('@#!?!');
on first line.
the actual symptom have that, after soapclient
tries __soapcall
method (in other application), expects have received soapheader
s (which method might setting; don't know) response headers empty.
code
commented lines things i've been using try , debug.
symfony controller
class defaultcontroller extends controller { const service_uri = 'http://example.com/api'; public function wsdlaction() { $log = new logger('api'); $response = new response(); $response->headers->set('content-type', 'text/xml'); $response->setcontent($this->makewsdl()); // $log->debug(sprintf('[%s] wsdl response', __method__)); return $response; } public function operationaction(request $request) { $log = new logger('api'); try { $wsdlfile = tmpfile(); $wsdlpath = stream_get_meta_data($wsdlfile)['uri']; file_put_contents($wsdlpath, $this->makewsdl()); } catch (exception $e) { $log->error(sprintf('[%s] couldn\'t create temporary wsdl file soapserver: "%s"', __method__, $e->getmessage())); throw $e; } // $c = file_get_contents($wsdlpath); // $log->debug(sprintf('[%s] created wsdl temporary file in %s: %s', __method__, $wsdlpath, $c)); $server = new soapserver( $wsdlpath, [ 'soap_version' => soap_1_1, 'encoding' => 'utf-8', ] ); // $log->debug(sprintf('[%s] created server', __method__)); $server->setobject(new myservice($server, $log)); // $log->debug(sprintf('[%s] set server object', __method__)); // foreach ($server->getfunctions() $f) { // $log->debug(sprintf('[%s] soap function: %s', __method__, (string) $f)); // } $response = new response(); $response->headers->set('content-type', 'text/xml; charset=utf-8'); // $log->debug(sprintf('[%s] create new response', __method__)); ob_start(); // $log->debug(sprintf('[%s] calling server->handle(%s)', __method__, $request->getcontent())); $server->handle($request->getcontent()); // $log->debug(sprintf('[%s] setting response content', __method__)); $response->setcontent(ob_get_clean()); // $log->debug(sprintf('[%s] operate response', __method__)); return $response; } private function makewsdl() { $wsdlgenerator = new php2wsdl\phpclass2wsdl(myservice::class, self::service_uri); $wsdlgenerator->generatewsdl(true); return $wsdlgenerator->dump(); } }
this controller "works". mean, can call route wsdl , wsdl. , can call route operations , work $server->handle($request->getcontent());
throws exception.
myservice
class myservice { private $server; private $log; public function __construct(soapserver $server, logger $log) { $this->server = $server; $this->log = $log; // $this->log->debug(sprintf('[%s] __construct called', __method__)); } /** * @soap */ public function login(array $parameters = []) { // throw new \exception('login throws immediately'); // $this->log->debug(sprintf('[%s] login called: %s', __method__, json_encode($parameters))); $this->server->addsoapheader(new soapheader( 'http://example.com/api', 'authheader', ['token' => 'fake-token'] )); return true; } }
the wsdl generated class php2wsdl seems working perfectly.
the external application calls controller throwing exception because it's expecting authheader
soap header in soap response comes defaultcontroller
. isn't finding one. whether or not attempt use addsoapheader
here correct, can't see login
method being called.
the external application
$this->client = new soapclient('http://example.com/api/wsdl', [ 'trace' => 1, 'encoding' => 'utf-8', 'soap_version' => soap_1_1, 'cache_wsdl' => wsdl_cache_none, 'location' => 'http://example.com/api', ]); ... $response = $this->client->__soapcall( 'login', ['username' => '', 'password' => ''], [], null, $outputheaders ); ... if ($outputheaders['authheader']) { ...
this code throws exception when $outputheaders['authheader']
not set. here, can dump soap requests , responses. here's request:
<?xml version="1.0" encoding="utf-8"?> <envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/api/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" soap-env:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/"> <body> <login> <parameters xsi:type="ns2:map"> <item> <key xsi:type="xsd:string">username</key> <value xsi:type="xsd:string"></value> </item> <item> <key xsi:type="xsd:string">password</key> <value xsi:type="xsd:string"></value> </item> </parameters> </login> </body> </envelope>
and response, of course, empty; output headers.
this code "legacy" bit can't change. bit more background: calls real, third-party soap service , i'm trying @ moment build mock of service can used testing.
Comments
Post a Comment