Table of Contents
Previous Chapter
I dokumentet nedan utgår jag ifrån att du har grundläggande kunskaper i uLPCprogrammering.
Ett Spinner uLPC-skript är en liten programsnutt (egentligen ett uLPC objekt) som körs när användaren tittar på sidan, dvs, istället för att returnera skriptet returneras det som skriptet returnerar.
Definitionen 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.ulpc i ditt hemdir med innehåll enligt ovan, och sedan accessar http://www.lysator.liu.se/~ditt_namn/test.ulpc, så kommer du att få se 'Hello world' i din Netscape.
Men hur gör man för att göra lite mer intressanta saker, var finns information om forms-variables, prestate och liknande? Jo, i objektet request_id. Se tabell 1 nedan.
--------------------------------------------------------------------------------------------------------------- Variabel Förklaring --------------------------------------------------------------------------------------------------------------- int time; När gjordes uppkopplingen? Sekunder sedan 00:00:00 den 1/1 1970. object conf; 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 I HTTP finns det en kul sak som heter 'variabler', de kommer oftast från en (string:string) variab 'form'. les; I den här mappingen finns allihop instoppade, färdigparsade. Exempel. En förfrågan efter filen/goo/bar?hmm=hej&foo=%20
kommer att resul tera att variables sätts till([ "hmm":"hej", "foo":" "])
. mapping (string:array Blandat smått och gott. Du behöver nog inte bry dig, men man kan ju alltid (string)) misc; skriva ut fältet för att se vad det innehåller: return sprintf("%O", request_id->misc); Här kan du även definiera dina egna variabler, om du mot all förmodan behöver det. Du bör dock se till att dina variabler har unika namn, om du inte vill råka ut för otrevliga överraskningar. Variablerna är request-lokala. 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 inklu dera 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. Man kan också använda SPML för att göra det<aconf +/-CONFIG></ aconf>
. 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ämpligtvis för att generera olika 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 pragmaheadrar 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 generera 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) ·({ 1, "username" })
(authentifiering skickad, och auth modulen tycker att den är korrekt) mapping Alla cookies som klienten har skickat. (string:string) cookies; ---------------------------------------------------------------------------------------------------------------
Fast det räcker ju inte riktigt att ha tillgång till all data, man måste kunna returnera data också.
Det enklaste fallet är att man helt enkelt returnerar en sträng. Den strängen kommer sedan att skickas genom Spinners parser. I annat fall så måste man 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.
lpc/http.lpc
, som ärvs av
spinnerlib.
---------------------------------------------------------------------------------------------------------- Funktion Förklaring ---------------------------------------------------------------------------------------------------------- mapping Returnera en sträng som resultat, typen är text/html om inget annat http_string_answer(string anges. Strängen kommer inte att parsas av spinner innan den returneras data, string|void type); till klienten. mapping Returnera en fil som resultat, typen är text/html om inget annat anges. http_file_answer(object fp, Om man inte anger längden kommer spinner att ta reda på den själv. fp string|void type, void|int len); ska vara en instans av /precompiled/file mapping http_redirect( string En redirect till den url som anges. Om man skickar med request_id, och url, object|void request_id ) dessutom anger en relativ URL kommer både prestate och state att adderas till URLen. mapping Begär lösenord (authentifiering) inom namnrymden 'realm' på denna http_auth_failed(string realm) server. Netscape sparar undan ett användarnamn och lösenord för varje realm på varje server i minnet. mapping Samma sak som auth_failed, nästan, men man kan skicka med ett fel http_auth_required(string meddelande som visas om användaren väljer 'nej tack', och en liten realm, string message) annan kod används. Namnet säger nog det mesta -- required - Använda ren har inte försökt logga in innan, och failed -- användaren misslycka des. Ingen WWW-läsare som jag har sett skiljer på de här två resultatkodena. mapping Returnera ett meddelande mederror_code
som felkod. Se HTTP http_low_answer(int specifikationen för en lista med dylika, eller/usr/www/spinner/ error_code, string message) 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"); ----------------------------------------------------------------------------------------------------------
------------------------------------------------ tag förklaring ------------------------------------------------ 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 mimetypen som det som du skickar tillbaka har. Om du inte definierar en kommertext/ plain
att användas. raw Om du sätter den här variabeln kommer inget förutom det som du skriver att skickas till klien ten. 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 kli enten av spinner, och du förvän tas hantera all socket kommunikation och upprens ning själv. Används av proxy modulerna. extra_heads Dessa huvudfält kommer att adderas till svaret. Ett använd bart 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 definierade i/usr/ www/spinner/server/ include/variables.h
(den mest feldöpta filen i hela Spinner..) ------------------------------------------------
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, ])
Nu finns det bara några få saker till att känna till om skripten:
Dvs om man returnerar ett så laddas skriptet inte om. Ovanstående exempel tillåter bara att man laddar om det om man har med formsvariabeln reload=<nånting, precis vad som helst> när man trycker på reload.
Det är lite olyckligt att Garbs utgivning sammanfaller med väldigt intressanta saker som händer med WWW-servern Spinner/Roxen. Det olyckliga ligger i att det infaller så dumt att Garb inte hinner rapportera om det intressanta som inträffar den 9:e september men ändå påverkar det korrektheten i artiklarna i och med att vissa namn är ändrade.
Jag hoppas och tror att artiklarna trots allt är intressanta.