UMEÅ UNIVERSITET 22 september 2003 Institutionen för datavetenskap Laboration 1 XML-RPC David Granström <ei01dgm@cs.umu.se> http://www.cs.umu.se/ ei01dgm/rapport_lab1.pdf kommentarer Handledare: Magnus Janlert, Jonas Birmé
Introduktion I Denna laboration har vi fått till uppgift att fördjupa oss i något middleware. Vi har valt XML- RPC på grund av att vi ville lära oss ett middleware som vi kan använda oss av i laboration 2. För att testa XML-RPC laddade vi hem exempelfiler och lade dem på en server med apache och php4. 5 Metoden returnerar resultatet till XML- RPC-processen som packar ihop det till ett XML-dokument. 6 Servern returnerar XML-dokumentet till den som gjort HTTP-POST-begäran. 7 XML-RPC-klienten kollar igenom XMLdokumentet och skickar returvärde till klientprogrammet[2]. Allmänt om XML-RPC XML-RPC är en enkel specifikation för att skicka Remote Procedure Calls (RPC) över Internet med hjälp av extensible Markup Language (XML). XML-RPC är designat för att vara så enkelt som möjligt. Datat som man vill skicka lagras i XML-dokument och skickas över Internet via protokollet Hyper Text Transport Protocoll (HTTP). XML-RPC har utvecklats av Userland software, mer specifikt av Dave Winer som också bidragit till SOAP. XML-RPC är till för att göra funktionsanrop mellan applikationer i nätverk oberoende av plattform. XML-RPC används till största del för att bygga webservices. Det finns många implementationer för XML- RPC: Perl, Python, Java, Frontier, C/ C++, Lisp, PHP, Microsoft.NET, Rebol, Real Basic, Tcl, Delphi, WebObjects och Zope[2][4]. Hur fungerar det? 1 Ett klientprogram gör ett funktions anrop och använder sig av en XML-RPC-klient och specifierar metodnamn, parametrar och vilken server metoden ligger på. 2 XML-RPC-klienten paketerar sedan metodnamn och parametrar i XML-format. Sedan utfärdar klienten en HTTP-POST-begäran som innehåller information till servern. 3 HTTP-server tar emot paketet och skickar det till XML-RPC-listener (programmet på servern som tillhandahåller alla metoder). 4 XML-RPC-listener kollar igenom XMLdokumentet och skickar parametrarna till rätt metod Figur 1: Så här fungerar flödet i XML-RPC[4] Överföring av data När man gör ett proceduranrop till en annan dator på tex Internet så konverteras proceduranropet till ett XML-dokument som använder HTTP-protokollet för att skicka iväg anropet. När anropet kommer till servern exekveras koden och returnerar svaret eller ett felmeddelande (se Felmeddelanden). Svaret kommer även tillbaka i XML-form. Parametrar kan skickas som heltal, strängar, arrayer, datum etc, men även binär datöverföring är möjlig med hjälp av base64- encoding. Det saknas NULL-värde i XML-RPC, dvs avsaknad av värde. Det har inte gjorts något åt den saken officiellt men det finns en experimentell version in en JAVA-implementation. Då kallas NULL-värdet nil <nil/>. Ett exempel på ett XML-RPC-anrop: POST /RPC2 HTTP/1.0 User-Agent: Frontier/5.1.2 (WinNT) Host: betty.userland.com Content-Type: text/xml Laboration 1 2 22 september 2003
Content-length: 181 <?xml version="1.0"?> <methodcall> <methodname>getcapitalcity</methodname> <params> <param> <string>sweden</string> </param> </params> </methodcall> Header Här finns information om servern och vilka protokoll som används. Body I denna sektion finns namnet på den anropade metoden och dess parametrar. I det här fallet skickas strängen Sweden. Hela meddelandet är inkapslat i en <methodcall>... </methodcall>. Det är under taggen <params> som alla skickade parametrar hamnar inkapslade i taggen <param> här finns även parameterns datatyp som tag. Ett exempel på ett XML-RPC-svar: HTTP/1.1 200 OK Connection: close Content-Length: 158 Content-Type: text/xml Date: Fri, 17 Jul 1998 19:55:08 GMT Server: UserLand Frontier/5.1.2-WinNT <?xml version="1.0"?> <methodresponse> <params> <param> <string>stockholm</string> </param> </params> </methodresponse> Header Svarskoden måste alltid vara 200 OK för XML- RPC därför XML-RPC lägger sig ovan på HTTP-protokollet istället för att utöka det. Body Här returneras svaret Stockholm på funktionsanropet[2][4]. Används det i praktiken? I så fall hur och var? Red Hat, Inc Använder sig av XML-RPC I deras implementation av komponenter I Red Hat Network. XML-RPC används i registrerings processen, up2date och rhnsd vid kommunikation (med HTTP) med Red Hat Network servers. Det används också internt som middleware. Triple Point Technology, Inc. http://www.tpt.com De använder sig av XML-RPC i sin produkt genom kommunikation med deras olika servrar[4][3]. Felhantering XML-RPC har en liknande felhantering som Java med exceptions. Om ett error uppstår i behandlandet av ett anrop så skickas en <fault>...</fault> struktur i svaret. En fault struktur innehåller två medlemmar, ett XML- RPC-värde som är en felkod och en sträng som beskriver problemet/felet. Det finns ingen standard för felkoder eller felmeddelanden så den som får tillbaka ett fel får lita på den sträng som beskriver felet. Felkoderna är olika för olika implementationer. Om man själv skriver felkoder bör man börja på höga nummer. I PHP implementation till exempel så måste felkoderna börja på 800[2]. Ett exempel på hur ett felmeddelande kan se ut: HTTP/1.1 200 OK Connection: close Content-Length: 426 Content-Type: text/xml Laboration 1 3 22 september 2003
Date: Fri, 17 Jul 1998 19:55:02 GMT Server: UserLand Frontier/5.1.2-WinNT <?xml version="1.0"?> <methodresponse> <fault> <struct> <member> <name>faultcode</name> <int>4</int> </member> <member> <name>faultstring</name> <string>too many parameters.</string> </member> </struct> </fault> </methodresponse> Minneshantering XML-RPC är tillståndslöst eftersom den använder sig av HTTP-protokollet. Om minne behövs så får man använda sig av sessioner[2]. Säkerhet Det finns ingen säkerhet inbyggd XML- RPC-standarden, eftersom XML-RPC använder HTTP som är ett öppet protokoll. Detta innebär att ansvaret ligger hos programmeraren. Om högre säkerhet önskas kan man kryptera med t. ex. SSL, eller så kan man tunnla det m. h. a. SSH, eller skicka via Viritual Private Network(VPN), samt via protokollet HTTPS[2]. Exempel En demokod från XML-RPC[1] provkördes på en apacheserver via php4, källkoden finns i appendix A, B. Denna kod skickar ett message innehållande två tal till servern mha RPC. Detta sker genom att konvertera meddelandet till XML och skicka det via HTTP. Just detta exempel frågar efter summan och differensen mellan två tal. Servern skickar tillbaks svaret till klienten, som lätt kan presentera svaret i webbläsaren. (se fig 2) Figur 2: Resultat från ett RPC-annrop Dettaexemplet körs genom att lägga filerna server.php client.php i public html- katalogen samt lägga dit filerna xmlrpc.inc och xmlrpcs.inc, som finns på XML-RPC s hemsida [1]. Resurser Information om XML-RPC hittar man på den officiella hemsidan http://www.xmlrpc.com. Mjukvara: Mjukvara för C/C++, JAVA finns att ladda ner på http://xmlrpcc.sourceforge.net/ Referenser [1] Kidd, E. XML-RPC Howto. Websida, 10 sept. 2003. http://xmlrpc- c.sourceforge.net/xmlrpc-howto/- xmlrpc-howto.html. [2] St Laurent, S., Johnston, j., och Dumbill, E. Programming Web Services with XML-RPC, first uppl. O Reilly & Associates, inc., 101 Morris Street Sebastopol, CA95472, 2001. [3] www.redhat.com. Websida, 10 sept. 2003. http://www.redhat.com. [4] www.xmlrpc.com. Websida, 10 sept. 2003. http://www.xmlrpc.com. Laboration 1 4 22 september 2003
A client.php <html> <head> <title>xml-rpc PHP Demo</title> </head> <body> <h1>xml-rpc PHP Demo</h1> <?php include xmlrpc.inc ; // Make an object to represent our server. $server = new xmlrpc_client( /api/sample.php, xmlrpc-c.sourceforge.net, 80); // Send a message to the server. $message = new xmlrpcmsg( sample.sumanddifference, array(new xmlrpcval(5, int ), new xmlrpcval(3, int ))); $result = $server->send($message);?> // Process the response. if (!$result) { print "<p>could not connect to HTTP server.</p>"; } elseif ($result->faultcode()) { print "<p>xml-rpc Fault #". $result->faultcode(). ": ". $result->faultstring(); } else { $struct = $result->value(); $sumval = $struct->structmem( sum ); $sum = $sumval->scalarval(); $differenceval = $struct->structmem( difference ); $difference = $differenceval->scalarval(); print "<p>sum: ". htmlentities($sum). ", Difference: ". htmlentities($difference). "</p>"; } </body> </html> Laboration 1 5 22 september 2003
B server.php <?php include xmlrpc.inc ; include xmlrpcs.inc ; function sumanddifference ($params) { // Parse our parameters. $xval = $params->getparam(0); $x = $xval->scalarval(); $yval = $params->getparam(1); $y = $yval->scalarval(); } // Build our response. $struct = array( sum => new xmlrpcval($x + $y, int ), difference => new xmlrpcval($x - $y, int )); return new xmlrpcresp(new xmlrpcval($struct, struct )); // Declare our signature and provide some documentation. // (The PHP server supports remote introspection. Nifty!) $sumanddifference_sig = array(array( struct, int, int )); $sumanddifference_doc = Add and subtract two numbers ;?> new xmlrpc_server(array( sample.sumanddifference => array( function => sumanddifference, signature => $sumanddifference_sig, docstring => $sumanddifference_doc))); Laboration 1 6 22 september 2003