realizzazione
siti web a Bologna

dal 2002
16 anni di siti web

salvare il posizionamento del sito web con il codice 503

10/05/2013

cosa sono gli http status code

I codici di stato http (http status code) sono un elemento essenziale del protocollo; tramite questi codici il client e il server si possono scambiare informazioni importanti sull'esito delle richieste. Quando ad esempio richiediamo un documento a un server web riceviamo di norma una risposta che inizia con 200 Ok. Per fare un esempio banale proviamo a vedere cosa succede quando richiediamo una pagina da un sito web:

GET /chi_siamo.it.html HTTP/1.1
Host: www.videoarts.eu
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.videoarts.eu/
Connection: keep-alive

In pratica il nostro client richiede al server www.videoarts.eu la pagina chiamata chi_siamo.html; vediamo cosa risponde il server:

HTTP/1.1 200 OK
Date: Thu, 16 May 2013 16:14:42 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.3.3-7+squeeze15
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Length: 2665
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

La pagina è stata correttamente inviata dal server al client; infatti il messaggio di risposta inizia con HTTP/1.1 200 OK ovvero il codice di stato http 200 che significa «tutto bene».

differenza tra http status code 404 e 503

Cosa succede però se la richiesta non va a buon fine? Il server ci risponderà in questo caso con un codice di stato che indica il tipo di errore riscontrato. Per esempio, se chiediamo un documento inesistente riceveremo il famoso codice 404 (documento non trovato). Questo in sé per sé non è un male; indica semplicemente al client che la risorsa richiesta non è disponibile sul server, per esempio perché la richiesta è sbagliata.

Se però la richiesta è corretta ma il documento non è disponibile per altri motivi, il codice 404 non è sufficiente; ci sono altri codici che possiamo usare per dare al client informazioni aggiuntive su dove e quando può reperire la risorsa richiesta. Ad esempio, se il client sta richiedendo una risorsa che abbiamo intenzionalmente rimosso dovremmo informarlo con un codice 410 (risorsa non più disponibile) mentre se la risorsa è stata definitivamente spostata altrove l'ideale sarebbe reindirizzare il client alla nuova locazione unitamente all'invio di un codice 301 (risorsa definitivamente spostata). Il W3C mette a disposizione degli utenti sul proprio sito una dettagliata descrizione dei codici di stato http.

Il codice che ci interessa oggi però è il 503, che informa il client del fatto che la risorsa non è momentaneamente disponibile ma non per un errore o un problema, ma per normale manutenzione. Questo è importante soprattutto per gli spider dei motori di ricerca che vengono così informati del fatto che sul nostro sito va tutto bene e che anche se vi sono delle risorse irraggiungibili la cosa è sotto controllo.

Trasmettendo un codice 503 quindi non rischiamo di perdere posizioni (non troppe almeno) sui motori di ricerca a causa di una manutenzione programmata del nostro server; è particolarmente importante anche fornire al client un'indicazione di quanto tempo durerà questo periodo di indisponibilità della risorsa in modo da evitare che l'utente torni a cercarla troppo presto e soprattutto per rafforzare l'idea che abbiamo la situazione in pugno.

Con una strategia di questo genere è possibile fermare un sito anche per diversi giorni senza che questo penalizzi il suo posizionamento. Diversamente potremmo avere parecchi problemi!

realizzare la pagina «sito in manutenzione»

Realizzare una pagina web che implementi correttamente questa strategia (codice di stato 503 e indicazione del tempo previsto di blocco del sito) richiede un minimo di pratica con lo sviluppo in PHP. Qui di seguito vediamo un esempio:

<?php

    // data e ora di fine del downtime
	$expectedReboot = '2013-05-19 10:50:00';
	$expectedRebootTimestamp = strtotime( $expectedReboot );

    // timestamp corrente
	$currentTimestamp = time();

    // secondi mancanti alla fine del downtime
	$eta = $expectedRebootTimestamp - $currentTimestamp;

    // questa riga imposta un header HTTP con codice di stato 503
	header('HTTP/1.1 503 Service Temporarily Unavailable',true,503);

    // questa riga dice ai client di riprovare tra circa 24 ore
	header('Retry-After: '.$eta);

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>

	<title>sito in manutenzione</title>
	<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

	<script type="text/javascript">
	    <!--
		var seconds = <?php echo $eta; ?>;
		function writeTimer( elementId , seconds ) {
		    var t = '';
		    var dd = Math.floor(seconds/86400);
		    var hh = Math.floor(((seconds/86400)%1)*24);
		    var mm = Math.floor(((seconds/3600)%1)*60);
		    var ss = Math.round(((seconds/60)%1)*60);
		    if( hh < 10 ) { hh = "0"+hh; }
		    if( mm < 10 ) { mm = "0"+mm; }
		    if( ss < 10 ) { ss = "0"+ss; }
		    if( dd > 0 ) { t = t + dd + " giorni e "; }
		    var t = t+hh+":"+mm+":"+ss+" ore";
		    document.getElementById( elementId ).innerHTML = t;
		}
	    -->
	</script>

    </head>
    <body style="text-align: center;" 
	onload="setInterval( function() { 
		writeTimer( 'timerSpan' , seconds ); seconds--; 
	    } , 1000 );">

	<h1>sito in manutenzione</h1>
	<h2>saremo di nuovo online entro <span id="timerSpan"></span></h2>

	<p>
	    <a href="http://validator.w3.org/check?uri=referer" style="border: 0px;">
		<img src="http://www.w3.org/Icons/valid-xhtml10" 
		    alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
	</p>

    </body>
</html>

La struttura del file è molto semplice, nella prima parte abbiamo il codice PHP che restituisce gli header appropriati (righe 14 e 17); il calcolo della durata del downtime è effettuato alla riga 11 sulla base della data e ora inserite nella variabile $expectedReboot alla riga 4. Si noti che il tempo è calcolato in secondi perché l'header Retry-After richiede, per l'appunto, i secondi.

la pagina di manutenzione completata e funzionante

A parte gli header, la pagina contiene un messaggio per gli utenti e un indicazione del tempo rimanente prima del riavvio del sito; abbiamo voluto aggiungere un po' di movimento con l'animazione del timer, realizzata grazie a poche righe di JavaScript (28-45 e 48-51) sulle quali non ci soffermeremo in questa sede in quanto i dettagli sarebbero fuori argomento. Si noti infine che la pagina è validata e ben formata, anche se si tratta di una semplice pagina di errore; è importante, nella realizzazione dei siti web, curare i dettagli.

catturare il traffico con .htaccess

Ora rimane solo da «catturare» le richieste per indirizzarle verso la nostra pagina di manutenzione (poniamo per esempio di averla chiamata manutenzione.php); questo si può fare facilmente con un file .htaccess opportunamente preparato sfruttando il modulo rewrite di Apache2.

Qui di seguito vediamo un esempio di come questo file può essere realizzato:

<ifmodule mod_rewrite.c>

    RewriteEngine on
    
    RewriteCond %{REMOTE_ADDR} !^999.999.999.999$
    RewriteCond %{REQUEST_URI} !^/manutenzione\.php$
    RewriteRule ^(.*)$ manutenzione.php [L]

</ifmodule>

La condizione alla riga 5 (dove dovete inserire l'ip del vostro server al posto di 999.999.999.999) e quella alla riga successiva impediscono al reindirizzamento di andare in loop. La riga 7 contiene la regola di riscrittura vera e propria, che cattura qualsiasi richiesta fatta al server reindirizzandola alla pagina manutenzione.php.

conclusioni

Come abbiamo visto, realizzare una pagina di manutenzione corretta e funzionale è molto semplice; ovviamente questo è un esempio, e se volete utilizzarlo in produzione dovreste migliorarlo perlomeno sotto l'aspetto grafico. Ad ogni modo, l'utilizzo di questa tecnica è in grado di preservare il posizionamento del sito anche in condizioni piuttosto critiche, per esempio in caso di downtime prolungati.