2012-08-03 5 views
9

Ich arbeite an einer Django-Web-Anwendung, die (unter anderem) Transaktionsstatusinformationen verarbeiten muss, die mit einer POST Anfrage gesendet werden.Einstellung HTTP_REFERER-Header in Django-Test

Neben der von der Payment-Gateway unterstützt HTTP Sicherheit, meiner Meinung nach überprüft request.META['HTTP_REFERER'] gegen einen Eintrag in settings.py versuchen lustiges Geschäft zu verhindern:

if request.META.get('HTTP_REFERER', '') != settings.PAYMENT_URL and not settings.DEBUG: 
    return HttpResponseForbidden('Incorrect source URL for updating payment status') 

Nun möchte Ich mag, wie arbeiten, testen dieses Verhalten.

Ich kann einen Fehler leicht genug erzeugen; HTTP_REFERER ist (vorhersagbar) None mit einer normalen Seite zu laden:

def test_transaction_status_succeeds(self): 
    response = self.client.post(reverse('transaction_status'), { ... }) 
    self.assertEqual(response.status_code, 403) 

Wie aber kann ich fälschen erfolgreiche Einreichung? Ich habe versucht, HTTP_REFERER in extra, z.self.client.post(..., extra={'HTTP_REFERER': 'http://foo/bar'}), aber das funktioniert nicht; Die Ansicht sieht anscheinend immer noch einen leeren Header.

Unterstützt der Testclient sogar benutzerdefinierte Header? Gibt es einen Workaround, wenn nicht? Ich benutze Django 1.1 und würde es vorziehen, wenn überhaupt nicht zu aktualisieren.

+0

Das war nicht dein Problem, aber für andere, die die Schwierigkeiten hatten, die ich hatte: Django erkannte die Header nicht, weil ich ihre Namen nicht richtig als dokumentiert [hier] umwandelte (https: // docs. djangoproject.com/de/1.6/topics/testing/tools/#django.test.client.Client.get), wie [beschrieben die CGI-Spezifikation] (http://tools.ietf.org/html/draft-robinson- www-interface-00 # Seite-8). Zum Beispiel wäre 'X-CSRFToken'' HTTP_X_CSRFTOKEN'. Nachdem ich sie transformiert hatte, konnte ich sie einfach als Kwargs verwenden, wie in der Antwort von Supervacuo unten. –

Antwort

14

Fast richtig. Es ist eigentlich:

def transaction_status_suceeds(self): 
    response = self.client.post(reverse('transaction_status'), {}, HTTP_REFERER='http://foo/bar') 

ich einen ** verpasst hatte (Scatter-Operator/keyword Argument Auspacken Operator/whatever), wenn reading the source of test/client.py; extra endet als ein Wörterbuch der zusätzlichen Schlüsselwort Argumente für die Funktion selbst.

+0

Ich habe ein "__init __() erhalten ein unerwartetes Schlüsselwort Argument" HTTP_REFERER "", wenn Sie versuchen, dies zu verwenden. Vielleicht hat es sich in neueren Versionen von Django geändert? –

+0

@StevenRogers, es klingt, als hättest du 'c = Client (HTTP_REFERER = 'http: // foo/bar')' statt dessen gemacht (das einzige, was mir einfällt, wird '__init__' aufrufen). Ich schlug vor, das als Kwarg zu 'post()' & 'get()' hinzuzufügen; Ich habe es gerade auf Django 1.7.3 getestet und es scheint gut zu funktionieren ... – supervacuo

0

Sie können HTTP-Header an den Konstruktor Client passieren:

from django.test import Client 
from django.urls import reverse 

client = Client(
    HTTP_USER_AGENT='Mozilla/5.0', 
    HTTP_REFERER='http://www.google.com', 
) 
response1 = client.get(reverse('foo')) 
response2 = client.get(reverse('bar')) 

Auf diese Weise brauchen Sie nicht Header, die Sie jedes Mal eine Anfrage zu übergeben.