Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how do you include a csrf token when testing a POST endpoint in django?

I am learning how to make an api endpoint and I am trying to write a test to see if a post request returns a 200 status code. I plan on writing more tests to see if the endpoint is returning all the expected results as well. I keep getting a 403 status code and I think it is because I need to include a csrf token in the post data. What is a good way to test a POST endpoint in django?

my Test:

from django.test import TestCase from app import settings import requests  class ProjectEndpoint(TestCase):    def post_endpoint(self):       data = {'hello':'23'}       post_project = requests.post(settings.BASE_URL+'/api/project', params=data)       self.assertEqual(post_endpoint.status_code, 200) 

This test keeps failing with 403 != 200

I think it is because the view is protected against csrf attacks, but I am really not sure. Appreciate any insight that someone has.

like image 619
Spencer Cooley Avatar asked Jul 28 '14 20:07

Spencer Cooley


People also ask

How do you pass CSRF token in post request Python?

import sys import requests URL = 'https://portal.bitcasa.com/login' client = requests. session() # Retrieve the CSRF token first client. get(URL) # sets cookie if 'csrftoken' in client.

How does CSRF token work in Django?

csrf_token. Django has a {% csrf_token %} tag that is implemented to avoid malicious attacks. It generates a token on the server-side when rendering the page and makes sure to cross-check this token for any requests coming back in. If the incoming requests do not contain the token, they are not executed.

How do I send a CSRF token in Postman Django?

You need to set it as a header in the request, not in the body. X-CSRFToken is the key and the value is CSRF token from the cookie. This will work if you are using an API framework like Tastypie or Django Rest Framework .


1 Answers

Actually, django doesn't enforce (by default) csrf checking with tests, as per https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#testing:

The CsrfViewMiddleware will usually be a big hindrance to testing view functions, due to the need for the CSRF token which must be sent with every POST request. For this reason, Django’s HTTP client for tests has been modified to set a flag on requests which relaxes the middleware and the csrf_protect decorator so that they no longer rejects requests. In every other respect (e.g. sending cookies etc.), they behave the same.

If, for some reason, you want the test client to perform CSRF checks, you can create an instance of the test client that enforces CSRF checks:

from django.test import Client

csrf_client = Client(enforce_csrf_checks=True)

However, this does require you to be using the Django Client vs requests; as far as I know, Django doesn't mock/instrument/etc. requests... so you're actually hitting the real server when you run that unit test.

Also note that you should name your test functions something that starts with test_

So something like this (when run through django manage.py test .ProjectEndpoint)

def test_post_endpoint(self):    data = {'hello':'23'}    c = Client() #above, from django.test import TestCase,Client    #optional, but may be necessary for your configuration: c.login("username","password")    response = c.post('/api/project',params=data)    self.assertEqual(response.status_code, 200) 
like image 51
Foon Avatar answered Sep 23 '22 00:09

Foon