I've just started building an API with Django for the first time and I've run into an issue while trying to test an endpoint with Postman. When I send a POST request to the endpoint http://localhost:8000/arithmetic/ containing the following JSON:
{
"expression": "1 2 × 3"
}
I get the following response:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE">
<title>403 Forbidden</title>
<style type="text/css">
html * {
padding: 0;
margin: 0;
}
body * {
padding: 10px 20px;
}
body * * {
padding: 0;
}
body {
font: small sans-serif;
background: #eee;
color: #000;
}
body>div {
border-bottom: 1px solid #ddd;
}
h1 {
font-weight: normal;
margin-bottom: .4em;
}
h1 span {
font-size: 60%;
color: #666;
font-weight: normal;
}
#info {
background: #f6f6f6;
}
#info ul {
margin: 0.5em 4em;
}
#info p,
#summary p {
padding-top: 10px;
}
#summary {
background: #ffc;
}
#explanation {
background: #eee;
border-bottom: 0px none;
}
</style>
</head>
<body>
<div id="summary">
<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>
</div>
<div id="info">
<h2>Help</h2>
<p>Reason given for failure:</p>
<pre>
CSRF token from the 'X-Csrftoken' HTTP header has incorrect length.
</pre>
<p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
<a href="https://docs.djangoproject.com/en/4.1/ref/csrf/">Django’s
CSRF mechanism</a> has not been used correctly. For POST forms, you need to
ensure:</p>
<ul>
<li>Your browser is accepting cookies.</li>
<li>The view function passes a <code>request</code> to the template’s <a
href="https://docs.djangoproject.com/en/dev/topics/templates/#django.template.backends.base.Template.render"><code>render</code></a>
method.</li>
<li>In the template, there is a <code>{% csrf_token
%}</code> template tag inside each POST form that
targets an internal URL.</li>
<li>If you are not using <code>CsrfViewMiddleware</code>, then you must use
<code>csrf_protect</code> on any views that use the <code>csrf_token</code>
template tag, as well as those that accept the POST data.</li>
<li>The form has a valid CSRF token. After logging in in another browser
tab or hitting the back button after a login, you may need to reload the
page with the form, because the token is rotated after a login.</li>
</ul>
<p>You’re seeing the help section of this page because you have <code>DEBUG =
True</code> in your Django settings file. Change that to <code>False</code>,
and only the initial error message will be displayed. </p>
<p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>
</div>
</body>
</html>
I am unsure how to resolve this issue so that I can test my endpoint.
Here is my code so far:
Within the arithmetic app:
views.py:
import json
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
# Create your views here.
def parse_request(str):
if '×' in str:
str = str.replace('×', '*')
if '÷' in str:
str = str.replace('÷', '/')
def calculate(request):
if request.method == 'POST':
# parse the json object
body = json.loads(request.body)
expression = body['expression']
return JsonResponse({
'response': expression
})
else:
return JsonResponse({
'error': 'invalid request method'
})
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.calculate)
]
And my main projects urls.py looks like this:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('arithmetic/', include('arithmetic.urls'))
]
The idea is to connect this too a React frontend that I've already developed but I want to test the endpoint on its own to ensure its working before I try to connect it to the frontend.
Any help or guidance would be greatly appreciated.
CodePudding user response:
The fastest way to solve this problem is by using Django's csrf_exempt
function to disable CSRF protection for your view.
from django.views.decorators.csrf import csrf_exempt
urlpatterns = [path('', csrf_exempt(views.calculate))]
You can as well use the decorator on your view:
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def calculate(request):
if request.method == 'POST':
# parse the json object
body = json.loads(request.body)
expression = body['expression']
return JsonResponse({
'response': expression
})
else:
return JsonResponse({
'error': 'invalid request method'
})
You can also remove the middleware completely from the config file, this would disable the CSRF protection for all the endpoints. From the config file, remove this line:
django.middleware.csrf.CsrfViewMiddleware
NOTE: This is not recommended for most cases, as it leaves your API vulnerable to CSRF attacks.