ugrás a tartalomhoz

Php Soap xsd nem szűr

inf · 2010. Júl. 6. (K), 16.31
Sziasztok!
Csináltam egy Soap tesztet, az a para vele, hogy nem szűri meg az xsd alapján az átvitt objektumokat.

probe.wsdl:

<?xml version="1.0" encoding="utf-8" ?>
<definitions
    name="probe"
    targetNamespace="http://test.omg/probe"
    xmlns:tns="http://test.omg/probe"
   
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
>
    <types>
        <xsd:schema>
            <xsd:import schemaLocation="probe.xsd" namespace="http://test.omg/probe" />
        </xsd:schema>
    </types>
    <message name="testRequest">
        <part name="testUser" type="xsd:User" />
    </message>
    <message name="testResponse">
        <part name="testMessage" type="xsd:Message" />
    </message>
    <portType name="probePortType">
        <operation name="test">
            <input message="tns:testRequest"/>
            <output message="tns:testResponse"/>
        </operation>
    </portType>
    <binding name="probeBinding" type="tns:probePortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
        <operation name="test">
            <soap:operation soapAction="http://test.omg/probe/test"/>
            <input>
                <soap:body namespace="http://test.omg/probe" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body namespace="http://test.omg/probe" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
    </binding>
    <service name="probeService">
        <port name="probePort" binding="probeBinding">
            <soap:address location="http://localhost/service/service.php"/>
        </port>
    </service>
</definitions>
probe.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://test.omg/probe"
>
<xsd:complexType name="User">
<xsd:all>
<xsd:element name="name" type="xsd:string" minOccurs="1" maxOccurs="1" />
</xsd:all>
</xsd:complexType>
<xsd:complexType name="Message">
<xsd:all>
<xsd:element name="code" type="xsd:integer" minOccurs="1" maxOccurs="1" />
<xsd:element name="content" type="xsd:string" minOccurs="1" maxOccurs="1" />
</xsd:all>
</xsd:complexType>
</xsd:schema>
service.php:
  1. class Dispatcher  
  2. {  
  3.     protected $controller;  
  4.      
  5.     public function __construct($controller)  
  6.     {  
  7.         $this->controller=$controller;  
  8.     }  
  9.      
  10.     public function __call($method,$arguments)  
  11.     {  
  12.         if (!method_exists($this->controller,$method))  
  13.         {  
  14.             throw new SoapFault(404,'Called action '.get_class($this->controller).'.'.$method.' does not exist!');  
  15.         }  
  16.         $result=call_user_func_array(array($this->controller,$method),$arguments);  
  17.         return $result;  
  18.     }  
  19. }  
  20.   
  21. class WebService  
  22. {  
  23.     protected $wsdl;  
  24.     protected $dispatcher;  
  25.     protected $server;  
  26.      
  27.     public function setController($class)  
  28.     {  
  29.         $this->wsdl=$class.'.wsdl';  
  30.         if (!file_exists($this->wsdl))  
  31.         {  
  32.             throw new SoapFault(404,'The '.$class.' wsdl file for service does not exist!');  
  33.         }  
  34.         if (!class_exists($class,true))  
  35.         {  
  36.             throw new SoapFault(404,'The '.$class.' service does not exist!');  
  37.         }  
  38.         $this->dispatcher=new Dispatcher(new $class());  
  39.     }  
  40.      
  41.     public function run()  
  42.     {  
  43.         $this->server=new SoapServer($this->wsdl);  
  44.         $this->server->setObject($this->dispatcher);  
  45.         $this->server->handle();  
  46.     }  
  47. }  
  48.      
  49. class ServiceBus  
  50. {  
  51.     public function dispatch($controller)  
  52.     {  
  53.         $service=new WebService();  
  54.         $service->setController($controller);  
  55.         $service->run();  
  56.     }  
  57. }  
  58.   
  59.   
  60. class User  
  61. {  
  62.     public $name;  
  63.     public $test;  
  64. }  
  65.   
  66. class Message  
  67. {  
  68.     public $code;  
  69.     public $content;  
  70.     public $test;  
  71. }  
  72.   
  73. class Probe  
  74. {  
  75.     public function test($user)  
  76.     {  
  77.         $message=new Message();  
  78.         $message->code=1;  
  79.         $message->content=var_export($user,true);  
  80.         $message->test='valami';  
  81.         return $message;  
  82.     }  
  83. }  
  84.   
  85. ini_set('soap.wsdl_cache_enabled',0);  
  86. $bus=new ServiceBus();  
  87. $bus->dispatch('Probe');  
client.php:
  1. ini_set("soap.wsdl_cache_enabled","0");       
  2.   
  3. class User  
  4. {  
  5.     public $name;  
  6.     public $test;  
  7. }  
  8.   
  9. class Message  
  10. {  
  11.     public $code;  
  12.     public $content;  
  13. }  
  14.   
  15. try{  
  16.     $probe=new SoapClient('probe.wsdl');  
  17.     $user=new User();  
  18.     $user->test='valami';  
  19.     $user->name='Egy kis szöveg.';  
  20.     $message=$probe->test($user);  
  21.     var_dump($message);  
  22. }  
  23. catch(SoapFault $e)  
  24. {  
  25.     var_dump($e);  
  26. }  
A kérés eredménye:
  1. object(stdClass)#3 (3) {  
  2.   ["code"]=>  
  3.   int(1)  
  4.   ["content"]=>  
  5.   string(87) "stdClass::__set_state(array(  
  6.    'name' => 'Egy kis szöveg.',  
  7.    'test' => 'valami',  
  8. ))"  
  9.   ["test"]=>  
  10.   string(6) "valami"  
  11. }  
Mint látható a 'test' példányváltozó lazán átment. Ez normális viselkedés, vagy én rontottam el valamit?
 
1

PHP SOAP

janoszen · 2010. Júl. 6. (K), 16.58
A PHP SOAP interfésszel rengeteg szívásunk volt (pl ez: http://bugs.php.net/bug.php?id=50675) úgyhogy nem biztos hogy jól jársz ha erre építesz. Felhő régebben említette a WSO2-t mint lehetséges csere.
2

Köszi

inf · 2010. Júl. 7. (Sze), 12.57
Köszi, tényleg szopás, megnézem a wso-t. Annyi bonyolultsága van a dolognak, hogy én nem az alkalmazás logika szétosztására akarom használni a soap-ot, hanem js->php adatátvitelre. Szal gyakorlatilag a Controller-eket hívnám meg Soap-pal javascriptből.
3

JSON

Ifju · 2010. Júl. 7. (Sze), 15.50
JSON-RPC nem lenne célszerűbb javascript kiszolgálására?
4

Hát nekem első sorban amiatt

inf · 2010. Júl. 8. (Cs), 02.12
Hát nekem első sorban amiatt tetszett meg a SOAP, mert nagyon szépen lehet vele XSD-vel validáltatni. Gyakorlatilag remote call-t szeretnék, valahogy így:

js:
  1. new Package(  
  2. {  
  3.     Security: new Class(  
  4.     {  
  5.         login: Soap.Action  
  6.     }).Extends(Soap.WebService),  
  7.     User: new Class(  
  8.     {  
  9.         setEmail: Class.Setter,  
  10.         setPassword: Class.Setter  
  11.     })  
  12. }).bind(window);  
  13. //itt a window-ra bindelem a package-t, ez annyit jelent, hogy az ott megadott osztályok window alatt jelennek meg, tehát global namespace-ben...  
  14. //a Soap.Action automatikusan hívja az osztály nevének megfelelő service-ben a metódus nevének megfelelő action-t  
  15.   
  16. try  
  17. {  
  18.     var user=new Security().login(new User().setEmail('test##kukac##test.com').setPassword('myPass'));  
  19.     alert('sikeres belépés ['+user.getName()+']');  
  20. }  
  21. catch(fault)  
  22. {  
  23.     alert('sikertelen belépés ['+fault.getMessage()+']');  
  24. }  
  25.   
  26. //a security.login-ből kijövő user nem ugyanaz, mint amit paraméterként megadtam, mert visszafele már csak name tulajdonsággal küldi a szerver  
php:
  1. namespace MyProject\Controllers;  
  2.   
  3. class Security extends \Engine\Soap\WebService  
  4. {  
  5.     public function login(\MyProject\Models\User $user)  
  6.     {  
  7.         if ($user->login())  
  8.         {  
  9.             return $user;  
  10.         }  
  11.         else  
  12.         {  
  13.             $fault=new SoapFault();  
  14.             $fault->setMessage('gond');  
  15.             return $fault;  
  16.         }  
  17.     }  
  18. }  
  19.   
  20. //a frontController ezt példányosítja a javascript kérés alapján  
  21. //a wsdl-t az osztály neve alapján tölti be egy fájlból  
  22. //a wsdl-ben megadott adat típus hasonló elnevezésű, mint a Model osztály, ebből tudja a rendszer, hogy melyik osztályt kell betölteni (erre még nem találtam ki a konkrét koncepciót)  
  23. //az User osztályt autoload-dal tölti be  
wsdl:
Gyakorlatilag azt írja le, hogy a login-nál a bejövő ojjektum User osztályú, és email és password példányváltozók értékeit kell, hogy hozza, a kimenő pedig szintén User osztályú, és a name példányváltozót viszi csak vissza. Nyilván így a be és kimenő adatok xml schema típusa eltérő, de az osztályuk azonos. (Egyelőre még nem tudom, hogy ez megvalósítható e complexType restriction-nel, vagy muszáj lesz elnevezésekkel játszani, ezért nem írok konkrét példát.)


Ha ilyen szintű távoli eljáráshívást meg lehet oldani JSON-RPC-vel, akkor szívesen átállok rá, sajnos még nem volt szerencsém megnézni. (A lényeg, hogy js-ben nagyjából sikerült megoldanom, hogy legyenek osztályok, és ugyanolyan példányokat szeretnék használni távoli eljáráshívásra, mint bármilyen oo nyelvben.)
5

Belenéztem

inf · 2010. Júl. 8. (Cs), 02.49
Megnéztem, és szerintem a validálásra nem lesz elég. Az osztály nevének az átvitelét meg lehet oldani, max lefoglalok rá egy kulcsot, viszont a validálása sokkal gyengébb, mint amire egy xsd képes. Egyelőre most xsd-vel fogok foglalkozni pár napig, amíg kitalálom, hogy hogyan lehet vele az átvitt példányváltozókra megszorítást csinálni. Ha összejön, akkor a wso2-t fogom felhasználni, ha nem, akkor lehet, hogy belenézek a json-rpc forrásába, hátha tovább tudom fejleszteni olyanra, ami nekem kell.

Microsoft is csinált valami újabb rendszert távoli dolgokra .NET-ben, de sajnos most nem jut eszembe a neve :S