Adding beforeSend function to XMLHttpRequest request - javascript

I'm trying to add Ajax like beforeSend function to my XMLHttpRequest. I'm getting following error:
TypeError: Cannot read property 'type' of undefined
Here is my code:
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function beforeSend(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
var http = new XMLHttpRequest();
http.open('POST', messageEndpoint, true);
http.setRequestHeader('Content-type', 'application/json');
http.onreadystatechange = function() {
if (http.readyState === 4 && http.status === 200 && http.responseText) {
Api.setResponsePayload(http.responseText);
}
};
var params = JSON.stringify(payloadToWatson);
if (Object.getOwnPropertyNames(payloadToWatson).length !== 0) {
Api.setRequestPayload(params);
}
// Added beforeSend() function before sending the params
beforeSend();
http.send(params);

I notice your using jQuery... then you can use $ajax method; here an example
$ajax({
url: 'yourURLhere',
data: {some: 'value'},//{} or [] or ""
method: 'POST',
beforeSend: function(jqXHR, settings) {
// do something
},
success: function(data) {
},
error: function(err) {
}
})

Anyone who was in my situation and trying to send csrf token with XMLHttpRequest request. Here is how I solved it:
Create csrf token:
var csrfcookie = function() {
var cookieValue = null,
name = 'csrftoken';
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
Build http request:
var http = new XMLHttpRequest();
http.open('POST', messageEndpoint, true);
http.setRequestHeader('X-CSRFToken', csrfcookie());

Related

I'm using vanilla js to make a ajax post request to django

I'm trying to make a ajax post request to django this is js snippet
const xhr = new XMLHttpRequest();
console.log(xhr.readyState);
xhr.open('POST', '');
var data = '{% csrf_token %}';
console.log(data);
console.log(typeof(data));
xhr.setRequestHeader('X-CSRF-Token', data);
xhr.onload = function(){
console.log(xhr.readyState);
console.log(xhr.status);
if(xhr.status == 200){
console.log(JSON.parse(xhr.responseText));
}else{
console.log("Something went wrong!!");
}
}
xhr.send({'userId' : userId})
}
This is my error log:
I've been getting a 403 forbidden error can anybody help me out?
This function should get you the csrf-token
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// 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;
}
then:
const csrftoken = getCookie('csrftoken');
to get the csrf-token.
What also might be worth looking at is changing X-CSRF-Token
xhr.setRequestHeader('X-CSRF-Token', data);
to X-CSRFToken
xhr.setRequestHeader('X-CSRFToken', data);
hope this helps
The {% csrf_token %} in the templates page translates to:
<input type="hidden" name="csrfmiddlewaretoken" value="WRWu3DwbdHDl1keRwSqUNrvcwZXqhCzkInEGVftyuwWG0v5kBBzeGrZ34wKpjFB5">
We need to get the CSRF token , i.e., the value of this element:
x = document.getElementsByName("csrfmiddlewaretoken")[0].value;
Then, we need to pass this value to the setRequestHeader method of the JSON request, with "X-CSRFToken" as the first argument:
function requestJSON() {
x = document.getElementsByName("csrfmiddlewaretoken")[0].value;
jsonRequest = new XMLHttpRequest();
jsonRequest.overrideMimeType("application/json");
jsonRequest.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200 ) {
var j = JSON.parse(this.responseText);
// do whatever with the JSON data
}
else {console.log(this.status);}
};
jsonRequest.open("POST","url/");
jsonRequest.setRequestHeader("content-type","application/x-www-form-urlencoded");
jsonRequest.setRequestHeader("X-CSRFToken",x);
jsonRequest.send();
}

JavaScript equivalent of Python's oauth2client POST request to Google Reminders

I would like to port this open source Python library for Google Reminders to JavaScript:
https://github.com/jonahar/google-reminders-cli
I have ported the authorization with the help of https://developers.google.com/identity/protocols/OAuth2UserAgent
My JavaScript version: https://github.com/Jinjinov/google-reminders-js
Now I need to port the Python's oauth2client POST request:
body = {
'5': 1, # boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
'6': num_reminders, # number number of reminders to retrieve
}
HEADERS = {
'content-type': 'application/json+protobuf',
}
response, content = self.auth_http.request(
uri='https://reminders-pa.clients6.google.com/v1internalOP/reminders/list',
method='POST',
body=json.dumps(body),
headers=HEADERS,
)
My XMLHttpRequest POST request returns:
HTTP 400 - Bad Request - if I use 'application/x-www-form-urlencoded'
HTTP 401 - Unauthorized - if I use 'application/json'
My code (full code with authorization and access token is on GitHub):
function encodeObject(params) {
var query = [];
for (let key in params) {
let val = encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
query.push(val);
}
return query.join('&');
}
function list_reminders(num_reminders, access_token, callback) {
var body = {
'5': 1, // boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
'6': num_reminders, // number of reminders to retrieve
};
body['access_token'] = access_token;
//body = JSON.stringify(body);
body = encodeObject(body);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list' + '?' + body);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
//xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list');
//xhr.setRequestHeader('Content-type', 'application/json');
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
var content_dict = JSON.parse(xhr.response);
if (!('1' in content_dict)) {
console.log('No reminders found');
}
else {
var reminders_dict_list = content_dict['1'];
var reminders = [];
for(var reminder_dict of reminders_dict_list) {
reminders.push(build_reminder(reminder_dict));
}
callback(reminders);
}
}
else if (xhr.readyState === 4 && xhr.status === 401) {
callback(null);
}
}
//xhr.send(body);
xhr.send(null);
}
I was trying to send both, the body and the access token in the same way.
The solution is to send the access token as url encoded and the body as json:
function list_reminders(num_reminders, access_token, callback) {
/*
returns a list of the last num_reminders created reminders, or
None if an error occurred
*/
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list' + '?' + 'access_token=' + access_token);
xhr.setRequestHeader('Content-type', 'application/json+protobuf');
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
var content_dict = JSON.parse(xhr.response);
if (!('1' in content_dict)) {
console.log('No reminders found');
}
else {
var reminders_dict_list = content_dict['1'];
var reminders = [];
for(var reminder_dict of reminders_dict_list) {
reminders.push(build_reminder(reminder_dict));
}
callback(reminders);
}
}
else if (xhr.readyState === 4 && xhr.status === 401) {
callback(null);
}
}
var body = {
'5': 1, // boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
'6': num_reminders, // number of reminders to retrieve
};
xhr.send(JSON.stringify(body));
}

How to write one javascript function to perform an ajax request without repeating to avoid code-smell without using JQuery library

i have a javascript code that uses objects and attributes to perform different ajax requests. i want to find a way that i can optimize my code to avoid repetition and code-smell. i have an object trip that has list which should fetch the details from the database and append to my servlet defined with a path ./trips/action/ . No JQuery needed
var trip = {
list: function(){
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function(){
if(ajax.readyState == 4){
if(ajax.status == 200){
document.getElementById('ajax-content').innerHTML = ajax.responseText;
}
}
}
ajax.open("GET", "./trips/action", true);
ajax.send();
},
add: function(){
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function(){
if(ajax.readyState == 4){
if(ajax.status == 200){
document.getElementById('ajax-content').innerHTML = ajax.responseText;
}
}
}
ajax.open("GET", "./trip/addTrip.jsp", true);
ajax.send();
},
save: function(){
var me = this;
var ajax = new XMLHttpRequest();
var depatureDate = document.getElementById('depatureDate').value;
var arrivalDate = document.getElementById('arrivalDate').value;
var route = document.getElementById('route').value;
var vehicle = document.getElementById('vehicle').value;
var price = document.getElementById('price').value;
var params = 'depatureDate=' + encodeURIComponent(depatureDate)
+ '&arrivalDate=' + encodeURIComponent(arrivalDate)
+ '&route=' + encodeURIComponent(route)
+ '&vehicle=' + encodeURIComponent(vehicle)
+ '&price=' + encodeURIComponent(price);
console.log(params);
ajax.onreadystatechange = function(){
if(ajax.readyState == 4){
if(ajax.status == 200){
me.list();
}
}
}
ajax.open("POST", "./trips/action/add", true);
ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
ajax.send(params);
}
}
You can create utility functions:
var utils = {
ajax: function(url, method, params, callback) {
if (typeof callback == 'undefined') {
callback = arguments[1];
params = null;
}
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function() {
if (ajax.readyState == 4){
if (ajax.status == 200){
if (typeof callback == 'function') {
callback(ajax.responseText);
}
}
}
}
ajax.open(method, url, true);
if (params) {
ajax.send(params);
} else {
ajax.send();
}
},
get: function(url, params, callback) {
this.ajax(url, 'GET', params, callback);
},
post: function(url, params, callback) {
this.ajax(url, 'POST', params, callback);
}
};
and you can use it in your code:
var trip = {
list: function(){
util.get("./trips/action", function(data) {
document.getElementById('ajax-content').innerHTML = data;
});
},
...
};

403 (FORBIDDEN)

I'm trying to send $ajax, and I have got it, but I have to send file with my form, in the same or not, doesn't matter. csrf token has not been found and I'm getting error.
My javascript
$(document).ready(function() {
var csrf_token = $('input[name="_token"]').val();
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
// $("body").bind("ajaxSend", function(elm, xhr, s) {
// if (s.type == "POST") {
// xhr.setRequestHeader('X-CSRF-Token', csrf_token);
// }
// });
window.getCookie = function(cname) { //window for testing in console
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
}
return "";
};
function sendPost() {
var data = $('form').serialize();
var file = $(document.getElementById('files').files[0]);
$.ajax({
type: 'POST',
url: '/delling_data_objects/document/',
//data: $('form').serialize(), it's working
data: file, // its don't
enctype: 'multipart/form-data',
headers: window.getCookie('csrftoken')
});
};
$('#submit').on('click', function() {
sendPost();
});
});
my view.py
def load_files(request):
form = ApartForm(request.POST)
import pdb
pdb.set_trace()
if form.is_valid():
form.save()
file_form = request.POST['file']
for f in file_form:
with open(f) as dest:
for chunk in f.chunks():
dest.write(chunk)
else:
return HttpResponse('form is not valid')
return HttpResponse('ok')
You are not doing it correctly. It feels like you are sending the requestHeader twice.(edit: nevermind didn't see a part of the code was commented)
Based on your code, try something like this :
function sendPost() {
var data = $('form').serialize();
var file = $(document.getElementById('files').files[0]);
var csrftoken = getCookie("csrftoken");
$.ajax({
method: "POST",
url: '/delling_data_objects/document/',
data: data,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
success: function(data) {
// whatever you want to do
}
});
}
$('#submit').on('click', function() {
sendPost();
});
var getCookie = function(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 csrfSafeMethod = function (method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
};

consuming API JSon calls through TVJS-tvOS

I am trying to play with tvOS, and I have small question regarding handling json call. I have to get some data through an API, let's say for sake of test that I am calling this link
http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%223015%22&format=json
I tried to use this function with some modification
function getDocument(url) {
var templateXHR = new XMLHttpRequest();
templateXHR.responseType = "json";
templateXHR.open("GET", url, true);
templateXHR.send();
return templateXHR;
}
but didn't work out. Any hints or help ?
If I need to use NodeJS, how can I do that ?
This is one that I got working. It's not ideal in many respects, but shows you something to get started with.
function jsonRequest(options) {
var url = options.url;
var method = options.method || 'GET';
var headers = options.headers || {} ;
var body = options.body || '';
var callback = options.callback || function(err, data) {
console.error("options.callback was missing for this request");
};
if (!url) {
throw 'loadURL requires a url argument';
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onreadystatechange = function() {
try {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback(null, JSON.parse(xhr.responseText));
} else {
callback(new Error("Error [" + xhr.status + "] making http request: " + url));
}
}
} catch (err) {
console.error('Aborting request ' + url + '. Error: ' + err);
xhr.abort();
callback(new Error("Error making request to: " + url + " error: " + err));
}
};
xhr.open(method, url, true);
Object.keys(headers).forEach(function(key) {
xhr.setRequestHeader(key, headers[key]);
});
xhr.send();
return xhr;
}
And you can call it with the following example:
jsonRequest({
url: 'https://api.github.com/users/staxmanade/repos',
callback: function(err, data) {
console.log(JSON.stringify(data[0], null, ' '));
}
});
Hope this helps.
I tested this one out on the tvOS - works like a charm with jQuery's syntax (basic tests pass):
var $ = {};
$.ajax = function(options) {
var url = options.url;
var type = options.type || 'GET';
var headers = options.headers || {} ;
var body = options.data || null;
var timeout = options.timeout || null;
var success = options.success || function(err, data) {
console.log("options.success was missing for this request");
};
var contentType = options.contentType || 'application/json';
var error = options.error || function(err, data) {
console.log("options.error was missing for this request");
};
if (!url) {
throw 'loadURL requires a url argument';
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = timeout;
xhr.onreadystatechange = function() {
try {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (xhr.responseType === 'json') {
success(null, xhr.response);
} else {
success(null, JSON.parse(xhr.responseText));
}
} else {
success(new Error("Error [" + xhr.status + "] making http request: " + url));
}
}
} catch (err) {
console.error('Aborting request ' + url + '. Error: ' + err);
xhr.abort();
error(new Error("Error making request to: " + url + " error: " + err));
}
};
xhr.open(type, url, true);
xhr.setRequestHeader("Content-Type", contentType);
xhr.setRequestHeader("Accept", 'application/json, text/javascript, */*');
Object.keys(headers).forEach(function(key) {
xhr.setRequestHeader(key, headers[key]);
});
if(!body) {
xhr.send();
} else {
xhr.send(body);
}
return xhr;
}
Example queries working on Apple TV:
var testPut = function(){
$.ajax({
type: 'PUT',
url: url,
success: successFunc,
error: errFunc,
dataType: 'json',
contentType: 'application/json',
data: data2
});
}
var testGet = function(){
$.ajax({
dataType: 'json',
url: url,
success: successFunc,
error: errFunc,
timeout: 2000
});
}
var getLarge = function(){
$.ajax({
dataType: 'json',
url: url,
success: successFunc,
error: errFunc,
timeout: 2000
});
}
Did you call your function in the 'App.onLaunch'
App.onLaunch = function(options) {
var url = 'http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%223015%22&format=json';
var doc = getDocument(url);
console.log(doc);
}
Might be worth looking at https://mathiasbynens.be/notes/xhr-responsetype-json
I came across this question looking to accomplish the same thing, and was inspired by #JasonJerrett's answer, but found it a bit lacking because in my instance I am using an XML template built in Javascript like this:
// Index.xml.js
var Template = function() {
return `very long xml string`;
};
The issue is that you can't perform the XHR request inside the template itself, because the template string will be returned back before the XHR request actually completes (there's no way to return data from inside an asynchronous callback). My solution was to modify the resource loader and perform the XHR request there, prior to calling the template and passing the data into the template function:
ResourceLoader.prototype.loadResource = function(resource, dataEndpoint, callback) {
var self = this;
evaluateScripts([resource], function(success) {
if (success) {
// Here's the magic. Perform the API call and once it's complete,
// call template constructor and pass in API data
self.getJSON(dataEndpoint, function(data) {
var resource = Template.call(self, data);
callback.call(self, resource);
});
} else {
var title = "Failed to load resources",
description = `There was an error attempting to load the resource. \n\n Please try again later.`,
alert = createAlert(title, description);
Presenter.removeLoadingIndicator();
navigationDocument.presentModal(alert);
}
});
}
// From: https://mathiasbynens.be/notes/xhr-responsetype-json
ResourceLoader.prototype.getJSON = function(url, successHandler, errorHandler) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.onreadystatechange = function() {
var status;
var data;
if (xhr.readyState == 4) {
status = xhr.status;
if (status == 200) {
data = JSON.parse(xhr.responseText);
successHandler && successHandler(data);
} else {
errorHandler && errorHandler(status);
}
}
};
xhr.send();
};
Then the template function needs to be modified to accept the incoming API data as a parameter:
// Index.xml.js
var Template = function(data) {
return 'really long xml string with injected ${data}';
};
You need to implement the onreadystatechange event on the XHR object to handle the response:
templateXHR.onreadystatechange = function() {
var status;
var data;
if (templateXHR.readyState == 4) { //request finished and response is ready
status = templateXHR.status;
if (status == 200) {
data = JSON.parse(templateXHR.responseText);
// pass the data to a handler
} else {
// handle the error
}
}
};
If you want to call the request on app launch, just add in application.js:
App.onLaunch = function(options) {
var javascriptFiles = [
`${options.BASEURL}js/resourceLoader.js`,
`${options.BASEURL}js/presenter.js`
];
evaluateScripts(javascriptFiles, function(success) {
if(success) {
resourceLoader = new ResourceLoader(options.BASEURL);
var index = resourceLoader.loadResource(`${options.BASEURL}templates/weatherTemplate.xml.js`, function(resource) {
var doc = Presenter.makeDocument(resource);
doc.addEventListener("select", Presenter.load.bind(Presenter));
doc.addEventListener('load', Presenter.request);
navigationDocument.pushDocument(doc);
});
} else {
var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
navigationDocument.presentModal(errorDoc);
}
});
}
In presenter.js add a method:
request: function() {
var xmlhttp = new XMLHttpRequest() , method = 'GET' , url = 'your Api url';
xmlhttp.open( method , url , true );
xmlhttp.onreadystatechange = function () {
var status;
var data;
if (xmlhttp.readyState == 4) {
status = xmlhttp.status;
if (status == 200) {
data = JSON.parse(xmlhttp.responseText);
console.log(data);
} else {
var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
navigationDocument.presentModal(errorDoc);
}
}
};
xmlhttp.send();
},

Categories

Resources