Come gestire il report degli erroriLink to this heading

Quando esponi un sito pubblico, dovresti sempre disattivare DEBUG. Questo renderà il tuo server molto più veloce, e inoltre previene di mostrare a utenti malevoli i dettagli della tua applicazione che possono essere rivelati dalle pagine di errore.

Tuttavia, l’esecuzione con DEBUG impostato a False comporta che non saranno mai visibili gli errori generati dal tuo sito – al loro posto chiunque vedrà solo le pagine pubbliche di errore. Per tenere traccia degli errori che si verificano in un sito pubblicato, Django può essere configurato per creare reports con dettagli su tali errori.

Rapporti emailLink to this heading

Errori del serverLink to this heading

Quando DEBUG è False, Django invierà una mail agli utenti citati nel setting ADMINS ogni volta che il tuo codice lancerà un’eccezione non gestita e che risulterà come un error interno del server ( in poche parole, per ogni risposta con un codice HTTP 500 or maggiore ). Questo comporta un’immediata notifica agli amministratori di qualsiasi errore. Le persone specificate nel setting ADMINS riceveranno un descrizione dell’errore, un traceback Python completo, e i dettagli della richiesta HTTP che ha generato gli errori.

Di default, Django invierà le email da root@localhost. Ma, qualche mail provider rifiuta tutte le mail da questo indirizzo. Per utilizzare un indirizzo diverso, modifica il setting SERVER_EMAIL

Per attivare questo comportamento, inserisci l’indirizzo email del destinatario nella configurazione ADMINS .

Errori 404Link to this heading

Django può essere configurato per inviare via email errori relativi ai link non funzionanti (errore 404 «pagina non trovata»). Django invia email relative ad errori 404 quando:

Se queste condizioni sono soddisfatte, Django invierà un’e-mail agli utenti elencati nell’impostazione MANAGERS ogni volta che il tuo codice genera un 404 e la richiesta ha un referer. Non si preoccupa di inviare e-mail per i 404 che non hanno un referer: di solito si tratta di persone che digitano URL non funzionanti o bot Web non funzionanti. Ignora anche i 404 quando il referer è uguale all’URL richiesto, poiché questo comportamento è dovuto anche a bot web rotti.

Puoi dire a Django di smettere di segnalare particolari 404 modificando l’impostazione IGNORABLE_404_URLS. Dovrebbe essere un elenco di oggetti di espressioni regolari compilati. Per esempio:

Code
import re

IGNORABLE_404_URLS = [
    re.compile(r"\.(php|cgi)$"),
    re.compile(r"^/phpmyadmin/"),
]

In questo esempio, un 404 a qualsiasi URL che finisce con .php oppure .cgi non verrà riportato.Inoltre nessuna URL inizierà con /phpmyadmin/`.

Gli esempi seguenti mostrano come escludere alcune URLs standard che i browser ed i crawler richiedono con frequenza:

Code
import re

IGNORABLE_404_URLS = [
    re.compile(r"^/apple-touch-icon.*\.png$"),
    re.compile(r"^/favicon\.ico$"),
    re.compile(r"^/robots\.txt$"),
]

(Nota bene che queste sono espressioni regolari, quindi mettiamo un backslash prima del punto per assicurarci l’interpretazione come carattere)

Se desideri personalizzare ulteriormente il comportamento di django.middleware.common.BrokenLinkEmailsMiddleware (ad esempio per ignorare le richieste provenienti dai web crawler), dovresti ereditare la classe e sovrascrivere i suoi metodi.

Filtra i report di erroreLink to this heading

Filtraggio informazioni sensibiliLink to this heading

I report sugli errori sono davvero utili per il loro debug, quindi è generalmente utile registrare quante più informazioni possibili a riguardo. Ad esempio, per impostazione predefinita Django registra il full traceback per l’eccezione sollevata, le variabili locali di ogni traceback frame e i attributes di HttpRequest.

Comunque, a volte alcuni tipi di informazioni possono essere troppo sensibili e quindi non può essere appropriato tenere traccia ad esempio, della password o del numero di carta di credito di un utente. Quindi oltre a filtrare le impostazioni che sono sensibili come descritto nella documentazione DEBUG, Django offre una serie di decoratori di funzioni che ti aiutano a controllare quali informazioni debbano essere filtrate sul report degli errori in ambiente di produzione (cioè con DEBUG impostato a False): sensitive_variables() e sensitive_post_parameters().

sensitive_variables(*variables)Link to this definition

Se una funzione (sia essa una view o una callback regolare) nel tuo codice usa variabili locali suscettibili di contenere infomazioni sensibili, puoi evitare che i valori di quelle variabili vengano inclusi nei report degli errori usando il decoratore sensitive_variables:

Code
from django.views.decorators.debug import sensitive_variables


@sensitive_variables("user", "pw", "cc")
def process_info(user):
    pw = user.pass_word
    cc = user.credit_card_number
    name = user.name
    ...

Nell’esempio sopra, i valori delle variabili user, pw e cc verranno nascosti e sostituiti con asterischi (**********) nei report di errore, mentre verrà mostrato il valore della variabile name.

Per nascondere sistematicamente tutte e variabili locali di una funzione dal sistema di gestione degli errori nei log, non indicare alcun argomento al decoratore sensitive_variables:

Code
@sensitive_variables()
def my_function(): ...
sensitive_post_parameters(*parameters)Link to this definition

Se una delle tue view riceve un oggetto HttpRequest con POST parameters suscettibile di contenere informazioni riservate, puoi impedire che i valori di tali parametri siano inclusi nei report di error utilizzando il decoratore sensitive_post_parameters:

Code
from django.views.decorators.debug import sensitive_post_parameters


@sensitive_post_parameters("pass_word", "credit_card_number")
def record_user_profile(request):
    UserProfile.create(
        user=request.user,
        password=request.POST["pass_word"],
        credit_card=request.POST["credit_card_number"],
        name=request.POST["name"],
    )
    ...

Nell’esempio di cui sopra, i valori dei parametri di POST per pass_word e credit_card_number saranno nascosti e rimpiazzati con degli asterischi (**********) nella rappresentazione della request nel report degli errori, dove invece il valore del parametro name sarà mostrato.

Per nascondere sistematicamente tutti i parametri di una richiesta POST nel report degli errori, non inserire alcun parametro al decoratore sensitive_post_parameters

Code
@sensitive_post_parameters()
def my_view(request): ...

Tutti i parametri in POST sono sistematicamente filtrati dai report degli errori per alcune view django.contrib.auth.views (login, password_reset_confirm, password_change, add_view e user_change_password nell’amministrazione auth) per prevenire la fuoriuscita di informazioni sensibili come ad esempio le password utente.

Rapporti di errore personalizzatiLink to this heading

Tutto ciò che fanno sensitive_variables() e sensitive_post_parameters() è, rispettivamente, annotare la funzione decorata con i nomi delle variabili sensibili e annotare l’oggetto HttpRequest con i nomi dei parametri POST sensibili, in modo che le informazioni possona essere successivamente filtrate dai report quando si verifica un errore. Il vero filtro viene eseguito dal filtro di report degli errori predefinito di Django: django.views.debug.SafeExceptionReporterFilter. Questo filtro utilizza le annotazioni dei decoratori per sostituire i valori corrispondenti con gli sterischi (**********) quando vengono prodotti i report di errore. Se desideri sovrascrivere o personalizzare questo comportamento predefinito per l’intero sito, devi definire la tua classe di filtro e dire a Django di usarla tramite l’impostazione DEFAULT_EXCEPTION_REPORTER_FILTER:

Code
DEFAULT_EXCEPTION_REPORTER_FILTER = "path.to.your.CustomExceptionReporterFilter"

Puoi controllare in modo più granulare quale filtro utilizzare all’interno di una vista configurando il parametro exception_reporter_filter della HttpRequest:

Code
def my_view(request):
    if request.user.is_authenticated:
        request.exception_reporter_filter = CustomExceptionReporterFilter()
    ...

La tua classe del filtro personalizzato ha bisogno di ereditare da django.views.debug.SafeExceptionReporterFilter e può sovrascrivere i seguenti attributi e metodi:

class SafeExceptionReporterFilterLink to this definition
cleansed_substituteLink to this definition

Il carattere da utilizzare per rimpiazzare valori sensibili. Di default viene rimpiazzato il valore di stringhe sensibili con l’asterisco (**********).

hidden_settingsLink to this definition

Un oggetto di espressione regolare compilato per trovare le impostazioni ed i valori request.META considerati sensibili. In modo predefinito è equivalente a:

Code
import re

re.compile(r"API|AUTH|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.IGNORECASE)
is_active(request)Link to this definition

Restituisce True per attivare il filtro in get_post_parameters() e get_traceback_frame_variables(). Di default, il filtro è attivo se DEBUG is False. Nota che i valori sensibili request.META sono sempre filtrati così come i valori di impostazioni sensibili, come descritto nella documentazione di DEBUG.

get_post_parameters(request)Link to this definition

Restituisce un dizionario filtrato di parametri POST. I valori sensibili sono rimpiazzati con cleansed_substitute.

get_traceback_frame_variables(request, tb_frame)Link to this definition

Restituisce un dizionario filtrato di variabili locali per una data finestra di traceback. I valori sensibili sono rimpiazzati con cleansed_substitute.

Se necessiti di personalizzare i report degli errori oltre ai filtri, potresti specificare una classe personalizzata per il report degli errori definendo l’impostazione DEFAULT_EXCEPTION_REPORTER:

Code
DEFAULT_EXCEPTION_REPORTER = "path.to.your.CustomExceptionReporter"

Il reporter delle eccezioni è resposabile di compilare i dati per il report delle eccezioni e di formattarli come HTML in modo appropriato. (Il reporter delle eccezioni usa DEFAULT_EXCEPTION_REPORTER_FILTER quando prepara i dati di report delle eccezioni).

La tua classe report personalizzata deve ereditare da django.views.debug.ExceptionReporter.

class ExceptionReporterLink to this definition
html_template_pathLink to this definition

Proprietà che restituisce un pathlib.Path che rappresenta il percorso assoluto sul filesystem di un template per fare render della rappresentazione HTML dell’eccezione. E” predefinito il template che offre Django.

text_template_pathLink to this definition

Proprietà che restituisce un pathlib.Path che rappresenta il percorso assoluto sul filesystem di un template per fare render della rappresentazione in plain-text dell’eccezione. E” predefinito il template che offre Django.

get_traceback_data()Link to this definition

Restituisce un dizionario che contiene le informazioni utili per l’analisi

Questa è il punto principale dell’estensione per personalizzare i report delle eccezioni, per esempio:

Code
from django.views.debug import ExceptionReporter


class CustomExceptionReporter(ExceptionReporter):
    def get_traceback_data(self):
        data = super().get_traceback_data()
        # ... remove/add something here ...
        return data
get_traceback_html()Link to this definition

Restituisce la versione HTML del report dell’eccezione

Usato per la versione HTML del debug della pagina di errore 500 HTTP.

get_traceback_text()Link to this definition

Restituisce una versione testuale del resoconto dell’eccezione

Usato per la versione testuale del debug della pagina di errore 500 HTTP e report email.

Così come con la classe filtro, puoi controllare quale classe per il report di eccezioni usare dentro ad ogni view impostando l’attributo exception_reporter_class di HttpRequest:

Code
def my_view(request):
    if request.user.is_authenticated:
        request.exception_reporter_class = CustomExceptionReporter()
    ...