mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 19:14:01 +03:00
made Browsable API base template cachable: omit CSRF token when unnecessary (#7717)
HTML responses generated by the Browsable API otherwise generate inconsistent ETAGs -- due to the presence of CSRF tokens in the response -- even when the API is read-only, (and as such when the response contains no resource-modifying forms, i.e. neither POST nor PUT forms, which might require the CSRF token). While the template was appropriately including CSRF tokens only within POST and PUT forms, its AJAX overlay included the CSRF token in *every* response, regardless of whether it would be needed. This change brings the logic of the `script` block into line with that of the rest of the template -- and such that read-only APIs (and really the Browsable API pages of *any* read-only resources) will not needlessly include the CSRF token, and will now be safely cachable -- by both back-end systems and by the user agent.
This commit is contained in:
parent
b0ca248d88
commit
9c9ffb18f4
|
@ -290,7 +290,7 @@
|
||||||
<script>
|
<script>
|
||||||
window.drf = {
|
window.drf = {
|
||||||
csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
|
csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
|
||||||
csrfToken: "{% if request %}{{ csrf_token }}{% endif %}"
|
csrfToken: "{% if request %}{% if post_form or put_form %}{{ csrf_token }}{% endif %}{% endif %}"
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script src="{% static "rest_framework/js/jquery-3.5.1.min.js" %}"></script>
|
<script src="{% static "rest_framework/js/jquery-3.5.1.min.js" %}"></script>
|
||||||
|
|
|
@ -3,15 +3,23 @@ import re
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
|
||||||
def test_base_template_with_context():
|
|
||||||
context = {'request': True, 'csrf_token': 'TOKEN'}
|
|
||||||
result = render({}, 'rest_framework/base.html', context=context)
|
|
||||||
assert re.search(r'\bcsrfToken: "TOKEN"', result.content.decode())
|
|
||||||
|
|
||||||
|
|
||||||
def test_base_template_with_no_context():
|
def test_base_template_with_no_context():
|
||||||
# base.html should be renderable with no context,
|
# base.html should be renderable with no context,
|
||||||
# so it can be easily extended.
|
# so it can be easily extended.
|
||||||
result = render({}, 'rest_framework/base.html')
|
result = render({}, 'rest_framework/base.html')
|
||||||
# note that this response will not include a valid CSRF token
|
# note that this response will not include a valid CSRF token
|
||||||
assert re.search(r'\bcsrfToken: ""', result.content.decode())
|
assert re.search(r'\bcsrfToken: ""', result.content.decode())
|
||||||
|
|
||||||
|
|
||||||
|
def test_base_template_with_simple_context():
|
||||||
|
context = {'request': True, 'csrf_token': 'TOKEN'}
|
||||||
|
result = render({}, 'rest_framework/base.html', context=context)
|
||||||
|
# note that response will STILL not include a CSRF token
|
||||||
|
assert re.search(r'\bcsrfToken: ""', result.content.decode())
|
||||||
|
|
||||||
|
|
||||||
|
def test_base_template_with_editing_context():
|
||||||
|
context = {'request': True, 'post_form': object(), 'csrf_token': 'TOKEN'}
|
||||||
|
result = render({}, 'rest_framework/base.html', context=context)
|
||||||
|
# response includes a CSRF token in support of the POST form
|
||||||
|
assert re.search(r'\bcsrfToken: "TOKEN"', result.content.decode())
|
||||||
|
|
Loading…
Reference in New Issue
Block a user