Att skriva Spinner µLPC skript
Att skriva Spinner µLPC skript
I dokumentet nedan utgår jag ifrån att du har grundläggande
kunskaper i µLPC programmering
Ett Spinner µLPC-skript är en liten programsnutt (egentligen ett µLPC
objekt) som körs när användaren tittar på sidan, dvs, istället för att
returnera skriptet returneras det som skriptet returnerar.
Defenitionen av ett skript är mycket enkel.
Nedan följer ett som implementerar ett gammalt känt testfall:
string|mapping parse(object request_id)
{
return "Hello world!\n";
}
Om du skapar filen public_spinner/test.lpc i ditt hemdir med
innehåll enligt ovan, och sedan accessar
http://www.lysator.liu.se/~ditt_namn/test.lpc, så kommer du
att få se 'Hello world' i din Netscape.
Men hur gör man för att föra lite mer intressanta saker, var finns
information om forms-variables, prestate och liknande? Jo, i objektet
request_id.
request_id - objektet med all info
Nedan följer en mycket kortfattad beskrivning av de flesta variablerna
i objektet i fråga:
- int time;
- När gjordes uppkopplingen? Sekunder sedan 00:00:00 den 1/1 1970.
- object conf;
- Current configuration, en pekare till den virtuella server som
requesten kom till (alltså den server som din modul ligger i).
Du behöver nog inte den här variabeln, om du inte vill utföra udda
operationer.
- string raw_url;
- URLen helt oparsad som den kom från klienten.
- mapping (string:string) variables;
- I HTTP finns det en kul sak som heter 'variabler', de kommer oftast
från en 'form'.
I den här mappingen finns allihop instoppade, färdigparsade.
Exempelvis:
En förfrågan efter filen /goo/bar?hmm=hej&foo=%20%20 kommer
att resultera att variables sätts till ([ "hmm":"hej", "foo":" "]).
- mapping (string:array (string)) misc;
- Blandat smått och gott.. Du behöver nog inte bry dig, men man kan ju
alltid skriva ut fältet för att se vad det innehåller:
return sprintf("%O", request_id->misc);
- list (string) prestate;
- Prestate används mycket, iallafall på Lysator.
Det är en lista med strängar, man kan alltså göra saker som
if(request_id->prestate->nobg)
no_background = 1;
Prestate skrivs innan filnamet I URLen, så här: /(foo,bar)/goo/bar
- list (string) config;
-
Config fungerar precis som prestate, men det lagras inte undan i
URLen, utan i client-side cookies. Detta har flera fördelar:
- Den syns inte i URL-en
- Användaren kommer att ha kvar sin config även om hon avslutar sin
Netscape och startar den igen.
- Om folk lägger upp länkar till dina sidor i sina sidor kommer de
inte att inkludera konfigurationen.
Men även några nackdelar:
- Det kan bara finnas en lista med konfigurerade val per server.
- Det är svårt att bli av med sin konfiguration.
- Bara Netscape implementerar dem än.
För att addera något till 'config' låter man användaren accessa en fil enligt:
http://din.server:port/<+config,-config,...>/riktig/URL
Användaren kommer då att få configen tillagd till cookien
Spinner-Config i sin klient, och få en redirect till
/riktig/URL. Detta är mycket Spinner specifikt..
- list (string) supports;
- Vad klienten kan hantera.
Innehållet i den här listan kommer från filen etc/supports, per
default. Det hela kan ändras i konfigurationsinterfacet.
Används lämpligtis för att konditionellt generera kod till olika klienter
Exempel:
if(request_id->supports->tables)
return make_table();
else
return make_pre();
- string remoteaddr;
- IP-nummret till datorn på andra sidan förbindelsen, som en sträng
("158.126.90.157")
- array (string) client;
- Vilken klient som frågar efter sidan, en array eftersom protokollet
(HTTP/1.*) dumt nog tillåter flera User-Agent: header rader, och man
vet ju aldrig..
Lämpligtvis använder man '*' operatorn för att få en sträng av det
hela (request_id->client*""). Ofta är det dock mycket
smartare att använda supports istället för client.
- array (string) referer;
- Den (eller de..) sidor som refererade till den här sidan.
- list (string) pragma;
- Alla pragma headrar klienten har skickat. Intressant är 'no-cache',
som skickas när man trycker på 'reload' av de flesta klienter.
- string prot;
- Det protokoll som användes för att generara frågan, troligtvis
HTTP/1.0 eller HTTP/1.1, men även saker som FTP, GOPHER och HTTP/0.9
kan förekomma.
- string method;
- Metod, troligtvis 'GET'.
- string rest_query;
- Allt efter ett '?' i URL-en som inte är variabler.
- string raw;
- Hela requesten som rå data.
- string query;
- Allt efter '?' i URLen.
- string not_query;
- Allt innan '?' i URLen exklusive prestate, det är det här som används
av spinner för att få fram vilka moduler som requesten ska mappas
genom.
- string data;
- Allt i en BODY i requesten. Oftast inte mycket, men vid metoden POST
används det till alla variabler.
- array (int|string) auth;
- Antingen 0 (ingen authentifiering skickad av klienten),
({ 0, "username:password" }) (authentifiering skickad, men auth
modulen tycker inte att den är korrekt, och
användaren finns inte ens),
({ 0, "username" }) (authentifiering skickad, men auth
modulen tycker inte att den är korrekt, och
användaren finns)
eller
({ 1, "username" }) (authentifiering skickad, och auth modulen tycker att den är korrekt)
- mapping (string:string) cookies;
- Alla cookies som klienten har skickat.
Fast det räcker ju inte riktigt att ha tillgång till all data, man
måste kunna returnera data också. Det gör man enligt nedan:
Att returnera data
Det enklaste fallet är att man helt enkelt returnerar en sträng. Den
strängen kommer sedan att skickas genom Spinners parser, precis som
vanliga HTML filer. Det kan vara mycket smidigt att returnera vanlig
SPML kod från sina lpc skript.
Man kan annars returnera en mapping.
Att själv sätta ihop en mapping av det slag som ska returneras kan
vara lite knivigt. Därför finns det en hel del hjälpfunktioner.
Alla är defenierade i filen lpc/http.lpc, som ärvs av spinnerlib, som
man i sin tur lämpligen ärver i sina skript om man tänker använda de
här funktionerna.
- mapping http_string_answer(string data, string|void type);
- Returnera en sträng som resultat, typen är text/html om inget annat
anges. Strängen kommer inte att parsas av spinner innan den
returneras till klienten.
-
mapping http_file_answer(object fp, string|void type, void|int len);
- Returnera en fil som resultat, typen är text/html om inget annat
anges. Om man inte anger längden kommer spinner att ta reda på den
själv. fp ska vara en instans av /precompiled/file, eller ett objekt
som implementerar samma metoder (du vill inte, jag lovar..)
- mapping http_redirect( string url, object|void request_id )
- En redirect till den url som anges. Om man skickar med request_id, och
dessutom anger en relativ URL kommer prestate att adderas till URLen
helt automatiskt.
- mapping http_auth_failed(string realm)
- Begär lösenord (authentifiering) inom namnrymden 'realm' på denna
server. Netscape sparar undan ett användarnamn och lösenord för varje
realm på varje server i minnet.
- mapping http_auth_required(string realm, string message)
- Samma sak som auth_failed, nästan, men man kan skicka med ett
felmeddelande som visas om användaren väljer 'nej tack', och en liten
annan kod används. Namnet säger nog det mesta -- required - Användaren
har inte försökt logga in innan, och failed -- användaren
misslyckades. Ingen WWW-läsare som jag har sett skiljer på de här två
resultatkodena.
- mapping http_low_answer(int error_code, string message)
- Returnera ett meddelande med 'error_code' som felkod. Se HTTP
specifikationen för en lista med dylika, eller
/usr/www/spinner/server/include/variables.h
Kan användas så här:
if(search(lower_case(request_id->client*""), "aol") != -1)
return http_low_answer(402,
"Please enter your VISA number and expiration date below:\n");
Om du hör till de som tycker att det är kul att pilla med detaljerna
så är det här hur returmappingen egentligen ser ut: (alla fält kan
utelämnas, men om man utelämnar alla samtidigt blir det inte mycket
till svar.)
([
"file":file_object,
"data":"string",
"len":int,
"type":"main/sub",
"raw":0|1,
"leave_me":0|1,
"extra_heads":([ "name":"value, ... ]),
"error":int,
])
- file
- Ett filobjekt som ska skickas till klienten. Skickas efter eventuell "data".
- data
- En sträng som ska skickas innan "file".
- len
- Längden av data och file ihop. Om du inte specifierar det här kommer
den att räknas ut av Spinner.
- type
- mime typen som det som du skickar tillbaka har.
Om du inte defenierar en kommer "text/plain" att användas.
- raw
- Om du sätter den här variabeln kommer _inget_ förutom det som
du skriver att skickas till klienten. Du måste alltså generera alla
headrar och liknande själv.
- leave_me
- Om du sätter den här variablen kommer inget att skickas till klienten
av Spinner, och du förväntas hantera all socketkommunikation och
upprensning själv. Används av proxy modulerna.
- extra_heads
- Dessa huvudfält kommer att adderas till svaret.
Ett användbart värde är ([ "Expire":http_date(time()), ])
Nu kommer skriptets returvärde att expira direkt.
- error
- HTTP svarskoden som ska användas. 200 är normalt, alla koder finns
defenierade i spinner/server/include/variables.h (den mest
feldöpta filen i hela Spinner, skulle jag tro.)
Nu finns det bara några få saker till att känna till om skripten: