Django - Sending POST request from javascript - javascript

I have a JS event-triggered function which goal is send a POST request in order to update some objects in my database. The event which triggers the function is a drop-event, so i initially avoided using forms to pass my request, but tell me if i did wrong.
Big Edit:
I found that my mistake was to not include the csrf_token on my post request.
However, i still have an error: my post request comes in empty when i do print(request.POST) on my django view.
My JS file:
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 = 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;
}
var csrftoken = getCookie('csrftoken');
const dragDrop = function (e) {
e.preventDefault()
const droppedElId = e.dataTransfer.getData('Text/html').split('__id-')[1]
const request = new XMLHttpRequest()
request.open('POST', '', true)
request.setRequestHeader('X-CSRFToken', csrftoken)
request.setRequestHeader('Content-Type', 'application/json')
// request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
request.send(JSON.stringify({
"request_name":"change-extra-fields",
"type":"increase",
"id":droppedElId,
}))
}
The query-dict of the request.POST is empty when i do this. However, the request works if i change the Content-Type header to application/x-www-form-urlencoded, but it puts everything on the same key.
Example:
Result with 'application/json':
<QueryDict: {}>
Result with 'application/x-www-form-urlencoded':
<QueryDict: {'{"request_name":"change-extra-fields","type":"increase","id":"8"}': ['']}>
Anyways, i think that 'application/json' should be working and i have no idea why it isn't..

There is a typo I think
request.setRequestHeader('Content-Type', 'application/json');
As you mentioned in comments, your post request required you to be authenticated.
So, you first need to authenticate/login to the site(using another Ajax call perhaps). If the site supports jwt/api authentication you would get a token back which you have to send in attached with header in next (post)request. it would be something like this
xhr.setRequestHeader('Authorization', 'Bearer arandombereartoken');
if the site uses session/cookie authentication then I suggest consider using jQuery and its Ajax functions.
I this this(2nd one) should be helpful.
UPDATE:
if you want to get data as application/json you have to look in the body of the request
if request.method == "POST":
print(request.body)
this would give you a byte object. you have load it to a json if you want json. request.POST is only for Content-Type 'application/x-www-form-urlencoded'

Related

Create checkout session NBG

I would like to make a Basic HTTP authentication call request via javascript but I do not know how to do it.. I have a javascript code and inside of it there is a session parameter. Thus, I need to make first this call, get the session_id from this call as a response and continue my javascript code. This is the doc of this basic http auth: https://ibanke-commerce.nbg.gr/api/documentation/apiDocumentation/rest-json/version/latest/operation/Session%3a%20Create%20Checkout%20Session.html?locale=en_US
It is about payment option between bank and ecommerce.
How will this be written in javascript?
My code structure is like this for now:
<script
//need call auth somewhere here I guess
Payment.Config({
... ... ..
Url: "...",
Name: "...",
session: "here I need the response of the call"
...
...
});
</script>
Any help/guidelines would be appreciated
You need three things:
1. Create you Basic Header for your authentication
The Basic Header is an Base64 encoded string of your user and
password. To get that you should encode your credentials as shown below.
user_id:password
In you case user_id is the merchantId
You can use online services like this to encode your credentials strings
Or
You can encode it in your javascript code like this
var clientId = "user_id";
var clientSecret = "password";
// var authorizationBasic = $.base64.btoa(clientId + ':' + clientSecret); // jQuery
var authorizationBasic = window.btoa(clientId + ':' + clientSecret); // Javascript
I would recommend the first option.
2. Make your post request with the Basic Header
You can follow this answer on how to make an HTTP POST authentication basic request using Javascript
3. Use the response from the authentication request in your code
So your final code would be something like this
var url = 'your_url_server';
var authorizationBasic = 'the_created_basic_header';
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.setRequestHeader('Authorization', 'Basic ' + authorizationBasic);
request.setRequestHeader('Accept', 'application/json'); // Modify according to the response format
request.send("parameter1=parameter1_value&parameter2=parameter2_value"); // Any parameter you might need
request.onreadystatechange = function () {
if (request.readyState === 4) {
alert(request.responseText);
Payment.Config({
... ... ..
Url: "...",
Name: "...",
session: request.responseText // Here is the response of the call
...
...
});
}
};

How to send csrf token in AJAX request (Without Jquery) in expressjs?

I am using the csurf module in expressjs. It works for all post requests as I use it the following way.
app.use(csrf());
res.locals.csrfToken = req.csrfToken();
This way its automatically available in all forms where I have the following.
<input type="hidden" name="_csrf" value="<%=csrfToken%>">
but how do I set the csrftoken on AJAX requests, I am not using jquery, below is the JS function to send AJAX request. I do have the csrf token available on the html as a hidden value that I have access via getElementByID.
note: I am able to send the request if I disable csrf.
function voteQuestion () {
var qid = document.getElementById("qid").value;
var csrf = document.getElementById("csrf").value;
var http = new XMLHttpRequest();
var url = "/q/ajaxcall";
var params = "qid="+ qid;
http.open("POST", url);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == XMLHttpRequest.DONE && http.status == 200) {
var json = (http.responseText);
var obj = JSON.parse(json);
document.getElementById("vote-sp").innerHTML = (obj.upvotes);
}
};
http.send(params);
}
I have been trying to figure this out for almost a week now, and just decided to console.log req.session and found cookies contains "XSRF-TOKEN" value, so in the AJAX request header I set XSRF-TOKEN to csrf and now it works, I dont know why it works this way particularly for AJAX requests.
setRequestHeader("XSRF-TOKEN", csrf);
Set crsf token in your params as below..
var params = "qid="+ qid + "&crsf="+csrf;
OR
You can create a new object for sending data as below..
var data = {}; //crates new object
data.qid = qis; //adds qid to object
data.csrf = csrf; //adds qid to object
params = data; // to server

How do i correctly format parameters passed server-side using javascript?

I cannot figure out how to get the following code working in my little demo ASP.NET application, and am hoping someone here can help.
Here is the javascript:
function checkUserName() {
var request = createRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var theName = document.getElementById("username").value;
var userName = escape(theName);
var url = "Default.aspx/CheckName";
request.onreadystatechange = createStateChangeCallback(request);
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/json");
//none of my attempts to set the 'values' parameter work
var values = //JSON.stringify({userName:"userName"}); //"{userName:'temp name'}"; //JSON.stringify({ "userName":userName });
request.send(values);
}
}
Here is the method in my *.aspx.cs class:
[WebMethod]
[ScriptMethod(UseHttpGet=true)]
public static string CheckName(string userName)
{
string s = "userName";
return s + " modified backstage";
}
When this code runs I receive this exception:
---------------------------
Message from webpage
---------------------------
{"Message":"Invalid web service call, missing value for parameter: \u0027userName\u0027.","StackTrace":" at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}
---------------------------
OK
---------------------------
I started searching here, then went on to several threads on SO, trying quite a few combinations of quotation marks and key-value pairs, but nothing I've tried has worked.
When I remove the parameter from the C# method and request.send(), I get a response in my JS callback that I can work with. But as soon as I try to do something with parameters, I get the above exception. I'd like to know how to do this without using jQuery, if possible.
Thanks in advance.
FINAL VERSION
Using Alexei's advice, I ended up with the following, which works. The URL was missing the apostrophes on either end of the parameter value; this was keeping the call from going through.
function checkUserName() {
var request = createRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var theName = document.getElementById("username").value;
var userName = encodeURIComponent(theName);
var url = "Default.aspx/CheckName?name='" + theName + "'";
request.onreadystatechange = createStateChangeCallback(request);
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/json");
request.send();
}
}
request.send(values);
This won't work with a "GET". Try
request.open("POST", url, true);
http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp
You need to:
decide whether you want GET or POST. For GET request you need all parameters to be in Url (and body to be empty), for POST you can use both. As of current code you are expecting GET, but sending POST.
properly add query parameter - name and encoded value. encodeUriComponent is JavaScript function of choice, see Build URL from Form Fields with Javascript or jquery for details
if using POST you need to properly encode parameters there too as well specify correct "content-type" header.
if sending JSON you need to decode JSON server side.
Alternatively you can use hidden form to perform POST/GET as covered in JavaScript post request like a form submit
Side note: jQuery.ajax does most of that for you and good source to look through if you want to do all yourself.
Like Alan said, use the POST method. Or pass your arguments in your URL before opening it, e.g.
var url = "Default.aspx/CheckName?userName=" + values;
EDIT : no, it's probably a bad idea since you want to send JSON, forget what I said.
If you need to go for POST, then you need to send it like this.
var values = JSON.stringify({"'userName':'"+ userName+ "'"});
And you have to change HttpGet to HttpPost
Given that your server side method asks for GET, you need:
request.open("GET", url + "?username=" + userName, true);
request.send();
The works for me:
function checkUserName() {
var request = new XMLHttpRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var userName = "Shaun Luttin";
var url = '#Url.RouteUrl(new{ action="CheckName", controller="Home"})';
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE ) {
if(request.status == 200){
document.getElementById("myDiv").innerHTML = request.responseText;
}
else if(request.status == 400) {
alert('There was an error 400')
}
else {
alert('something else other than 200 was returned')
}
}
}
request.open("GET", url + "?username=" + userName, true);
request.send();
}
}
With this on the server side:
[HttpGet]
public string CheckName(string userName)
{
return userName + " modified backstage";
}

Sending a JSON to server and retrieving a JSON in return, without JQuery

I need to send a JSON (which I can stringify) to the server and to retrieve the resulting JSON on the user side, without using JQuery.
If I should use a GET, how do I pass the JSON as a parameter? Is there a risk it would be too long?
If I should use a POST, how do I set the equivalent of an onload function in GET?
Or should I use a different method?
REMARK
This question is not about sending a simple AJAX. It should not be closed as duplicate.
Sending and receiving data in JSON format using POST method
// Sending and receiving data in JSON format using POST method
//
var xhr = new XMLHttpRequest();
var url = "url";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log(json.email + ", " + json.password);
}
};
var data = JSON.stringify({"email": "hey#mail.com", "password": "101010"});
xhr.send(data);
Sending and receiving data in JSON format using GET method
// Sending a receiving data in JSON format using GET method
//
var xhr = new XMLHttpRequest();
var url = "url?data=" + encodeURIComponent(JSON.stringify({"email": "hey#mail.com", "password": "101010"}));
xhr.open("GET", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log(json.email + ", " + json.password);
}
};
xhr.send();
Handling data in JSON format on the server-side using PHP
<?php
// Handling data in JSON format on the server-side using PHP
//
header("Content-Type: application/json");
// build a PHP variable from JSON sent using POST method
$v = json_decode(stripslashes(file_get_contents("php://input")));
// build a PHP variable from JSON sent using GET method
$v = json_decode(stripslashes($_GET["data"]));
// encode the PHP variable to JSON and send it back on client-side
echo json_encode($v);
?>
The limit of the length of an HTTP Get request is dependent on both the server and the client (browser) used, from 2kB - 8kB. The server should return 414 (Request-URI Too Long) status if an URI is longer than the server can handle.
Note Someone said that I could use state names instead of state values; in other words I could use xhr.readyState === xhr.DONE instead of xhr.readyState === 4 The problem is that Internet Explorer uses different state names so it's better to use state values.
Using new api fetch:
const dataToSend = JSON.stringify({"email": "hey#mail.com", "password": "101010"});
let dataReceived = "";
fetch("", {
credentials: "same-origin",
mode: "same-origin",
method: "post",
headers: { "Content-Type": "application/json" },
body: dataToSend
})
.then(resp => {
if (resp.status === 200) {
return resp.json()
} else {
console.log("Status: " + resp.status)
return Promise.reject("server")
}
})
.then(dataJson => {
dataReceived = JSON.parse(dataJson)
})
.catch(err => {
if (err === "server") return
console.log(err)
})
console.log(`Received: ${dataReceived}`)
You need to handle when server sends other status rather than 200(ok), you should reject that result because if you were to left it in blank, it will try to parse the json but there isn't, so it will throw an error

Force "charset=x-user-defined'" on jQuery Ajax Post

I am trying to call a Hessian web service from a Javascript application, but I'm having issues parsing the response, since jQuery is treating the response as text and stripping the first bytes of it.
In my research, I have found out that you need to set the charset as 'charset=x-user-defined' in order to the browser leave my bytes as is. But, according the ajax docs:
Sending Data to the Server
By default, Ajax requests are sent using the GET HTTP method. If the
POST method is required, the method can be specified by setting a
value for the type option. This option affects how the contents of the
data option are sent to the server. POST data will always be
transmitted to the server using UTF-8 charset, per the W3C
XMLHTTPRequest standard.
And indeed, the charset is not changing regardless of the settings I used. I have tried the following, separately and all at once, with no luck
$.ajax({
type : 'POST',
url : url,
timeout : 3000,
data : parameters,
contentType : "x-application/hessian; charset=x-user-defined'",
mimeType: 'text/plain; charset=x-user-defined',
headers: {
Accept : "text/plain; charset=x-user-defined",
"Content-Type": "text/plain; charset=x-user-defined"
},
beforeSend : function(xhr) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
}
})
Also I tried to mess around with the data converters and custom contenttypes defined in jQuery, with no succes.
It appears that as per the standard, I will not be able to do this. It works with GET but not with POST, and the Hessian protocol requires POST.
Do you have any ideas? Or do I need to start to build my XHR method form scratch?
Turns out that I was making a silly mistake somewhere else. But anyhow, I found a sweet way for handling binary data on request and responses, from here.
define(function() {
// Do setup work here
function configurationException(message) {
throw new Error(message + " missing from configuration object");
}
return {
post : function(config) {
if (config) {
var url = config.url || configurationException("url");
var done = config.done || configurationException("callback function");
var timeout = config.timeout || 10000;
var data;
if (config.data) {
data = config.data;
} else {
data = null;
console.warn('No data is specified in binaryPost');
}
var request = new XMLHttpRequest();
request.open("POST", url, true);
request.responseType = "arraybuffer";
request.setRequestHeader("Content-Type", "x-application/hessian;");
request.onload = function(oEvent) {
var arrayBuffer = request.response; // Note: not oReq.responseText
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
done(byteArray);
}
};
request.send(data);
} else {
throw new Error("Configuration object is missing");
}
}
};
});
Hope you find it useful

Categories

Resources