2012-08-03 21 views
9

Estoy trabajando en una aplicación web Django que (entre otras cosas) necesita manejar la información de estado de la transacción enviada mediante una solicitud POST.Configuración del encabezado HTTP_REFERER en la prueba Django

Además de la seguridad de HTTP con el apoyo de la pasarela de pago, cheques de mi punto de vista request.META['HTTP_REFERER'] contra una entrada en settings.py para tratar de evitar cosas raras:

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

Ahora me gustaría encontrar la manera de probar este comportamiento

Puedo generar una falla con la suficiente facilidad; HTTP_REFERER es (previsiblemente) None con una carga normal de la página:

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

bien, ¿cómo puedo fingir una presentación exitosa? He intentado configurar HTTP_REFERER en extra, p.self.client.post(..., extra={'HTTP_REFERER': 'http://foo/bar'}), pero esto no está funcionando; la vista aparentemente sigue viendo un encabezado en blanco.

¿El cliente de prueba incluso admite encabezados personalizados? ¿Hay una solución alternativa si no es así? Estoy usando Django 1.1, y preferiría no actualizar aún si es posible.

+0

Este no era su problema, pero para otros que están teniendo la dificultad que tenía: Django no reconocía los encabezados que estaba enviando porque no transformaba correctamente sus nombres como se documenta [aquí] (https: // docs. djangoproject.com/en/1.6/topics/testing/tools/#django.test.client.Client.get), como [describe la especificación CGI] (http://tools.ietf.org/html/draft-robinson- www-interface-00 # page-8). Por ejemplo, 'X-CSRFToken' sería' HTTP_X_CSRFTOKEN'. Después de transformarlos, simplemente podría usarlos como kwargs, como en la respuesta de supervacuo a continuación. –

Respuesta

14

Casi a la derecha. En realidad es:

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

me había perdido un ** (argumento del operador de dispersión/palabra clave desembalaje operador/whatever) cuando reading the source of test/client.py; extra termina siendo un diccionario de argumentos de palabras clave adicionales para la función en sí.

+0

Obtuve un "__init __() obtuvo un argumento de palabra clave inesperado 'HTTP_REFERER'" al intentar usar esto. ¿Tal vez cambió en las versiones más nuevas de django? –

+0

@StevenRogers, parece que ha hecho 'c = Client (HTTP_REFERER = 'http: // foo/bar')' en su lugar (lo único que puedo pensar que llamará '__init__'). Estaba sugiriendo agregar eso como un kwarg a 'post()' & 'get()'; Acabo de probar esto en Django 1.7.3 y parece funcionar bien ... – supervacuo

0

Puede pasar cabeceras HTTP al constructor de Client:

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')) 

De esta manera no es necesario pasar cabeceras cada vez que realice una solicitud.

Cuestiones relacionadas