How to pass value to the url in Django while event occurs? - javascript

I'm trying to send a value to the URL, whenever event occurs it shows:
error that the Forbidden (CSRF token missing or incorrect.): /mapreq
[03/Nov/2017 11:08:27] "POST /mapreq HTTP/1.1" 403 2502
This is the script:
<script>
$(document).ready(function () {
$('path').mouseup(function () {
document.getElementById('state').innerHTML = $(this).attr('aria-label');
var state_lbl = document.getElementById('state').innerHTML = $(this).attr('aria-label');
loadstate(state_lbl);
})
});
function loadstate(state_lal) {
$.ajax({
type: "POST",
url: "mapreq",
data: {'state': state_lal}
});
}
</script>

You need to pass the csrf token. It is important to protect your users data.
With a JavaScriptCookie you can get it like that:
var csrftoken = Cookies.get('csrftoken');
var data = new FormData();
data.append('state',state_lal);
data.append('csrftoken', csrftoken);
function loadstate(state_lal) {
$.ajax({
type: "POST",
url: "mapreq",
data: data,
});
If you do not want to use a third-party just have a look at this documentation. Here is also the third-party mentioned but also the way without it.

In your settings.py file comment or remove the 'django.middleware.csrf.CsrfViewMiddleware' line from middelware classes.
`MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
)`
Then you will not get the error message related to CSRF token.
Otherwise Add CSRF key in parameter list like:
'data: { CSRF: getCSRFTokenValue()}'

Related

PUT type request with a file in AJAX arrives without data

I am making a request in a Laravel form (Blade).
To create the object I use a POST type request but to modify it I use a PUT type request.
I have to use AJAX and I have to send a file in the same request.
I have searched for information and with the POST type, it works correctly, but with the PUT type the request is empty.
I have been researching and testing and I have realized that the problem comes from this line of code within my "processData: false," request.
The problem is that if I don't put this line I get the error "Uncaught (in promise) TypeError: Illegal invocation".
That it was the same error that appeared in the POST request, so searching the internet I solved it like this.
Could someone help me to make the PUT request with the attached file?
My code:
const type_request = 'PUT';
const url_request = '{{ route('put_update_login', ['client' => $client, 'id' => $login->id]) }}';
let data_form = new FormData(document.getElementById(id_form));
$.ajax({
type: type_request,
url: url_request,
data: data_form,
dataType: "json",
processData: false,
contentType: false,
success: function(response) {
if (response.hasOwnProperty("route")) {
window.open(response['route'], "_self").focus();
} else {
$('#alert_error').removeAttr('hidden');
$("#alert_error").fadeTo(20000, 500000);
let errors = response['errors'];
$.each(errors, function (index, value) {
$("#alert_error").last().html(value);
});
$(':button').prop('disabled', false);
$('#spinner_form').prop('hidden', true);
}
}
});
The differences between the POST and PUT version is the "type_request" and the "url_request".
Thanks in advance

Ajax calling 401 unauthorized from backend in html

I have a problem with my AJAX. Using Insomnia, I was able to get in with a successful response of 200 using the API token.
However, when I implement it in the HTML, I get a 401 response of access denied.
$.ajax({
url: "https://ecoexchange.dscloud.me:8080/api/get",
method: "GET",
apikey: sessionStorage.getItem("apikey"),
dataType: 'json',
success: function(result) {
$('#infoTable tr').empty();
var header = $('#infoTable thead');
var body = $('#infoTable tbody');
var hTr;
$('#infoTable thead').append(hTr = $('<tr>'));
// Headers
for (var h = 0; h < result.headers.length; h++) {
hTr.append($('<th>', {
text: result.headers[h]
}))
}
// Body
for (var d in result.data) {
var data = result.data[d];
$('#infoTable tbody').append($('<tr>')
.append($('<td>', {
text: data.RecyclableID
}))
.append($('<td>', {
text: data.Name
}))
.append($('<td>', {
text: data.RecyclableType
}))
)
}
}
})
I am not sure how to put in the token or user name or password.
How can I improve the code so I don't get the error?
What is this apikey parameter you're using? That's not in the documentation.
apikey: sessionStorage.getItem("apikey"),
Did you mean to pass it as a header instead? For example:
headers: {"apikey": sessionStorage.getItem("apikey")},
The documentation for the service you're using should specify how to include the API key. Presumably you have that information, because:
Using Insomnia, I was able to get in with a successful response
So you'll need to include the value in your AJAX request wherever it belongs. Most likely as either a header value or a query string value. But the jQuery .ajax() function isn't going to know how to pass the value, you have to specify.
I think your problem is with passing queries which can be solved here
As it's been said on David's answer , You must know where your apikey is required on the server-side, in header or queries(parameters).
If your apikey is required on queries based on the docs you can use :
$.get('/api/get' , {'apikey' : 'YOUR-KEY'}).done((res) => {
console.log(res)
})
Or if your apikey is required in headers:
$.ajax({
url: '/api/get',
type: 'GET',
headers: {'apikey' : 'YOUR-KEY'},
success : (res) =>{
console.log(res);
}
})
jQuery.ajax() docs can be found here
And jQuery.get() docs here

django ajax call return 403 bad request

I'm trying to compile project https://github.com/kannan4k/django-carpool
please refer this project repo for this issue.
and end up with following error during ajax call.
Failed to load resource: the server responded with a status of 400 (BAD REQUEST).
I know this is because of ajax post request & CSRF tokens.
following is my setting.
1. disable "django.middleware.csrf.CsrfViewMiddleware"
2. in new_trip page I have a button (Postdata)so this button sends an ajax request.
My View:-
#login_required
def save_journey(request):
if request.is_ajax() and request.method == "POST":
try:
res = json.loads(request.body)
cords = res['cords']
cords = [[x['d'], x['e']] for x in cords]
distance = res['distance']
start_place = res['start']
end_place = res['end']
clusters = clusterize_latlngs(cords, distance)
time = datetime.datetime.strptime(res['time'], "%m/%d/%Y %H:%M")
Trip.objects.create(user=request.user, time=time, cluster=json.dumps(clusters), travel_distance=distance,
start_place=start_place, end_place=end_place)
return HttpResponse()
except:
return HttpResponseBadRequest()
else:
return HttpResponseNotAllowed(['POST'])
Ajax call (home.js)
function postData() {
radius = 0;
var url = "/save_journey/";
var dataType = 'json';
if (type == 'r') {
radius = $('#radius').val();
url = "/get_results/";
dataType = 'html';
}
var data = JSON.stringify({
cords: myroute,
time: document.getElementById('dateStart').value,
start: document.getElementById('startPlace').innerHTML,
end: document.getElementById('endPlace').innerHTML,
radius: radius,
distance: distance
});
$.ajax({
type: "POST",
url: url,
dataType: dataType,
data: data,
success: function (data) {
if (type == 'r') {
window.location.href = "/search_results/";
}
else {
window.location.href = '/trip_success/';
}
},
error: function () {
console.log('Error getting options list...')
}
});
console.log(data);
}
this code is not able to call /save_journey/ URL.
I tried many answers from stack overflow & didn't figure out what is the problem .
You should never disable csrftoken unless you're absolutely sure about what you're doing. It's an important part of the security features implemented in Django.
Here is an example of how you can use Ajax with Django with csrftoken:
You can use Ajax Post to send JSON to Django and then handle the arguments as a dict(). Here is an example:
In browser (JQuery/JavaScript):
function newModule() {
var my_data = $("#my_element").val(); // Whatever value you want to be sent.
$.ajax({
url: "{% url 'modules' %}", // Handler as defined in Django URLs.
type: "POST", // Method.
dataType: "json", // Format as JSON (Default).
data: {
path: my_data, // Dictionary key (JSON).
csrfmiddlewaretoken:
'{{ csrf_token }}' // Unique key.
},
success: function (json) {
// On success do this.
},
error: function (xhr, errmsg, err) {
// On failure do this.
}
});
In server engine (Python):
def handle(request):
# Post request containing the key.
if request.method == 'POST' and 'my_data' in request.POST.keys():
# Retrieving the value.
my_data = request.POST['my_data']
# ...
Hope this helps.

Laravel, $.ajax POST does a GET request

I have a problem. My jquery submit function, tries to do a GET request, while I set it up as a POST request.
my submit function
function authenticate() {
var form = $('#form-login');
form.submit(function(evt) {
evt.preventDefault();
console.log('submitting!');
console.log(form.serialize());
$.ajax({
type: 'POST',
url: 'http://website.dev/loginz',
data: form.serialize(),
dataType: 'json',
success: function(data) { log_error(data.error); }
});
});
}
routes.php
Route::post('loginz', 'User\LoginController#authenticate');
What my chrome browser says
GET http://website.dev/loginz/ 405 (Method Not Allowed)
/Loginz
/* POST */
function authenticate(Request $request) {
$username = $request->input('username');
$password = $request->input('password');
if(Auth::attempt(['username' => $username, 'password' => $password])) {
redirect()->route('home'); /* should redirect to player */
}
return response()->json(['error' => trans('errors.user_password_combination').' => '.$username.' & '.$password]);
}
Maybe I am just stupid and hit a wall, I have stared myself to death and I just can't see the error :P
What version of laravel are you using?
Remind csrf token must be given for post requests.
you can disable the csrf verification also in \App\Http\Middleware\VerifyCsrfToken::class,
But would be better if you set in on the client side.
Meaning from laravel you should in the blade template add something like:
$( document ).ready(function() {
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' } });
});
But first, in Chrome (example) inspector -> network -> header: what is the request method?
The fault was an 301 redirect. The problem was created by myself. I added a redirect from non slash to slash (ex. /page to /page/) so the POST was redirected to a GET request.

HttpClient PostAsync equivalent in JQuery with FormURLEncodedContent instead of JSON

I wrote a JQuery script to do a user login POST (tried to do what I have done with C# in the additional information section, see below).
After firing a POST with the JQuery code from my html page, I found the following problems:
1 - I debugged into the server side code, and I know that the POST is received by the server (in ValidateClientAuthentication() function, but not in GrantResourceOwnerCredentials() function).
2 - Also, on the server side, I could not find any sign of the username and password, that should have been posted with postdata. Whereas, with the user-side C# code, when I debugged into the server-side C# code, I could see those values in the context variable. I think, this is the whole source of problems.
3 - The JQuery code calls function getFail().
? - I would like to know, what is this JQuery code doing differently than the C# user side code below, and how do I fix it, so they do the same job?
(My guess: is that JSON.stringify and FormURLEncodedContent do something different)
JQuery/Javascript code:
function logIn() {
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
success: getSuccess,
error: getFail
});
} catch (e) {
alert('Error in logIn');
alert(e);
}
function getSuccess(data, textStatus, jqXHR) {
alert('getSuccess in logIn');
alert(data.Response);
};
function getFail(jqXHR, textStatus, errorThrown) {
alert('getFail in logIn');
alert(jqXHR.status); // prints 0
alert(textStatus); // prints error
alert(errorThrown); // prints empty
};
};
Server-side handling POST (C#):
public override async Task ValidateClientAuthentication(
OAuthValidateClientAuthenticationContext context)
{
// after this line, GrantResourceOwnerCredentials should be called, but it is not.
await Task.FromResult(context.Validated());
}
public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
var manager = context.OwinContext.GetUserManager<ApplicationUserManager>();
var user = await manager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError(
"invalid_grant", "The user name or password is incorrect.");
context.Rejected();
return;
}
// Add claims associated with this user to the ClaimsIdentity object:
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
foreach (var userClaim in user.Claims)
{
identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
}
context.Validated(identity);
}
Additional information: In a C# client-side test application for my C# Owin web server, I have the following code to do the POST (works correctly):
User-side POST (C#):
//...
HttpResponseMessage response;
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>( "grant_type", "password"),
new KeyValuePair<string, string>( "username", userName ),
new KeyValuePair<string, string> ( "password", password )
};
var content = new FormUrlEncodedContent(pairs);
using (var client = new HttpClient())
{
var tokenEndpoint = new Uri(new Uri(_hostUri), "Token"); //_hostUri = http://localhost:8080/Token
response = await client.PostAsync(tokenEndpoint, content);
}
//...
Unfortunately, dataType controls what jQuery expects the returned data to be, not what data is. To set the content type of the request data (data), you use contentType: "json" instead. (More in the documentation.)
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
contentType: "json", // <=== Added
success: getSuccess,
error: getFail
});
If you weren't trying to send JSON, but instead wanted to send the usual URI-encoded form data, you wouldn't use JSON.stringify at all and would just give the object to jQuery's ajax directly; jQuery will then create the URI-encoded form.
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: {
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
},
dataType: "json",
success: getSuccess,
error: getFail
});
// ...
To add to T.J.'s answer just a bit, another reason that sending JSON to the /token endpoint didn't work is simply that it does not support JSON.
Even if you set $.ajax's contentType option to application/json, like you would to send JSON data to MVC or Web API, /token won't accept that payload. It only supports form URLencoded pairs (e.g. username=dave&password=hunter2). $.ajax does that encoding for you automatically if you pass an object to its data option, like your postdata variable if it hadn't been JSON stringified.
Also, you must remember to include the grant_type=password parameter along with your request (as your PostAsync() code does). The /token endpoint will respond with an "invalid grant type" error otherwise, even if the username and password are actually correct.
You should use jquery's $.param to urlencode the data when sending the form data . AngularJs' $http method currently does not do this.
Like
var loginData = {
grant_type: 'password',
username: $scope.loginForm.email,
password: $scope.loginForm.password
};
$auth.submitLogin($.param(loginData))
.then(function (resp) {
alert("Login Success"); // handle success response
})
.catch(function (resp) {
alert("Login Failed"); // handle error response
});
Since angularjs 1.4 this is pretty trivial with the $httpParamSerializerJQLike:
.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
method: 'POST',
url: baseUrl,
data: $httpParamSerializerJQLike({
"user":{
"email":"wahxxx#gmail.com",
"password":"123456"
}
}),
headers:
'Content-Type': 'application/x-www-form-urlencoded'
})
})

Categories