Configurazione di Deliverance
medio
Up one level
L'intera configurazione di Deliverance va in un file XML. Questo file può configurare corrispondenze di pagina, rule di trasformazione, attività di proxy e impostazioni del server. Sebbene sia tutto in un singolo file, al suo interno esistono molte sezioni. Eccone una breve panoramica:
rule e theme
Determina il theme e applica le effettive trasformazioni alla pagina.
match e classi di pagina
In siti più complicati, le classi di pagina permettono di applicare rule basate su diversi criteri.
impostazioni proxy e server
Controlla le destinazioni del proxy, il server e le impostazioni di sicurezza.
corrispondenza request/response
Molti elementi possono essere usati solo quando la richiesta o la risposta soddisfano determinate condizioni. Tutti questi elementi condividono comportamento e attributi comuni.
Riferimenti pyref Python
Molti elementi possono richiamare espressioni Python.
Console di debug dello sviluppatore
Fornisce informazioni sulle attività di Deliverance, pagina per pagina.
Tutto va in una tag <ruleset>
Rule e Theme
Questo è il nucleo centrale delle funzioni di Deliverance: prende come riferimento un theme assieme al contenuto e vi applica delle trasformazioni.
Theme
L'elemento <theme> definisce il theme che si userà. Il theme viene dato sotto forma di URL. La forma base è:
<theme href="/theme.html" />
Questo definisce il theme come /theme.html. Significa che il theme può stare su dei file che stanno nella stessa macchina di Deliverance, oppure stare ad un indirizzo web (se l'host del theme si trova fuori Deliverance).
Se si ha <theme> nel livello globale (nell'elemento <ruleset>) allora quello è il theme di default. Si può anche inserirlo negli elementi <rule>, dopodiché esso si adeguerà a quell'impostazione, cosa molto utile se si stanno usando classi corrispondenza e pagina.
L'elemento theme supporta inoltre i riferimenti pyref Python. Se si usa:
<theme pyref="mymodule:get_theme" />
Quindi basta definire una funzione come questa:
def get_theme(request, response, log): return "/%s/theme.html" % request.host
Gli oggetti request e response sono oggetti WebOb.
Il nome di default della funzione è get_theme.
Rule
L'elemento <rule> definisce un set di trasformazioni, oltre a supportare il matching tra le classi di pagina e condizioni sulla request/response, della quale parleremo più avanti in questa sezione. Inoltre, come menzionato sopra, è possibile includere un elemento <theme>. Ma la cosa più importante sono le azioni di trasformazione.
Le azioni di trasformazione avvengono in ordine. Il loro punto di partenza è il documento theme, e le azioni copiano gli elementi dal contenuto dentro il theme.
Esistono quattro azioni:
<replace>:
Sostituisce qualcosa all'interno del theme con elementi provenienti dal contenuto.
<append>:
Aggiunge un contenuto in posizione successiva ad un elemento nel theme.
<prepend>:
Aggiunge un contenuto in posizione precedente ad un elemento nel theme.
<drop>:
Rimuove elementi dal theme o dal contenuto.
Selezione e tipi di selezione
Ogni rule dipende dal selezionare elementi dal theme e dal contenuto. La selezione più semplice possibile viene fatta con selettori CSS 3. Ad esempio, questo posiziona l'elemento nel contenuto con la id content dopo l'elemento nel theme con l'id header:
<append content="#content" theme="#header" />
Si possono anche usare i selettori Xpath. Qualunque selettore che inizia con / è trattato come un'espressione XPath, mentre ogni altra cosa è trattata come CSS. Il CSS può solo selezionare elementi, e mentre XPath può selezionare testo o attributi, a Deliverance interessano solo gli elementi. Lo spostare elementi in giro ha dei limiti, per questo esistono differenti tipi di selezione espliciti:
elements:
Di default, applica le regole agli elementi selezionati.
children:
Tipo comune, applica le regole al "children" degli elementi selezionati (incluso il contenuto testuale degli elementi).
attributes:
Applica le rule solo agli attributi. É inoltre possibile applicarlo solo ad alcuni attributi, come ad esempio gli attributi class e style con attributes(class,style):.
tag:
Applica la rule alla tag, ma non al children dell'elemento. Ad esempio la rimozione di una tag mantiene il children nel documento, ma rimuove l'apertura/chiusura della tag in questione.
É possibile creare diverse combinazioni, come content="children:#content". Non è detto che tutte le combinazioni abbiano senso, e non tutte sono consentite. Ad esempio <replace content="attributes:#content" theme="elements:#header" /> non ha senso, dato che non si possono sostituire elementi con delgi attributi. In genere possiamo dire che elements: e children: lavorano assieme, attributes: lavora solo con attributes:, e tag: solo con tag:.
Quando si selezionano gli elementi è possibile usare l'operatore ||. Questo si applica sia ai selettori CSS che XPath, e con questo operatore si possono mischiare. L'operatore || prende i risultati del primo selettore che si accorda con qualcosa. Così content="#content || children:body" prenderà l'elemento #content se presente; in caso contrario prenderà tutti i children di <body>. É possibile mischiare elements: e children: usando ||, sebbene nessun altro tipo possa essere mischiato in questo modo.
<replace>
L'azione <replace> sostituisce qualcosa nel theme con qualcosa nel contenuto. Cosa viene esattamente sostituito dipende dal tipo di selezione. Vediamo alcuni esempi:
<replace content="children:#content-wrapper" theme="children:#content" />
questo sostituisce gli elementi all'interno dell'elemento theme #content con gli elementi che si trovano dentro l'elemento content #content-wrapper. Il documento che ne risulta non avrà alcun elemento con id #content-wrapper (a meno che il theme non abbia già un elemento con quella id).
<replace content="elements:#content-wrapper" theme="elements:#content" /> <replace content="#content-wrapper" theme="#content" />
questi due sono uguali (elements: è il tipo di selezione di default). Questo sostituisce l'elemento theme #content con l'elemento content #content-wrapper. Il documento che ne risulta non ha un elemento #content.
<replace content="attributes:body" theme="attributes:body" />
questo rimuove tutti gli attributi (ad esempio class e onload) dall'elemento <body> nel theme e sposta gli attributi dall'elemento content body.
<replace content="tag:#content" theme="tag:#content" />
questo rimuove la tag #content nel theme con la sua tag corrispondente dal theme. Esse potrebbero non avere lo stesso nome (ad esempio il theme potrebbe essere una <p> e il content <div>), e tutti gli attributi saranno presi dal content.
<append> e <prepend>
Queste due azioni sono molto simili; <append> mette le cose dal content dopo le cose nel theme, mentre <prepend> le mette prima. Alcuni esempi:
<append content="children:#sidenav" theme="children:#sidebar" />
questo sposta il children dell'elemento content #sidenav alla fine dell'elemento theme #sidebar, combinando la navigazione del theme e del content. Se si desidera che la navigazione del content compaia per prima bisognerà usare:
<prepend content="children:#sidenav" theme="children:#sidebar" />
Ecco un altro esempio:
<append content="children:#sidenav" theme="ol.menulinks" />
questo sposta il children di #sidenav dopo l'elemento con l'elemento nel theme <ol class="menulinks">.
<append content="li.reference" theme="children:ol.menulinks" />
questo sposta ogni elemento nel content come <li class="reference"> dentro l'elemento nel theme <ol class="menulinks">.
Appen si può utilizzare anche con degli attributi:
<append content="attributes:div#content" theme="attributes:div#content-wrapper" />
Questo aggiunge qualsiasi attributo da div#content nell'elemento theme div#content-wrapper - quando però l'attributo già esiste nel theme, l'attributo del theme viene mantenuto. Se si usa <prepend> allora quando ci sono attributi sovrapposti l'attributo del content viene mantenuto.
tag: non può essere usato con queste azione.
<drop>
L'azione <drop> viene usata per rimuovere elementi problematici da un theme o un content. si può anche usare con if-content per altre condizioni. Dal momento che questa azione non sposta nessun elemento non è necessario mettere sia l'attributo content che l'attributo theme; ne basta uno e vanno bene entrambi.
Un esempio comune è la rimozione di un foglio di stile che crea conflitti:
<drop content="link[href $= '/sitestyle.css']" />
Questo è uno dei selttori più avanzati permessi da CSS 3. Non si può ancora usare (fiduciosamente) nei browser, ma in Deliverance si! L'operatore $= significa finisce-con, quindi questo selettore potrebbe essere descritto come: tutti gli elementi link con attributi href che finiscono con ‘/sitestyle.css’. Altri operatori sono sempre =, ^= che significa inizia-con, *= che significa contiene. Da notare che tutti i paragoni sono case-sensitive.
Altro esempio:
<drop content="attributes(class):a.external-link" />
rimuove la classe da ogni elemento <a class="external-link">.
<drop content="tag:font" />
rimuove tutte le tag <font>, ma non rimuove alcun contenuto di testo.
if-content
Tutte le azioni possono avere un attributo if-content="selector". Questo selettore viene provato sul contenuto, e se non trova corrispondenze verrà omesso.
Nessuna o molte corrispondenze e errori di gestione
A parte <drop>, nelle azioni è necessario che il selettore di theme corrisponda esattamente ad un elemento. Se questo non avviene con qualunque elemento, allora l'azione non potrà compiersi. Se invece c'è corrispondenza con più elementi l'azione sarà ambigua, poiché non è chiaro quale debba essere l'obiettivo dell'azione. Quando nessun elemento content risulta associato è segno che qualcosa non va, e lo stesso vale in alcuni casi se risultano associati più elementi content.
Il modo standard di gestire tutto questo è di registrare il problema al livello "warn". Se si presentano più corrispondenze inaspettate, la gestione di default è di loggare e usare il primo elemento. Esistono quattro attributi per sovrascrivere questa soluzione:notheme:
Quando non viene ritrovato nessun elemento.
manytheme:
Quando viene trovato più di un elemento.
nocontent:
Quando non viene trovato alcun elemento content.
manycontent:
Quando viene trovato più di un elemento content (e non ha senso rapportato al contesto dell'azione).
Un valore notheme="ignore" significa che l'azione viene ignorata e che viene visualizzato solo un messaggio di livello "debug". Un valore come nocontent="abort" significa che se non ci sono content allora tutte le azioni di theme verranno annullate, e la pagina content senza theme verrà visualizzata. Per manytheme e manycontent si possono indicare first o last (rispettivamente primo e ultimo) per selezionare il primo (default) o l'ultimo elemento. Si possono anche creare combinazioni, come manytheme="ignore:first".
Un esempio:
<replace content="children:#content" theme="children:#content" nocontent="abort" />
Quasi tutte le rule dovrebbero avere almeno un'azione con nocontent="abort", poiché questa è l'azione che sposta il corpo primario del content nel theme. Se non è possibile trovare il corpo primario, quando la pagina verrà visitata dagli utenti essi vedranno solo il theme e non i content.
manycontent si usa quandi si utilizzano tipi di selezione attributes: o tag: - in entrambi i casi tra il theme e l'elemento content ci sarà una corrispondenza uno a uno.
Quando si usa <drop>, è normale ritrovarsi con più theme e elementi content, quindi non ci sarà bisogno di gestirli come errore.
Includere contenuti esterni con href
Oltre a manipolare il theme e il contenuto dei documenti, è possibile importare del contenuto da una terza fonte usando l'attributo href su una rule.
Se si include href il documento in questa allocazione è usato al posto di un documento content normale. Ad esempio:
<append href="/sidebar" content="children:body" theme="children:#sidebar" />
Questi aggiunge tutti gli elementi nel corpo di /sidebar dentro il theme, possibilità che può essere sfruttata pe creare un theme più dinamico. Deliverance di per sè non produce contenuti, né vi apporta modifiche complesse, ma è possibile comunque utilizzare queste inclusioni per introdurre varie fonti di contenuti dinamici in una singola pagina: /sidebar può essere essa stessa una pagina generata dinamicamente.
Spostare e copiare
Di default le azioni spostano elementi dal content al theme. Vale a dire, se si seleziona del contenuto con un'azione, poi le azioni non saranno in grado di accedere a tali elementi content. Tutto ciò si rivela particolarmente utile in casi come questo:
<body> <div class="navigation">links...</div> Some content </body>
con le rule:
<rule> <replace content="children:#navigation" theme="children:#sidebar" /> <replace content="children:body" theme="children:#content" nocontent="abort" /> </rule>
Se gli elementi fossero copiati la navigazione apparirebbe due volte nella pagina risultante. Se proprio si vuole copiare il contenuto invece di spostarlo allora si aggiunga move="0" all'azione.
Azioni standard e suppress-standard
Molte azioni sono definite "standard" e solitamente sono comuni per l'HTML. Le azioni sono:
<rule> <replace content="children:/html/head/title" theme="children:/html/head/title" nocontent="ignore" /> <append content="elements:/html/head/link" theme="children:/html/head" nocontent="ignore" /> <append content="elements:/html/head/script" theme="children:/html/head" nocontent="ignore" /> <append content="elements:/html/head/style" theme="children:/html/head" nocontent="ignore" /> </rule>
Queste copiano il titolo, tutti i link, gli script, o i fogli di stile dal content e li incollano nel theme. Vengono sempre applicate a meno che non si usi <rule suppress-standard="1">.
Match e page class
Nota: se si deve creare un sito semplice, questa parte si può anche ignorare e semplicemente definire un semplice <rule> che si applichi a tutte le richieste. In molti casi però sarà necessario applicare rule specifiche solo ad alcune parti del sito. Ad esempio, applicazioni diverse potrebbero avere navigazione in specifiche parti della pagina; si potrebbe perciò desiderare che la rule faccia aggirare a tale navigazione la pagina specifica di quella applicazione.
Spesso gruppi diversi di rule si applicherannoa diverse parti del sito. Per definire quale rule debba associarsi a una determinata request/response esiste il concetto di "classi di pagina". Esistono classi che si applicano alla pagina, e le rule marcate con quelle classi vengono usate. Immaginiamo ad esempio una pagina che possiede le classi trac e default; queste classi saranno usate:
<rule class="trac">...</rule> <rule class="default">...</rule>
Come avviene con i CSS, ogni rule associata ad una particolare classe verrà eseguita. Sempre come il CSS è possibile avere più classi praticamente ovunque, separate da spazi. Diversamente dal CSS invece le classi sono ordinate, e definiscono l'ordine in cui vengono avviate le rule.
Ci sono molti modi per definire le classi di una pagina. Se si ha la possibilità di controllare il server della themed application si può aggiungere il response header X-Deliverance-Page-Class per controllare quale classe utilizzare. Si può anche aggiungere un attributo class agli elementi del proxy.
Una terza possibilità è <match>. Questi elementi possono aggiungere delle classi in base a delle condizioni sulla request. Per esempio è possibile usarli in questo modo:
<match domain="lists.*" class="lists" />
In questo modo si aggiunge la classe "lists" ad ogni richiesta diretta ad un dominio lists.*. La richiesta corrispondente è descritta in corrispondenza richiesta/risposta.
Impostazioni Proxy e Server
Deliverance è dotato di un proxy, deliverance-proxy, il quale avvia un server e inoltra le richieste HTTP agli altri server di backend (Zope, Apache/PHP, paster, etc).
Le impostazioni delle attività di proxying vanno anche nel file della rule. L'elemento <server-setting> definisce gli aspetti del server, mentre <proxy> deinisce server specifici a cui collegarsi col proxy.
<server-settings>
L'aspetto di questo elemento è il seguente:
<server-settings>
<server>localhost:8080</server>
<execute-pyref>false</execute-pyref>
<display-local-files>false</display-local-files>
<dev-allow>
127.0.0.1
192.168.0.1/24
</dev-allow>
<dev-deny>
192.168.0.121
</dev-deny>
<dev-htpasswd>/etc/deliverance-dev-users.htpasswd</dev-htpasswd>
<dev-user username="bob" password="uncle" />
<dev-expiration>60</dev-expiration>
</server-settings> In realtà non è possibile usare tutto questo assieme, vediamolo quindi punto per punto
<server>:
Indica l'host e la porta da usare. Se si usa localhost o 127.0.0.1 per l'host allora si potranno utilizzare solo connessioni locali. Se si usa 0.0.0.0 allora il server si avvierà su titte le interfacce. Il default è localhost:8080.
<execute-pyref>:
Questo di default restituisce True. Se restituisce True allora gli attributi pyref vengono concessi (vedi la sezione Riferimenti pyref Python). Questo permette a chiunque sia in grado di scrivere alle proprie rule l'abilità di eseguire un codice arbitrario per ogni richiesta, così da poterlo spegnere in caso persone indesiderate vi avessero accesso.
<display-local-files>:
Qualunque file locale verrà trovato di default dalla console di debug dello sviluppatore. Non è un problema se chi vi accede ha in genere un accesso ssh o simili al server; in caso contrario è importante disabilitare questa opzione.
<edit-local-files>:
I file possono essere editati tramite la console di debug dello sviluppatore, a meno che non si includa <edit-local-files>false</edit-local-files>.
Le tag <dev-*> definiscono l'accesso alla console dello sviluppatore.
<dev-allow>:
Questa è una lista di indirizzi IP (o IP+netmask) che hanno il permesso di accesso.
<dev-deny>:
A questi indirizzi è stato specificatamente ritirato il permesso.
<dev-htpasswd>:
Questa è una lista di username e password create col programma Apache htpasswd. Puoi loggarti utilizzando tali credenziali.
<dev-user>:
Invece di usare <dev-htpasswd> è possibile inserire direttamente le username e password. Non è esattamente una buona idea, ma in combinazione con <dev-allow> non è così male. Non è possibile invece usare <dev-allow> e <dev-htpasswd> insieme. Bisogna usare una di queste per accedere alla console.
<dev-expiration>:
Cioè il tempo, espresso in minuti, di durata di una sessione, allo scadere del quale sarà necessario effettuare nuovamente il login. L'impostazione di default è 0 (zero), cioè nessuna scadenza.
<proxy>
L'elemento <proxy> è quello che definisce quali indirizzi mappare. L'esempio classico è:
<proxy path="/trac"> <dest href="http://localhost:10002" /> </proxy>
In questo caso viene associata ogni richiesta all'indirizzo /trac all'indirizzo specificato nell'attributo href dell'elemento dest. Quindi una richiesta a qualcosa del tipo /trac/view/1 andrà a http://localhost:10002/view/1. Se si volesse manternere /trac si può usare <proxy strip-script-name="0">.
Se si desidera passare l'header Host senza cambiamenti sarà necessario usare <proxy keep-host="1">. Ciò in genere consente di rappresentare la request in modo appropriato, ma non è la norma in sistemi simili tanto che spesso il nome originale dell'host si trova solamente in X-Forwarded-Host. Proxy "veri" come Squid di solito conservano l'Host header, mentre invece Apache no, a meno che non lo si configuri in maniera appropriata. Quindi se il sistema è stato per l'attività di proxying usando Apache molto probabilmente non si sta conservando l'Host header.
Puoi anche valutare altre condizioni oltre al path, tieni presente che corrispondenze path complesse come per esempio path="regex:.*/manage$" non funzioneranno; in generale tutte le informazioni presenti nella request/response possono essere utilizzare per effettuare delle configurazioni (matching request/response).
É inoltre possibile aggiungere classi di pagina alla richiesta inoltrata usando <proxy class="page-class">.
Usando <proxy editable="1"> consentirai l'editing dei file reference attraverso la console di debug dello sviluppatore. Per fare ciò bisogna avere un <dest> che faccia riferimento ad una URL del tipo file:///...
Il proxy può contenere svariati elementi...
proxy: <dest>
L'elemento <dest> definisce la destinazione. É necessario disporre di un elemento dest.
Si può dare un valore href sia agli URL http://... che file:///... I file vengono serviti direttamente senza passare da un proxy, sebbene ciò rappresenti un'eccezione rispetto al resto del processo.
Il valore in href può essere un template URI (sebbene solo la forma più semplice di template). Si possono usare header come {Host}, variabili di ambiente come {REMOTE_USER}, oppure la variabile {here} la quale punta alla directory contenente il file rule. Tuttoo questo significa che se il file rule si trova in /etc/deliverance/rules/ruleset.xml, allora {here} punterà a file:///etc/deliverance/rules. Questo template viene sostituito per ogni richiesta, così da poter essere altamente dinamico.
In aggiunta è possibile usare i riferimenti pyref Python, come:
<proxy path="/trac"> <dest pyref="mymodule:get_proxy_dest" /> </proxy>
con la funzione
def get_proxy_dest(request, log):
if not request.remote_addr.startswith('192'):
raise AbortProxy('Bad remote_addr: %r' % request.remote_addr)
return 'http://localhost:10002' Puoi elaborare e far ritornare qualsiasi URL. Meccanismi di templating dell'URI non verranno adottati. Utilizzando AbortProxy, <proxy> verrà saltato e il sistema cercherà un altro proxy. Nel caso in cui non venga trovata nessuna corrispondenza in sistema invierà un messaggio si errore 404).
Se si desidera effettuare un request rewriting (come descritto nella prossima sezione) si può usare <dest next="1"> e le modifiche alla richiesta verranno effettuate; in caso contrario la sezione del proxy verrà saltata.
proxy: <request>
Modifica la richiesta prima che venga inoltrata. É possibile aggiungere degli header e avviare un codice Python contro la richiesta.
Da aggiungere all'header:
<request header="X-Project-Name" content="My Project" />
In alternativa è possibile usare un riferimenti pyref Python, come:
<request pyref="mymodule:modify_proxy_request" />
equipaggiato con il seguente codice:
def modify_proxy_request(request, log):
request.header['X-Project-Name'] = request.host.split('.')[0]
return request Questa request può essere modificata sul posto oppure si può procedere con una nuova request.
proxy: <response>
Modifica la response. Come per la richiesta si possono aggiungere degli header:
<response header="Cache-Control" content="max-age=0" />
E' anche possibile effettuare il rewrite dei link. Se si stanno servendo dei contenuti provenienti da http://othersite.com tutti i link continueranno a puntare a http://othersite.com. La riscrittura dei link implica che tutti quei link che tornano indietro attraverso il proxy verrano riscritti; tra questi sono compresi anche l'header Location, ogni riferimento a domain nei cookie e tutti i link nell'HTML.
<response rewrite-links="1" />
Naturalmente è sempre possibile utilizzare delle pyref:
<response pyref="mymodule:modify_proxy_response" />
con del codice simile al seguente:
def modify_proxy_response(
request, response, orig_base, proxied_base, proxied_url, log):
# orig_base: the original URL base: http://localhost:8080/trac
# proxied_base: where dest sent it to: http://localhost:10001/
# proxied_url: the full destination, e.g.,
# http://localhost:10001/view/1
# request.url: the full original URL, e.g.,
# http://localhost:8080/trac/view/1
response.body += 'look at me!'
return response Matching request/response
Molti elementi sono in grado di valutare condizioni sulla request/response: per esempio l'elemento match, rule e proxy. Tutte e tre utilizzano lo stesso sistema di matching.
Esistono molti attributi che si confrontano con parti diversi della request o della response. Se si utilizzano condizioni su attributi multipli è necessario che siano tutte soddisfatte.
Match stringhe
E' possibile confrontare attributi di tipo stringa basandosi su dei pattern che puoi fornire. Esistono molti tipi di pattern; diversi tipi di attributi hanno come impostazione di default diversi tipi di pattern, quello più logico per il valore dell'attributo.
Prima di tutto ecco un elenco degli attributi:
path:
Permette di valutare delle condizioni sul path contenuto nella request. Il pattern di default è path:.
domain:
Viene valutato il request host, il nome del dominio della URL. Il pattern di default è wildcard-insensitive:.
Ogni pattern string può iniziare con patterntype: che definisce proprio il tipo di pattern. Di seguito trovate una lista di pattern disponibili (questi si applicano anche alla corrispondenza chiave/valore descritta nella sezione successiva):
wildcard:
In pratica la corrispondenza carattere jolly, significa che è possibile usare *.
wildcard-insensitive:
Caratteri jolly che non distinguono tra maiuscole e minuscole.
regex:
Corrisponde con una regular expression. Da notare che si possono usare cose come (?i) per far si che un'espressione non distingua tra maiuscole e minuscole.
path:
Permette di valutare una stringa come path. Assomiglia molto a "starts-with", tranne per il fatto che riconosce il simbolo /. Ne consegue che path:/some-path selezionerà percorsi come /some-path/to/a/place, /some-path/ e /some-path, ma non /some-path-to-somewhere.
exact:
Corrisponde ad una stringa precisa.
exact-insensitive:
La stringa precisa, senza curarsi delle maiuscole e minuscole.
contains:
Vero se il pattern appare nella stringa.
contains-insensitive:
Come sopra, senza curarsi di maiuscole e minuscole.
boolean:
Verifica se la stringa è "vera". I valori "1", "true", "yes" e "on" sono da considerarsi come veri. Vuoto, o qualunque altro valore, è falso. Nel caso di boolean:not verrà invertito il valore della condizione
Condizioni Chiave/Valore
Altre condizioni possono essere costruite sulla base di match tra chiave/valore, permettendo di valutare valori associati a chiavi corrispondenti a header e variabili di ambiente. Ne risulta qualcosa di simile a environ="REMOTE_USER: bob", come key: pattern. La chiave può essere un carattere jolly, e se una qualunque chiave compatibile con quel carattere jolly corrisponde anche al pattern allora si ha una corrispondenza. I caratteri jolly possono essere utilizzati per valutare le chiavi. Tutti i pattern hanno come default exact:.
Gli attributi disponibili sono i seguenti:
request-header:
Valuta una header della request. Gli header sono case-insensitive
response-header:
Valuta un response header.
environ:
Valuta variabili di ambientea.
PyRef
E'possibile utilizzare delle pyref, con funzioni simili alla seguente:
def match_request(request, response, response_headers, log):
if response.headers.get('x-notheme'):
raise AbortTheme
return True
Si noti che response-headers è una lista di tutti gli header, inclusi gli header <meta http-equiv>.
Riferimenti pyref Python
Gli attributi pyref consentono di far riferimento a del codice Python. Per maggiori dettagli consultare il documento pyref.
Console di debug dello sviluppatore
Per visualizzare questo strumento occorre essere loggati. Per effettuare il login: /.deliverance/login - per definire l'utente utilizzare la configurazione server-settings.
Dopo aver effettuato il login sarà possibile aggiungere ?deliv_log ad ogni URL di pagina per avere un log al fondo della pagina. Il log illustra nei dettagli come la pagina sia stata trasformata, incluse informazioni su come il proxy sia stato scelto e ogni sotto-rischiesta. Inoltre permette di navigare la sorgente coinvolta, di vedere cosa i selettori selezionano nel contenuto o nel theme, oppure di ottenere una lista di id e classi interessanti che si trovano nel contenuto.
Theming lato client
Esiste una caratteristica sperimentale che permette la creazione di temi lato client-side usando Javascript. Questa tecnica consiste nel servire una struttura vuota del tema all'utente, con contenuti via via reperiti tramite chiamate XMLHttpRequest. Ciò significa che l'utente potrà ottenere una risposta rapidamente, visualizzando la struttura vuota della pagina theme con cui iniziare (in questo modo il theme dovrebbe essere scritto in modo tale che ogni slot contenga testo come "Loading..." nell'attesa di riempire la pagina definitiva con i chunk di contenuti ritornati via XMLHttpRequest). I singoli chunk inseriti saranno cachabili da parte del cliente.
Per abilitare tutto ciò inserire ciò che segue nella configurazione.
<clientside /> Ad esso possono anche essere aggiunte delle condizioni, come <clientside path="/slow-part" />. In questo caso si può usare un solo theme, dato che le classi di pagina non ottengono una corrispondenza prima che il theme sia stato inviato. Inoltre ogni rule che fa uso di espressioni href="..." devono poter essere applicate anche utilizzando un ordine diverso, visto che le chiamate di XMLHttpRequest potrebbero susseguirsi in ordini inaspettati. Ci possono essere dei problemi se per esempio si usano <replace> e <append> sullo stesso elemento - una soluzione migliore potrebbe essere quella di sgomberare l'elemento theme target ed usare <prepend> e <append>.
Deliverance utilizzerà questa tecnica con cautela. Le pagine in questione verranno inviate solo a client che abbiano Javascript abilitato (ciò avviene impostando un cookie via Javascript e poi testando su richieste successive se il cookie è impostato oppure no). Inoltre le pagine non saranno elaborate prima di sapere se viene ritornato dell'html dalla richiesta di backend. Se queste condizioni non sono vere ci si atterrà alla normale attività di theming lato server-side, cosa che non dovrebbe comportare sostanziali differenze.
Quanto ripostato è stato testato solo su Mozilla Firefox.