I have installed Chatterbot for Django integration. I followed the easy tutorial with every step and made it so that the endpoint was: http://127.0.0.1:8000/chatterbot/ What I did next was try to communicate with that endpoint to see if I would get back any results. So I made an Ajax request as follows:
var query = {"text": "My input statement"};
$.ajax({
type: 'POST',
url: "http://127.0.0.1:8000/chatterbot/",
data: JSON.stringify(query),
contentType: 'application/json',
success: function (data) {
console.log(data);
}
});
However, what returns in console is: POST http://127.0.0.1:8000/chatterbot/ 403 (Forbidden) and what returns in the cmd prompt when I run my server is:
csrf: WARNING - Forbidden (CSRF token missing or incorrect.):
/chatterbot/ [29/Mar/2018 02:16:43] "POST /chatterbot/ HTTP/1.1" 403
2502
Why am I getting this error? How can I fix it so I receive the call back from the endpoint?
View for this page:
def IndexView(request):
latest_questions = Questions.objects.all().order_by("-date_published")[:5]
popular_questions = Questions.objects.all().order_by("-num_replies")[:5]
return render(request, 'core/index.html',
{'latest_questions': latest_questions, 'popular_questions': popular_questions
})
Try this code
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
var query = {
"text": "My input statement",
"csrfmiddlewaretoken": csrftoken
};
$.ajax({
type: 'POST',
url: "http://127.0.0.1:8000/chatterbot/",
data: query,
contentType: 'application/json',
success: function (data) {
console.log(data);
}
});
one way is to send the csrfmiddlewaretoken like below
var query = {
"text": "My input statement",
'csrfmiddlewaretoken': "{{csrf_token }}"
};
other way is to use #csrf_exempt decorator
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def IndexView(request):
# .... code.....
other is to add a script
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Reference: https://docs.djangoproject.com/en/2.0/ref/csrf/
If you dont want to use CSRF tokens just add this above your code.
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def IndexView(request):
# your code
Related
I`m trying to send custom headers in a post request with axios in the following way:
const onSubmit = async (data) => {
const token = await getAccessTokenSilently();
console.log(token);
const header = {
headers: {
'Authorization': `Bearer ${token}`
}
};
const body = {
source: "website",
user_id: user.sub,
message_category: "crypto",
message_text: data,
};
console.log(body);
axios
.post(serverUrl + "messages/post_message", body, header)
.then((res) => {
// setPosts(res.data.messages);
console.log(res);
})
.catch(function (error) {
// handle error
console.error(error);
});
};
But in my python cherrypy server I`m not getting the custom headers at all. although I do receive it in Acess-Control-Request-Headers as titles without the data.
debugging: auth = cherrypy.request.headers in python:
PS: Sending headers via postman works normally.
Considering that your API is working correctly (you might recheck that as well). See if this works for you:
const onSubmit = async (data) => {
const token = await getAccessTokenSilently();
const options = {
headers: {
'Authorization': `Bearer ${token}`
},
body: {
source: "website",
user_id: user.sub,
message_category: "crypto",
message_text: data,
}
};
axios
.post(serverUrl + "messages/post_message", options)
.then((res) => {
// setPosts(res.data.messages);
console.log(res);
})
.catch(function (error) {
// handle error
console.error(error);
});
};
This is Ajax code in my application, it adds object in Model without refreshing the page and shows no error:
$(document).on('submit', '#addbookform', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: "{% url 'books:home' %}",
data: {
name: $('#name').val(),
price: $('#price').val(),
num_of_pages: $('#num_of_pages').val(),
csrfmiddlewaretoken: "{{ csrf_token }}"
},
success: function () {
alert('Form submitted successfully!!');
}
})
})
I tried to convert it to JavaScript, however it add objects to model, but it refreshes the page and moreover it shows a 403 error in console and then fade away.
document.querySelector('#addbookform').onsubmit = savebook;
function savebook() {
const name = document.querySelector('#name').value;
const price = document.querySelector('#price').value;
const num_of_pages = document.querySelector('#num_of_pages').value;
const url = "{% url 'books:home' %}"
const xhr = new XMLHttpRequest();
xhr.onload = function () {
if (this.status == 200) {
alert("Saved!");
}
}
xhr.open('POST', url, true);
xhr.send();
}
Can you please help me solve it?
In my React front end, I call Axios with post method successfully, in my Python Falcon backend parameters are received successfully and token is generated back,
problem is the code in .then or even .catch are never called, here is my front end code:
async submit() {
//var aluser = this.this.state.username;
await axios({
method: "post",
url: "http://127.0.0.1:8000/Login",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
params: {
username: this.state.username,
password: this.state.password
}
})
.catch(error => {
console.log(
"here is the error on a post request from the python server ",
error
);
})
.then(res => {
console.log(res);
sessionStorage.setItem("token", res.data[0]);
});
}
Note: the order of .then .catch was switched before, same result.
Thanks in advance
try to use try/catch
const params = new URLSearchParams();
params.append('username', this.state.username);
params.append('password', this.state.password);
async submit() {
//var aluser = this.this.state.username;
try {
const res = await axios({
method: "post",
url: "http://127.0.0.1:8000/Login",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
params
})
sessionStorage.setItem("token", res.data[0]);
} catch (err) {
console.log(
"here is the error on a post request from the python server ",
error
);
}
}
If your backend service is only returning a 200 response, axios will not call "then" because you haven't send response data back. I just sent an "OK" response payload back with my 200 status code. "then" was called as expected.
I am working on REST API using Django and Django Rest Framework.
In the front-end I have AngularJs app.
I have used Token authentication for APIs. This disables the CSRF checks.
I want keep CSRF validation with REST API. How to achieve this ?
How should I get CSRF Token value so that it can be set into the header of every POST request, using interceptor of my angular application.
I have this configuration in my app.js. Should do the trick!
app.config(function($httpProvider) {
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
});
I've got the same problem when i started to use Angular 1.x with Django and DRF, and then i found this code snippet in a book i think, and it works fine for me. Include this file in your base.html file or your main html file before any javascript import, and everything will work smoothly and you can start talking to your backend.
// Place at /static/js/csrf.js
// CSRF helper functions taken directly from Django docs
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/ ˆ (GET|HEAD|OPTIONS|TRACE) $ /.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
I have some AJAX that polls the server every 5 seconds:
var date = $('article').first().find('time').text();
console.log(date);
setInterval(function() {
$.post('pollNewEntries', {'date':date}, newEntrySuccess)
}, 5000);
Unfortunately, I'm getting a 403 error every time the AJAX tries to poll the server, stating that I have made an invalid CSRF request. I've used AJAX with forms before and included the CSRF token within the forms, but I"m not sure how I would do it with a formless AJAX request like above.
The solution to this problem is described in the Django documentation: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Add this code to the top of your js:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
You need to pass csrf token along with your post data:
var date = $('article').first().find('time').text();
console.log(date);
setInterval(function() {
$.post('pollNewEntries', {'date':date, 'csrfmiddlewaretoken': '{{csrf_token}}'}, newEntrySuccess)
}, 5000);
Simply add these lines in your script. Here is an example in coffeescript :
### CSRF methods ###
csrfSafeMethod = (method) ->
# these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method))
$.ajaxSetup(
crossDomain: false
beforeSend: (xhr, settings) ->
if !csrfSafeMethod(settings.type)
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'))
)
Read the documentation : CSRF
In other hand, as user1427661 suggests to you, it will be better to use HTTP GET method instead of POST, because you only need to read data and don't write anything. See the W3 docs.