L’archivio del tag «xml»

Ho pensato di affrontare in un paragrafo separato una questione particolare riguardante il reindirizzamento (redirect 301). Ed è il caso di scrivere «tratto da una storia vera»: ho passato due o tre ore a risolvere il problema in questione verificatosi sul mio sito.
Immaginiamo di avere pubblicato sul nostro sito una serie di documenti da mostrare (e evidentemente far scaricare) ai visitatori. Tali documenti sono raccolti in una directory del nostro server ma, durante i lavori di aggiornamento del nostro sito, abbiamo deciso di spostarli da un’altra parte (oppure semplicemente rinominare la directory). I nostri visitatori fedeli, però, sono abituati ad aprire i loro documenti preferiti con i loro indirizzi (URL) vecchi. Probabilmente hanno pure pubblicato dei link diretti su internet… Come possiamo proteggerli dall’errore 404?
Il problema si risolve con il file di configurazione del server (.htaccess o web.config).

1. La soluzione con il web.config
Nel caso di un server IIS (hosting Windows) dobbiamo risolvere il problema lavorando sul file web.config.
Ipotizziamo un problema con un indirizzo URL da riscrivere in modo complesso. Ipotizziamo dunque di avere un archivio pubblico dei libri in PDF raggruppati in sottocartelle chiamate con i cognomi degli autori. Di conseguenza, l’indirizzo di ogni file è http://sito.it/download/booksinpdf/nomeautore/nomelibro.pdf
La nostra biblioteca digitale è grande, quindi le componenti che ho messo in corsivo sono ovviamente varie e numerose. Noi abbiamo trasferito tutti i pdf e vogliamo essere certi che i visitatori li aprano sempre senza problemi agli indirizzi nuovi: http://sito.it/files/booksinpdf/nomeautore/nomelibro.pdf
Nell’indirizzo nuovo ho messo in corsivo anche la parte modificata.
La soluzione è la seguente:

<rule name="redirect PDFs" stopProcessing="true">
<match url="download/booksinpdf/([0-9A-Za-z ]+)/([0-9A-Za-z ]+).pdf$" />
<action type="Rewrite" url="files/booksinpdf/{R:1}/{R:2}.pdf" />
</rule>

Le componenti variabili sono racchiuse tra le parentesi tonde e vengono riprese nella fase di reindirizzamento nelle parentesi graffe. La loro quantità e posizione, naturalmente, variano in base alle necessità concrete.
Un’altra osservazione è banalissima: tale metodo funziona per tutte le estensioni dei file: .mp3, .jpg, .doc etc.

2. La soluzione con il .htaccess
Nel caso di un server Apache (hosting Linux) siamo costretti a lavorare con il file .htaccess.
La logica del reindirizzamento dovrebbe essere come descritta di seguito, anche se non ho avuto il modo di sperimentarla sulla pratica (sto sul server IIS, quindi ho risolto il caso come descritto sopra).
Ipotizziamo un problema con un indirizzo URL da riscrivere in modo complesso. Ipotizziamo dunque di avere un archivio pubblico dei libri in PDF raggruppati in sottocartelle chiamate con i cognomi degli autori. Di conseguenza, l’indirizzo di ogni file è http://sito.it/download/booksinpdf/nomeautore/nomelibro.pdf
La nostra biblioteca digitale è grande, quindi le componenti che ho messo in corsivo sono ovviamente varie e numerose. Noi abbiamo trasferito tutti i pdf e vogliamo essere certi che i visitatori li aprano sempre senza problemi agli indirizzi nuovi: http://sito.it/files/booksinpdf/nomeautore/nomelibro.pdf
Nell’indirizzo nuovo ho messo in corsivo anche la parte modificata.
La soluzione è la seguente:

RewriteEngine on
RewriteRule ^download/booksinpdf/(.+)/(.+\.pdf)$ files/booksinpdf/$1 [L]

Tale metodo deve funzionare per tutte le estensioni dei file: .mp3, .jpg, .doc etc.


Se il vostro sito rimane attivo per molti anni, cresce qualitativamente e si riempie con dei nuovi contenuti, a un certo punto sentirete la necessità di modificare la sua struttura. Modificarla per renderla meglio organizzata e più logica. Di conseguenza, molte (o addirittura tutte) le pagine del sito cambieranno il nome e/o collocazione (da una sezione all’altra). Forse vorrete anche trasferire il sito a un altro dominio.
Ma sicuramente non vorrete perdere i visitatori abituali, quelli che conoscono già gli indirizzi vecchi del sito, delle sezioni e delle pagine. Per evitare che sugli schermi di quei visitatori compaia la scritta «pagina non trovata» (errore 404), dobbiamo fare in modo che il browser dell’utente venga reindirizzato automaticamente al nuovo indirizzo di ciò che sta cercando di visualizzare.
Il reindirizzamento può essere fatto in due modi:
a. con il file di configurazione del server;
b. con uno script da inserire nel codice delle pagine che si trovano all’indirizzo vecchio.
È inutile chiedermi qual è il modo migliore: ognuno dei due può essere il più adatto alle concrete caratteristiche tecniche del vostro sito. Quindi io mi limito a descriverli. La scelta sulla applicazione, invece, spetta a voi.
Cominciamo con i file di configurazione del server: può essere il file .htaccess (nel caso di un server Apache) o il file web.config (nel caso di un server IIS).
1. Il redirect (reindirizzamento) con il .htaccess
Prima di tutto controlliamo se nella root esiste già questo file: nel caso positivo – e il più probabile – lavoriamo su quello, altrimenti lo creiamo da zero. E ora passiamo agli esempi concreti.
1.1. Per il reindirizzamento verso un nuovo dominio (per esempio, se il vostro sito si è trasferito) dovete inserire nel file .htaccess del server del vecchio dominio il seguente codice (ovviamente cambiando i domini):

RewriteEngine On
RewriteCond %{HTTP_HOST} vecchio.it
RewriteRule (.*) http://nuovo.it/$1 [R=301,L]

1.2. Per il reindirizzamento da una pagina del sito all’altra (può essere utile, per esempio, se l’indirizzo di una pagina è stato modificato) nel file .htaccess del vostro sito va inserito questo codice:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.dominio\.it$ [NC]
RewriteRule ^categoria/nomepagina/$ http://www.dominio.it/nuovapagina/ [R=301,L]

1.3. Per il reindirizzamento da una pagina qualsiasi del sito verso la pagina iniziale serve questo codice:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.dominio\.it$ [NC]
RewriteRule ^categoria/nomepagina/$ http://www.dominio.it/ [R=301,L]

1.4. Mentre nel caso contrario, cioè per il reindirizzamento dalla pagina iniziale a un’altra pagina del sito, serve questo codice:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.dominio\.it$ [NC]
RewriteRule ^$ http://www.dominio.it/categoria/nomepagina/ [R=301,L]

1.5. Per il reindirizzamento da tutte le pagine in generale verso quella iniziale va inserito questo codice:

RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule !(^$|.*\.(css|jpg|gif)) / [R=301,L]

1.6. Per il reindirizzamento dai domini vecchio.it e www.vecchio.it al nuovo dominio nuovo.it inserite, invece, questo codice:

RewriteCond %{HTTP_HOST} ^vecchio\.it
RewriteRule ^(.*)$ http://nuovo.it/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www.vecchio\.it
RewriteRule ^(.*)$ http://nuovo.iy/$1 [R=301,L]

(l’utilizzo di questo codice è pero possibile e sensato solo per alcuni piani tariffari di hosting)
1.7. Qualora sul vostro server fosse attivo il modulo mode_rewrite, potreste avere la necessità di realizzare il reindirizzamento dal dominio con il www al dominio senza il www. In tale caso inserite il seguente codice:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

1.8. Se, invece, dovete fare l’opposto, quindi reindirizzare da un dominio senza il www allo stesso domino con il www, inserite questo codice:

RewriteEngine On
RewriteCond %{HTTP_HOST} !^(www.) [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

1.9. Qualora avreste la necessità di reindirizzare tutti gli indirizzi delle vostre pagine al protocollo HTTPS (perché lo avete appena attivato oppure perché i vostri visitatori non sanno che lo state utilizzando sul sito), inserite questo codice:

RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

1.10. Inoltre, dobbiamo ricordarci che per i motori di ricerca gli URL http://www.dominio.it/ e http://www.dominio.it sono diversi. Di conseguenza, bisogna decidere quale URL utilizzare: quello con il slash finale o quello senza. Per togliere il slash finale dagli indirizzi di tutte le pagine del vostro sito, inserite il seguente codice:

RewriteEngine On
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} /$ [NC]
RewriteRule ^(.*)(/)$ $1 [L,R=301]

1.11. Invece per aggiungerlo sempre, utilizzate questo codice:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*[^/])$ $1/ [L,R=301]

1.12. A volte potrebbe anche essere utile sostituire a tutti i file l’estensione .htm con l’estensione .html – in tal caso inserite il seguente codice:

RewriteEngine on
RewriteBase /
RewriteRule ^(.*)\.htm$  $1.html [R=permanent]

Infine precisiamo una cosa importante: se nel vostro file .htaccess viene utilizzata più di una regola (per esempio, più regole prese da questo paragrafo), la riga «Rewrite Engine on» va utilizzata comunque solo una volta.

2. Il redirect (reindirizzamento) con il web.config
La logica della costruzione delle regole in un file web.config è altrettanto semplice. Quindi vediamo solo gli esempi principali.
Prima di tutto controlliamo se nella root esiste già questo file: nel caso positivo – e il più probabile – lavoriamo su quello, altrimenti lo creiamo da zero. E ora passiamo agli esempi concreti.
2.1. Per il reindirizzamento verso un nuovo dominio (per esempio, se il vostro sito si è trasferito) dovete inserire nel file web.config del server del vecchio dominio il seguente codice (ovviamente cambiando i domini):

<rule name="301 Redirect 1" stopProcessing="true">
<match url=".*" />
<action type="Redirect" url="http://nuovodominio.it" redirectType="Permanent" />
</rule>

2.2. Per il reindirizzamento da una pagina del sito all’altra (può essere utile, per esempio, se l’indirizzo di una pagina è stato modificato) nel file web.config del vostro sito va inserito questo codice:

<configuration>
  <location path="pagina1.html">
    <system.webServer>
      <httpRedirect enabled="true" destination="http://nomesito.it/pagina2.html" httpResponseStatus="Permanent" />
    </system.webServer>
  </location>
</configuration>

2.3. Per il reindirizzamento da una pagina qualsiasi del sito verso la pagina iniziale serve questo codice:

<rule name="redirect to home">
<match url="^nomepagina\.php" ignoreCase="false" />
<conditions>
<add input="{QUERY_STRING}" pattern="^$" ignoreCase="false" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="http://www.dominio.it/" />
</rule>

2.7. Potreste avere la necessità di realizzare il reindirizzamento dal dominio con il www allo stesso dominio senza il www. In tale caso inserite il seguente codice:

<rule name="remove www" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^www\.(.+)$" />
</conditions>
<action type="Redirect" url="http://{C:1}/{R:1}" redirectType="Permanent" />
</rule>

2.8. Se, invece, dovete fare l’opposto, quindi reindirizzare da un dominio senza il www allo stesso domino con il www, inserite questo codice:

<rule name="redirect to www" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^dominio.it$" />
</conditions>
<action type="Redirect" url="http://www.dominio.it/{R:0}" redirectType="Permanent" />
</rule>

2.9. Qualora avreste la necessità di reindirizzare tutti gli indirizzi delle vostre pagine al protocollo HTTPS (perché lo avete appena attivato oppure perché i vostri visitatori non sanno che lo state utilizzando sul sito), inserite questo codice:

<rule name="redirect to https" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
</rule>

2.10. Inoltre, dobbiamo ricordarci che per i motori di ricerca gli URL http://www.dominio.it/ e http://www.dominio.it sono diversi. Di conseguenza, bisogna decidere quale URL utilizzare: quello con il slash finale o quello senza. Per togliere il slash finale dagli indirizzi di tutte le pagine del vostro sito, inserite il seguente codice:

<rule name="remove trailing slash" stopProcessing="true">
  <match url="(.*)/$" />
  <conditions>
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
  </conditions>
  <action type="Redirect" redirectType="Permanent" url="{R:1}" />
</rule>

2.11. Invece per aggiungerlo sempre, utilizzate questo codice:

<rule name="add trailing slash" stopProcessing="true">
  <match url="(.*[^/])$" />
  <conditions>
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
  </conditions>
  <action type="Redirect" redirectType="Permanent" url="{R:1}/" />
</rule>

2.12. A volte potrebbe anche essere utile sostituire a tutti i file l’estensione .htm con l’estensione .html – in tal caso inserite il seguente codice:

<rule name="htm to html" stopProcessing="true">
<match url="^(.*)\.htm$" />
<action type="Rewrite" url="/{R:1}.html" />
</rule>

Tutte le regole del web.config illustrate su questa pagina (a eccezione del reindirizzamento da una pagina all’altra) vanno inserite al posto dei puntini di questo codice:

<configuration>
  <system.webServer>
    <rewrite>
      ...
    </rewrite>
  </system.webServer>
</configuration>

Il reindirizzamento realizzabile con uno script è descritto nel paragrafo successivo.


Oggi scrivo di un problema molto più ricorrente di quanto si possa pensare.
Il problema
Supponiamo di voler installare due WordPress sullo stesso dominio: il primo nella root (sito.it) e il secondo in una cartella (sito.it/cartella). Il risultato che attendiamo è il seguente:

Naturalmente, non sorge alcun problema qualora decidessimo di installare solo una copia di WordPress oppure installarne due o più nelle cartelle dello stesso livello (per esempio, sito.it/cartella1, sito.it/cartella2 etc.). Installando invece i due WordPress nella root e nella cartella, ci troviamo di fronte al non-funzionamento del secondo: al tentativo di aprire qualsiasi pagina appartenente a sito.it/cartella esce l’errore 404.
Le soluzioni
Qualora il nostro server avesse il sistema operativo Linux, avremmo potuto limitarci a inserire nella cartella sito.it/cartella (dove sta il nostro WordPress № 2) un file .htaccess come questo:

# BEGIN WordPress

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

… permettendo in questo modo di convivere pacificamente a sito.it con sito.it/cartella
Su un server Windows, invece, non è possibile utilizzare il file .htaccess Di conseguenza, dobbiamo convertirlo in un file web.config Esistono alcuni strumenti online e offline che permettono di effettuare la conversione in automatico, ma tutti essi hanno lo stesso problema: non sanno convertire il comando RewriteBase (il quale è fondamentale per evitare la comparsa dell’errore 404 al posto di tutte le pagine del WordPress installato nella cartella). Sostituiscono semplicemente quel comando con una riga di commento, senza avvisarci che in questo modo l’intero file diventa non funzionante.
Io, dunque, sono giunto alla seguente soluzione.
Creiamo due file web.config. Il primo, quello più semplice, lo mettiamo nella root dove è installato il WordPress № 1. Ecco il suo codice:

<?xml version="1.0" encoding="UTF-8"?>
<!--Questo file sta nella cartella della root.-->
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
          <rule name="nomeregolaroot" patternSyntax="Wildcard">
            <match url="*"/>
                <conditions>
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
                </conditions>
            <action type="Rewrite" url="index.php"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Il secondo file web.config è invece più complesso e va caricato nella cartella dove è installato il WordPress № 2. Eccolo:

<?xml version="1.0" encoding="UTF-8"?>
<!--Questo file sta nella cartella caricata nella root.-->
<configuration>
  <system.webServer>
<rewrite>
  <rules>
    <clear />
    <rule name="nomeregola1" stopProcessing="true">
      <match url="^index\.php$" ignoreCase="false" />
      <action type="None" />
    </rule>
    <rule name="nomeregola2" stopProcessing="true">
      <match url="." ignoreCase="false" />
      <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
      </conditions>
      <action type="Rewrite" url="/cartella/index.php" />
    </rule>
  </rules>
</rewrite>
  </system.webServer>
</configuration>

Attenzione! Alla riga 18 va indicato il nome della cartella nella quale viene caricato il relativo web.config (naturalmente al posto di «cartella»).
Basta, ora entrambi i WordPress devono funzionare correttamente.
So che in teoria avrei potuto provare a escludere l’eredità delle regole nel web.config-«padre» o inserire un <remove> delle regole ereditate nel web.config-«figlio»… Però io di solito preferisco le soluzioni più semplici che non richiedano delle pratiche mentali autolesive prolungate nel tempo. Sul mio sito (che state leggendo ora) ho utilizzato proprio il metodo appena descritto per fare due versioni linguistiche del sito stesso. Come potete vedere, funziona benissimo.
Se volessimo ora installare altre copie di WordPress in altre cartelle più profonde – per esempio, sito.it/cartella1/cartella2 – ci limitiamo a inserire il secondo web.config in ognuna delle cartelle interessate dalla installazione. Dobbiamo solamente ricordarci di indicare il nome della cartella alla riga 18.
È importantissimo, inoltre, indicare tutta la sequenza delle cartelle per i WordPress installati nelle cartelle «profonde». Supponiamo, per esempio, di avere sempre il costrutto sito.it/cartella1/cartella2 dove sono installati tre copie di WordPress: la prima nella root, la seconda nella cartella1 e la terza nella cartella2. La riga 18 del file web.config caricato nella cartella2 deve essere così:

<?xml version="1.0" encoding="UTF-8"?>
<!--Questo file sta nella in una sottocartella (root/cartella/cartella/).-->
<configuration>
  <system.webServer>
<rewrite>
  <rules>
    <clear />
    <rule name="nomeregola1cartella" stopProcessing="true">
      <match url="^index\.php$" ignoreCase="false" />
      <action type="None" />
    </rule>
    <rule name="nomeregola2cartella" stopProcessing="true">
      <match url="." ignoreCase="false" />
      <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
      </conditions>
      <action type="Rewrite" url="/cartella1/cartella2/index.php" />
    </rule>
  </rules>
</rewrite>
  </system.webServer>
</configuration>

Il metodo è stato testato con successo dal sottoscritto.
Se avete delle domande o soluzioni alternative, scrivetemi pure!