XML-RPC webszolgáltatás készítése PHP5-ben
December 5th, 2007
PHP-ben az xmlrpc bővítménnyel tudunk XML-RPC szolgáltatást készíteni. A bővítmény előnye, hogy C nyelven íródott, így biztosan jobb teljesítményt nyújt, mint más PHP-ben írt XML-RPC könyvtárak. Annak ellenére, hogy már négy éve létezik, sajnos még mindig "experimental" státuszban van. A PHP oldalán elég gyenge dokumentáció olvasható róla, ezért megpróbálom azokat az információkat röviden felsorolni, amelyek nekem hiányoztak.
Az RPC protokollok közül a legismertebbek az XML-RPC és a SOAP.
A távoli eljáráshívás (RPC) lehetővé teszi programunkból más rendszerek API-ját használni. Távoli eljáráshívás alatt azt értjük, hogy meghívunk egy eljárást. Az eljárásnak paramétereket adhatunk át. A távolí eljáráshívás annyiban különbözik a helyi eljáráshívástól, hogy a meghívott eljárást egy másik rendszer valósítja meg, általában egy távoli számítógépen. Az XML-RPC párbeszéd két részből áll: az ügyfél kérelméből és a kiszolgáló válaszából. A kérelmet át kell alakítani egy szabványos nyelvre, el kell küldeni, majd a kiszolgálónak a kérelmet át kell alakítania a számára érthető formára. Ezt a folyamatot “marshalling”-nak nevezzük. Ez természetesen meglehetős lassulással jár.
A kommunikáció HTTP protokollon keresztül történik, az üzenetváltás pedig XML formában. A PHP-hez írt xmlrpc bővítmény csak a kérelem dokumentumok előallítására és a válasz dekódolására szolgál.
Lássunk példát egy egyszerű kérelemdokumentumra:
A válasz szintén XML formátumú:
Hiba esetén ilyen XML dokumentumot kapunk vissza:
Az xmlrpc bővítmény szerencsére elvégzi helyettünk az XML-dokumentumok előállítását és visszaalakítását (dekódolását)
az xmlrpc_encode_request() és xmlrpc_decode() függvények segítségével.
string xmlrpc_encode_request(string method, mixed params [, array output_options])
mixed xmlrpc_decode(string $xml [, string $encoding])
XML-RPC kiszolgáló létrehozása
Az XML-RPC kérések mindig HTTP POST-ként vannak elküldve. A következő módon tudjuk elérni a nyers POST adatot:
Második lépésben létrehozzuk a kiszolgálót:
A harmadik lépés során visszahívott függvényeket (callback) írunk és meghatározzuk, hogy az egyes bejövő kérelmeket melyik visszahívott függvények fogják ellátni.
Lássunk erre egy példát:
Mielőtt visszaküldenénk valamit is a kliensnek, be kell állítanunk az adat adattartalom típusát (content type).
Utolsó lépésben feldolgozzuk a kérelmet és visszaadjuk a kigenerált XML-dokumentumot.
A kliens megírása
Egy távoli eljárás meghívása a következő lépésekre bontható:
- Az xmlrpc_encode_request() függvénnyel legyártatjuk az XML-lekérést.
- A legyártott XML-dokumentumot elküldjük a távoli kiszolgálónak (a letölthető forráskódban az XmlRpc_Client osztály valósítja ezt meg).
- A visszakapott választ az xmlrpc_decode függvénnyel alakítjuk át a PHP saját adattípusára
Az XML-RPC szolgáltatás leírása (Introspection)
Van néhány rezervált függvénynév, amelyeknek speciális feladata van. Ezek a függvények arra szolgálnak, hogy információkat kérjünk le a tagfüggvényekről (függvények paraméterlistái, a paraméterek adattípusai, a függvény visszatérési értéke, stb.). Lényegében a WSDL-hez hasonló célt szolgálnak. Az XML-RPC szolgáltatások automatikus felderítését teszik lehetővé.
- system.listMethods
- Visszaadja a kiszolgáló által megvalósított összes tagfüggvény nevét.
- system.methodHelp
- A tagfüggvény neve alapján megadja a lehetséges prototípusokat.
- system.methodSignature
- Fogadja a tagfüggvény nevét, és a leírásával tér vissza.
- system.describeMethods
- fully describes the methods and types implemented by this XML-RPC server.
- system.multiCall
- executes multiple methods in sequence and returns the results
- system.getCapabilities
- returns a list of capabilities supported by this server
Az xmlrpc bővítményünk szerencsére (majdnem) automatikusan létrehozza helyettünk ezeket a tagfüggfényeket. Mivel a PHP nyelv nem típusos nyelv, ezért saját magunknak kell megadni a típusokat. Ehhez egy XML dokumentumot kell írnunk, amiben az általunk megvalósított tagfüggvényeket írjuk le.
Ezután meg kell irnunk PHP-ben egy függvényt, ami beolvassa a diszkről ezt az XML-fájlt és visszaadja.
Az xmlrpc_server_register_introspection_callback() függvénnyel regisztráljuk az előbb megírt tagfüggvényt. Ez a módszer azért jó, mert az XML-fájl csak akkor lesz beolvasva és feldolgozva, ha tényleg szükség van rá (on demand), azaz amikor egy kliens érdeklődik a webszolgáltatásunk tagfüggvényeiről.
Ezekkel a speciális függvényekkel az a baj, hogy szinte egyik XMLRPC webszolgáltatás sem implementálta őket (például a Flickr és a WordPress sem). Valószínűleg semmilyen szabvány sem írja ezt elő. Mindenesetre én jó ötletnek tartom, hiszen nem sok munkába kerül, és lehetséges automatikus úton dokumentációt generálni belőle (lásd lentebb a linkeket) a webszolgáltatásunkat használni kivánó fejlesztők részére.
Tagfüggvényeinknek akár többféle paraméterezése (signature - szignatúrája) is lehetséges (egyfajta method overloading). Sajnos az XMLRPC bővítmény nem jól adja vissza a túlterhelt tagfüggvények paraméterezését. Ezt az észrevételemet ezen a fórumon írtam le XMLRPC introspection hiba. Ez azért nem jó hír, mert ha automatikusan szeretnénk kigenerálni a webszolgáltatásunk tagfüggvényeinek listáját automatikus felderítéssel, akkor a túlterhelt tagfüggvények paraméterezése nem lesz jó. Kerülő megoldásnak megírhatunk egy XSLT stíluslapot, ami a meta.xml fájlból készítene dokumentációt.
Letölthető példakód
Megírtam egy rövid, de hasznos példaalkalmazást, amely jó kiindulópont lehet azoknak, akiknek gyorsan kell XML-RPC webszolgáltatást készíteni.
Kipróbálható online is:
- HTML-interfész a tagfüggvények kipróbálására (csak Firefox böngészővel működik)
- A tagfüggvények leírása XML-fájlban
- Letölthető forráskód
És mi a helyzet a SOAP-al?
Egy webszolgáltatás megírása előtt el kell döntenünk, hogy SOAP-ot, vagy XML-RPC-t használjunk-e. Ilyenkor figyelembe kell vennünk a következő tényezőket:
- programozási nyelv
- milyen programozási nyelven íródott kliensek fogják használni a webszolgáltatást
- enterprise méretű webszolgáltatást írunk-e
A SOAP mellett szól, hogy W3C-szabványos leírónyelven kommunikál, és kliens-alkalmazások megírása is egyszerűbb.
Ha PHP-ben egyszerű lenne SOAP kiszolgáló megírása, gondolkodás nélkül a SOAP-ot választanám. ASP.NET-ben például egy SOAP szerver létrehozása gyerekjáték, szinte semmivel sem kell törődnünk, mindenről a .NET gondoskodik. PHP-be azonban egyáltalán nem könnyű és fáradságmentes egy SOAP szerver megírása. Magunknak kell megírni a WSDL (Web Services Description Language - webszolgáltatás-leíró nyelv) fájlt, ami jónéhány hosszú W3C-ajánlás elolvasását követeli meg. Erre meglehetősen sok idő elmegy, így sokan az XML-RPC-t használják PHP-ben.
Ha webszolgáltatásunkat csak PHP kliensek fogják használni, nyugodtan használjunk XMLRPC-t. Komoly méretű webszolgáltatáshoz mindenképpen a SOAP-ot tudom javasolni. A WSDL fájl megírásában esetleg segítségünkre lehet a Zend Studio WSDL generátora. Más ötletem nincsen, hogyan lehetne megúszni a WSDL fájl fáradságos megírását.
Remélem ez a rövid összefoglalás hasznos útmutatást adott azoknak, akik most tervezik saját webszolgáltatás írását.

Leave a Reply