Perl og SOAP
SOAP er et dårligt valgt akronym. Det står for Simple Object Acces Protocol, og er en standard for kommunikation imellem webbaserede tjenester ved hjælp af HTTP-protokollen og XML. Det er et dårligt akronym, fordi SOAP faktisk er en slags klister - det sætter vidt forskellige tjenester og klienter sammen, uanset om platformen hedder J2EE, .Net - eller om der blot er tale om et gement Perl-script bag en Apache-webserver.
Den slags kaldes remote procedure call - fjernkald - og SOAP angiver en standard som er uafhængig af platform og sprog. Perl har et svimlende antal klassebiblioteker, og et af dem hedder SOAPLite. Det er ikke en letvægtsimplementering, som man ellers kunne tro ud fra navnet, men det hentyder til, at biblioteket er utroligt nemt at bruge. Selv om man ikke har tænkt sig at benytte Perl, kan denne artikel forhåbentlig vise, at det ikke er særligt svært at komme i gang med egne webtjenester - både fra klient- og serversiden. Først skriver vi en simpel SOAP-tjeneste og dens tilhørende klient. Dernæst ser vi på, hvorledes vi nemt kan tilgå eksisterende tjenester via SOAPLite.
Apache og Perl
For at demonstrere serverdelen skal vi bruge en webserver, som for eksempel Apache, og Perl skal bruges både til klientdelen og serverdelen. Disse eksempler er afviklet under Windows 98. Apache downloades fra Apache.org, og Perl til Windows fra ActiveState. Installationen er i begge tilfælde lige ud af landevejen, men vi skal lige have sat Perl op som CGI-modul, og det er ganske nemt og forklares i ActiveStates dokumentation. Man behøver ikke at bruge Apache - hvis man for eksempel har IIS kørende i forvejen, kan den også nemt benyttes, og det står også i den førnævnte dokumentation.
Serveren
SOAPLite følger med de moduler, som kommer med ActiveState-pakken, så det er bare at sætte sig ned og kode løs. Eksemplerne her bygger på SOAPLites Quick Start Guide.
Til at starte med kan man lige teste sin opsætning med scriptet test.pl, som kunne se sådan ud:
#!C:\Perl\bin\perl.exe
use CGI qw(:standard) ;
print header();
print "Hej verden";
I den første linje skal stien sættes til at pege på perl-fortolkeren, hvis den skulle ligge et andet sted end C:\perl\bin\. Filen test.pl placeres i cgi-bin mappen i Apaches rod-folder (under Windows sædvanligvis i C:\Programmer\Apache Group\Apache), og derefter indtastes
http://localhost/cgi-bin/test.pl
i browseren, og så skulle serveren gerne returnere
Hej verden
Så langt, så godt. Nu skaber vi først en SOAP-servertjeneste og en SOAP-klient. Det er kun server-scriptet, som betjener sig af webserveren. Klienten benytter kun Perl via de indbyggede HTTP-klientfunktioner, og scriptet afvikles fra et DOS-vindue.
SOAPLite implementerer alle de nødvendige funktioner, så vi kommer slet ikke til at se XML-kode eller noget som helst i dette kodeeksempel. SOAPLite putter funktionskaldet ind i en XML-konvolout, som danner rammen om et SOAP-kald.
Server-scriptet ser således ud:
#!C:\Perl\bin\perl.exe
use SOAP::Transport::HTTP;
SOAP::Transport::HTTP::CGI
-> dispatch_to('Demo')
-> handle;
package Demo;
sub hi {
return "Hej verden";
}
sub bye {
return "goodbye, cruel world";
}
sub languages {
return ("Perl", "C", "sh");
}
Gem scriptet i en tekstfil med navnet hibye_server.pl i cgi-bin mappen.
Modulet SOAP::Transport::HTTP importeres i tredje linje, og den ordner det hele for programmøren. Metoden dispatch_to i klassen SOAP::Transport::HTTP::CGI videresender indkomne SOAP-forespørgsler til pakken Demo, som er defineret længere nede i scriptet, og handle-metoden fortæller, at forespørgslen skal håndteres.
Nede i Demo-pakken er der defineret et par dummy-funktioner. Ideen er, at klienten kalder disse funktioner, og det håndteres helt transparent i Perl. Forvirret? Læs videre, det er ganske nemt, når vi ser på klient-scriptet. Men lad os først lige slå fast, at klienten ikke er webbaseret - den afvikles blot via en kommando-prompt.
Klienten
Klient-scriptet ser sådan ud:
use SOAP::Lite;
print SOAP::Lite
-> uri('http://localhost/Demo')
-> proxy('http://localhost/cgi-bin/hibye_server.pl')
-> hi()
-> result;
Her kalder vi metoder i klassen SOAP::Lite, og de to sidste metoder er nemmest at forklare, så dem ordner vi først. hi() er simpelthen kaldet til hi()-funktionen i vores Demo-pakke i server-scriptet, og result spytter svaret ud vores DOS-vindue.
De to første metodekald er straks værre. Metoden med det lidt mystiske navn proxy indeholder webadressen til cgi-scriptet på serveren. Her i eksemplet kører det hele lokalt, men det kunne være hvor som helst på internettet.
Den anden metode, uri, er svær at forklare uden at tale sort, men vi gør et forsøg. Metoden skal kaldes med en uri som parameter, og det er en slags generaliseret webadresse, som definerer et navnerum i relation til den konkrete anvendelse. Til de fleste SOAP-kald har den ingen betydning, men i forbindelse med SOAP som Perl-til-Perl bindemiddel skal uri sættes til den pakke på den fjerne maskine, hvis metode man vil invokere. Eksemplet illustrerer forhåbentlig anvendelsen.
Gem scriptet under navnet hibye_client.pl, og kør det i et DOS-vindue med kommandoen
C:\Programmer\Apache Group\Apache\cgi-bin>perl hibye_client.pl
- så skulle Perl invokere vores hi()-metode i Demo-klassen via SOAP, og den returnerer Hej verden, som klient-scriptet skriver ud i DOS-vinduet.
Man kan prøve at skifte kaldet i klienten ud med en af de andre metoder i Demo-pakken, for eksempel bye().
Kaptajn Haddock
Det virker nemt. Alt for nemt, faktisk, for det er ikke rigtigt til at se det helt vildt smarte. Så lad os lige se et eksempel på, hvorledes en SOAP-kuvert ser ud:
<env:Envelope xmlns:env="http://www.w3.org/2001/06/
soap-envelope">
<env:Header>
<n:alertcontrol xmlns:n="http://example.org
/alertcontrol">
<n:priority>1</n:priority>
<n:expires>2001-06-22T14:00:00-05:00</n:expires>
</n:alertcontrol>
</env:Header>
<env:Body>
<m:alert xmlns:m="http://example.org/alert">
<m:msg>Pick up Mary at school at 2pm</m:msg>
</m:alert>
</env:Body>
</env:Envelope>
Dette eksempel er taget fra World Wide Web-konsortiets udkast til SOAP 1.2. Som man ser, er der en del at holde rede på, og derudover er der hele HTTP-processen, som skal lægges oven i hatten. SOAPLite klarer alle ærterne for os, uden at vi får snavs på fingrene.
Lad os nu se på et eksempel, hvor vi benytter en eksisterende SOAP-baseret webtjeneste, som altså kan være implementeret i alt muligt andet end Perl. Og hvor finder man sådan en? Det gør man på webstedet SOAPClient.com, som har en fyldig oversigt over mange forskellige webtjenester.
De fleste af dem er kun rene demonstrationstjenester, men en enkelt stikker ud, og er virkelig brugbar. Det er en svensk tjeneste, som returnerer prøver på den berømte sø-ulk Kaptajn Haddocks kraftudtryk på flere sprog, blandt andre svensk og hollandsk.
Insjögangsters
I dokumentationen til Captain Haddock Curser, som er tjenestens formelle navn, kan vi se at den understøtter to metoder, hvoraf den ene, Curse, returnerer den ønskede tekststreng. Ved hjælp af ganske få ændringer i vores klient-script, kan vi få adgang til Kaptajnens gloser. Det ser sådan ud:
use SOAP::Lite;
print SOAP::Lite
-> uri('')
-> proxy('http://www.tankebolaget.se/scripts/'.
'Haddock.exe/soap/IHaddock')
-> Curse()
-> result;
Det er jo næsten magen til vores klient fra før, på nær at proxy-metodens argument sættes til den svenske tjeneste, og den fjerne metode, vi invokerer hedder altså Curse().
Når vi kører scriptet, fortæller Kaptajnen os, at han ikke ved hvilket sprog, vi ønsker:
Miserable earthworms! I can't swear in that language!
Ved at sætte en streng-variabel, LangCode, kan det styres, hvilket af sprogene tjenesten skal returnere gloserne i. Sådan en variabel skal indpakkes i SOAP, og SOAPLite har en klasse med tilhørende metode, som klarer ærterne for os:
#!C:\Perl\bin\perl.exe
use SOAP::Lite;
my $lang = "se";
print SOAP::Lite
-> uri('')
-> proxy('http://www.tankebolaget.se/scripts/'.
'Haddock.exe/soap/IHaddock')
-> Curse(SOAP::Data->name('LangCode' => $lang))
-> result;
Og så får vi:
insjögangsters!
Jeg er ikke helt klar over, hvordan glosen lyder i Jørgen Sonnergaards vidtberømte Hergé-oversættelser. Skal vi gætte på ferskvandsgangstere?
SOAPClient.com indeholder også en webbaseret SOAP-klient, som man kan bruge til at teste sine server-scripts med. Der kan siges vældig meget mere om SOAP, men som eksemplerne her viser, så er det altså ikke mere kompliceret, end at man nemt kan komme i gang.