edit for future reference
Solved:
on fetch request in script.js, I used Headers instead of headers, hence the "Missing csrf token" instead of missing or incorrect
So i'm building a project in Django for a "password manager" I've built my modules and correctly implemented the Item insertion via Django ModelForm, with csrftoken and all that.
Now i need to make an ajax request for updating the fields of the Item, and wanted to do on the same page
so from Js when opening a LoginItem to edit the content I send a GET request as such
//fetch django for a form, and it sends back pre filled with initial values
fetch(`edit/login=id`)
.then((response) => response.text())
.then((form) => {
const edit_form = document.createElement('form');
edit_form.setAttribute("method", "post");
edit_form.setAttribute("id", "edittest");
edit_form.innerHTML = form;
//append the form
then in script.js, on submit:
fetch(`edit/login=id}`, {
method : "PUT",
Headers:{
//or "X-CSRFToken":event.target.querySelector('[name=csrfmiddlewaretoken]').value
"X-CSRFToken": getCookie("csrftoken"),
"Content-type": "application/json",
},
mode:"same-origin",
body : JSON.stringify(body),
})
.then((response) => response.json())
.then((data) => {
console.log(data)
})
in Views.py
def edit_login(request, id):
if request.method == GET:
login = Entry.objects.get(id=id)
// setting initial values for the form
initial = {
"title": login.title,
"username": login.username,
"password": login.password,
"note": login.note,
"folder": login.folder,
"protected":login.protected,
"favorite": login.favorite,
}
// setting the initial values to the ModelForm
form = LoginForm(initial=edit)
return render(request, 'vault/new_item.html', {"entry_form": form, 'uri_field': uri})
else if request.method == "PUT":
if request.user == login.owner:
data = json.loads(request.body)
print("test") # execution does not reach here
return JsonResponse({"message": "Succesfully edited"}, status = 200 ) # oppure 204 = No content
I get Forbidden (CSRF token missing.): /edit/login=27
In the PUT fetch request I also tried instead of getCookie()
using "X-CSRFToken":event.target.querySelector('[name=csrfmiddlewaretoken]').value to get this form's csrf input value that gave me a different csrftoken than the previous.
Also if I inspect every element I open, i see each of them has a different csrftoken (ok, different requests, so I could fathom the error Incorrect Token, but the missing error i don't understand.
Also, if anyone has a hint on how to do this in an easier way, that'd be great, I have limited knowledge
The simplest way I have solved this problem is by including the {{csrf_token}} value in the data without using #csrf_exempt decorator in Django(The decorator marks a view as being exempt from the protection ensured by the middleware.):
var csrftoken = "{{csrf_token}}";
//Sample ajax request
$.ajax({
url: url,
type: 'POST',
headers:{
"X-CSRFToken": csrftoken
},
data: data,
cache: true,
});
Related
I'm trying to send form data from a NativeScript app to a TYPO3-Webservice.
This is the JavaScript I'm using:
httpModule.request({
url: "https://my.domain.tld/webservice?action=login",
method: "POST",
headers: { "Content-Type": "application/json" },
content: JSON.stringify({
username:username,
password:password
})
}).then((response) => {
console.log("got response");
console.log(response.content);
//result = response.content.toJSON();
callback(response.content.toJSON());
}, (e) => {
console.log("error");
console.log(e);
});
But I can't read this data in the controller. Even with this:
$rest_json = file_get_contents("php://input");
$postvars = json_decode($rest_json, true);
$postvars is empty. $_POST is empty, too (which is - according to some docs - because the data is sent as JSON and thus the $_POST-Array isn't populated.
Whatever I do, whatever I try, I can't get those variables into my controller.
I tried it with fetch as well as with formData instead of JSON.stringify, same result.
I might have to add, that when I add the PHP-part in the index.php of TYPO3, $postvars is being populated. So I guess something goes missing, until the controller is called.
Any ideas?
the nativescript part seems ok, your problem must be corrected in the server side.
i use similare call and its works
// send POST request
httpModule.request({
method: "POST",
url: appSettings.getString("SERVER") + '/product/list',
content: JSON.stringify(data),
headers: {"Content-Type": "application/json"},
timeout: 5000,
}).then(response => { // handle replay
const responseAsJson = response.content.toJSON();
console.log('dispatchAsync\n\tresponse:', responseAsJson);
}, reason => {
console.error(`[ERROR] httpModule, msg: ${reason.message}`);
});
I would like to send json formatted data from my html page to a url on the click of a button, but currently the data is not getting updated to the url. I've included here a small subset of the data i'm trying to post. The GET method works fine for posting initial output to the url. The result of the ajax request is the alerted error output. How can I use POST to successfully update the output to the url?
The html:
<button type="submit" class="btn-sm btn-success btn-space" id ="commitButton" name="commitButton" value="enter">Commit</button>
Javascript:
<script>
document.getElementById('commitButton').onclick = function() {
$.ajax({
url: "/processjson",
type:'POST',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
"dataType": "json",
"data": {"schema": {"fields":[{"name":"index","type":"integer"},{"name":"OB_TIME","type":"datetime"},{"name":"LATITUDE","type":"number"},{"name":"LONGITUDE","type":"number"}]}, "data": [{"index":0,"OB_TIME":"2015-09-03T00:00:00.000Z","LATITUDE":21.9,"LONGITUDE":-152.0}]},
"contentType": "application/json",
success: function(result) {
alert('ok');
},
error: function(result) {
alert('error');
}
})
};
</script>
Flask:
#app.route('/processjson', methods=['GET','POST'])
#login_required
def processjson():
if request.method == 'GET':
return jsonify({'result':'Test'})
# getting the table data when the commit button is pressed
if request.method == 'POST':
# gets jsonified data and convert it to a python data structure (dictionaries)
data = request.get_json()
fields = data['schema']['fields']
tableData = data['schema']['data']
return jsonify({'result':'Success!','tableData' : tableData})
Place the json data inside the request body.
You can access the request body with request.form.get('data') to get a json string. This can be load to a dict using json.load(json_str).
request.get_json() parse form data as json, but this would work if you are submitting as form data. Looking at the JS snippet, it looks like you are not submitting it as form data (you are making an ajax call), so your data will be available in the property request.json
you can use like this : request.json
I want to send data to another page like using get method in a form when submitting form using php for example when I send data to a page test.php
I want it become like test.php?username=something here....
let headers = {
method: "GET",
data: {
username: "something here"
},
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
};
let data = await fetch('test.php', headers);
I want after I send that data to the test.php the $_GET has 'username' => something here
Note that this code is written inside an async function
I'm using axios to send requets and my current task is to send request for DELETing user. so i made a button and a function that triggers on click.
sendRequest(e) {
const token = document.querySelector("meta[name=csrf-token]").getAttribute('content');
axios.post('/users/2', {
_method: 'DELETE',
authenticity_token: token,
}).then(response => {
console.log(response)
});
}
According to rails docs:
When parsing POSTed data, Rails will take into account the special
_method parameter and act as if the HTTP method was the one specified inside it ("DELETE" in this example).
But after sending the request, i've got an error in console:
ActionController::RoutingError (No route matches [POST] "/users/2"):
UPD 1:
Just tried simple $.ajax request:
const token = document.querySelector("meta[name=csrf-token]").getAttribute('content');
$.ajax({
method: "POST",
url: "/users/2.json",
data: { _method: "delete", authenticity_token: token }
})
.done(function( msg ) {
alert( "Data Saved: " + msg );
})
and it works great. What's the difference than between axios post and ajax post requests so rails woun't parse axios _method field?
I'm building a REST api on top of express.js. I am having trouble updating variables inside my routes.
Example:
I'm calling app.get("/wp/page/create/:id", function(req, res)
Inside this route I start by calling a http request using request-promise library. The response of this call I use in a nested http call.
I use a global variable for the headers for the nested call, and it's to the header a i need to make changes by using the etag variable.
Code:
global.postHeaders = headers;
postHeaders['X-HTTP-Method'] = "MERGE";
postHeaders['Content-Type'] = 'application/json;odata=verbose';
postHeaders['X-RequestDigest'] = spContext;
request.get({
url: "xxx",
headers: headers,
json: true
}).then(function(response) {
var etag = response.d.__metadata.etag
postHeaders['If-Match'] = etag;
request.post({
url: "xxx",
type: "POST",
body: data,
headers: postHeaders,
json: true
}).then(function(data) {
res.send(data).end()
console.log("All done!");
})
})
When i start the server up and enter the route everything works fine. When i when try to hit it again the etag variables is still the same, even though it should be updated.
If I restart the server it works the again on the first attempt but fails on the second/third.
Any idea what I am doing wrong?
I have resolved the issues. The simple solution was to clear the headers containing the variable.
global.postHeaders = headers;
postHeaders['X-HTTP-Method'] = "MERGE";
postHeaders['Content-Type'] = 'application/json;odata=verbose';
postHeaders['X-RequestDigest'] = spContext;
request.get({
url: "xxx",
headers: headers,
json: true
}).then(function(response) {
var etag = response.d.__metadata.etag
postHeaders['If-Match'] = etag;
request.post({
url: "xxx",
type: "POST",
body: data,
headers: postHeaders,
json: true
}).then(function(data) {
postHeaders['If-Match'] = "";
res.send(data).end()
console.log("All done!");
})
})
postHeaders is a global variable. is headers in global.postHeaders = headers; also a global varaible ? Whatever you are trying to do here is grossly wrong. postHeaders variable will be shared across multiple request. so you will hit a scenario where postHeaders['If-Match'] value might be empty string or the etag .
Try this instead of the first line
var postHeaders = Object.assign({}, headers);
Not sure what you are trying, but at-least this statement will subside the huge error in the code. This will create a new header object for each request.