rest_framework api view not working when CSRF_HEADER_NAME param is not default · Issue #4410 · encode/django-rest-framework (original) (raw)

Checklist

Steps to reproduce

Set custom CSRF header name in settings.py eg.
setting.py:

CSRF_HEADER_NAME = "HTTP_X_XSRF_TOKEN"

  1. Go to api view
  2. Login to account with permission to modificate any data
  3. make request with unsafe method - for example modify data

Expected behavior

Request should work and data should be modified.

Actual behavior

Systems gives error CSRF Failed: CSRF token missing or incorrect.

Patch

rest_framework/static/rest_framework/js/csrf.js change line 49 to:

xhr.setRequestHeader(window.drf.csrfHeaderName, csrftoken);

rest_framework/templates/rest_framework/base.html add new line between lines 265-266 from:

window.drf = { csrfCookieName: "{{ csrf_cookie_name|default:'csrftoken' }}" };

to

window.drf = { csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}", csrfCookieName: "{{ csrf_cookie_name|default:'csrftoken' }}" };

same story in file rest_framework/templates/rest_framework/admin.html but modification should be done between lines 234 and 235

window.drf = { csrfCookieName: "{{ csrf_cookie_name|default:'csrftoken' }}" };

to

window.drf = { csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}", csrfCookieName: "{{ csrf_cookie_name|default:'csrftoken' }}" };

rest_framework/renderers.py add new line between 678 and 679 before:

        'csrf_cookie_name': settings.CSRF_COOKIE_NAME,
    }

after

        'csrf_cookie_name': settings.CSRF_COOKIE_NAME,
        'csrf_header_name': (settings.CSRF_HEADER_NAME[5:].replace("_","-") if settings.CSRF_HEADER_NAME.startswith('HTTP_') else settings.CSRF_HEADER_NAME.replace("_","-")),
    }

and that is all. Last modification have those replaces call because Django documentation say:

As with other HTTP headers in request.META, the header name received from the server is normalized by converting all characters to uppercase, replacing any hyphens with underscores, and adding an 'HTTP_' prefix to the name. For example, if your client sends a 'X-XSRF-TOKEN' header, the setting should be 'HTTP_X_XSRF_TOKEN'.

ps. great job guys! Nice module.