Laravel, $.ajax POST does a GET request - javascript

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.

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

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

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()}'

How to pass data from ajax to laravel 5.2 controller via post method

Hello StackOverflow family. This is my very first question and I hope to get help.
I'm new to laravel framework and am using version 5.2 in my project.
Am trying to pass data using the post method from my ajax function to a particular controller method but no data is passed to the controller.
I followed the steps in this forum https://laracasts.com/discuss/channels/laravel/process-data-in-controller-using-ajax-in-laravel but can't get it to work. Here is what I've done so far.
My JavaScript (post_script.js):
$.ajax({
method: 'POST',
url: './home',
data: {
userID: 76,
userName: 'Jimmy'
},
});
Note that this file is saved in assets/js directory in the laravel structure. Here is what I have in my route file (routes.php):
Route::get('/', "MyController#home");
Route::get('home', "MyController#home");
Here is the function I have in MyController.php file:
function home(Request $request) {
$userID = $request['userID'];
$userName = $request['userName'];
return view('home', [
'userID'=> $userID,
'userName' => $userName
]);
}
In my view, I tried to access it like this:
<p>User ID: {{$userID}}</p>
<p>User Name: {{$username}}</p>
Nothing is displayed! Please what am I doing wrong? I need your help. Forgive me if my question is not proper but I hope you get what I mean. Thank you
Your AJAX is POSTing, but you have no POST route set, only GET. Add a POST route, like so:
Route::post('home', "MyController#home");
First check with your developer/network tool (eg. firebug) wether your ajax call reaches the desired controller/functions and that the parameters are forwarded correctly.
A safe way to specify Url in the ajax call in the Laravel environment is using the URL facade like this:
url: "{{ URL::to('home'); }}",
In order to do it like this however you must store your js as a myscript.blade.php (!!) file and #include it into your view accordingly.
For receiving your posted parameters in the controller function there is no need to declare function arguments, you can simply use the Input::Get() function eg. like this:
public function home()
{
$userID = Input::Get('userID');
$userName = Input::Get('userName');
return view('home', [ 'userID'=> $userID, 'userName' => $userName ]);
}
If you try to do POST request you may need to have X-CSRF-Token.
Add this to meta:
<meta name="csrf-token" content="{{ csrf_token() }}">
And setup your AJAX:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
In Laravel docs: https://laravel.com/docs/5.2/routing#csrf-x-csrf-token
First you need set up dataType for ajax request like this (if you using jQuery)
$.ajax({
method: 'POST',
url: './home',
dataType: 'json'
data: {
userID: 76,
userName: 'Jimmy'
},
})
then try use into your controller as follow
Request::json()
and see result
Also you may use Input::get() :
Request::get('userID')
you can use route name to pass your data to the controller
$.ajaxSetup({
headers:{'X-CSRF-TOKEN': $("meta[name='csrf-token']").attr('content')}
});
$.ajax({
type:'POST',
url: '{{route("route_name_with_post_method")}}',
data:{
'id': data
},
success:function(r){
},error:function(r) {
}
});

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'
})
})

Hide basic authentication popup with jquery in Chrome

I use this code for a basic anthentification of REST API. Unfortunately, when the user/pass is wrong Google Chrome displays a popup. Firefox does not do that.
$.ajax({
type: "GET",
url: "/ad",
dataType: 'json',
async: false,
username: 'username',
password: 'password',
success: function (){
alert('success');
return false;
},
error: function(){
alert('error');
return false;
}
});
Edit 1 :
I use Laravel Framework
If you don't have server control, there is no (at least not known to me) way to prevent that. If you DO have server control you can do two things:
Change the response status code from standard 401 to something else. However, this is commonly not known as best practice since the status code does then not state the actual issue (authentication error).
Change the response header WWW-Authenticate: Basic realm="your_realm" to a custom value like WWW-Authenticate: x-Basic realm="your_realm" (Note the x-there!).
That should prevent any default login handling.
Update 1
As for using Laravel this would be an example of setting the correct response header WWW-Authenticate (changed Basic to x-Basic):
Route::filter('auth', function()
{
$credentials = ['email' => Request::getUser(), 'password' => Request::getPassword()];
if (!Auth::once($credentials)) {
$response = ['error' => true, 'message' => 'Unauthorized request'];
$code = 401;
$headers = ['WWW-Authenticate' => 'x-Basic'];
return Response::json($response, $code, $headers);
}
});
I think you can pass the username and password in the URL instead for HTTP authentication.
Give this a shot:
$.ajax({
type: "GET",
url: "http://username:password#whatever.com/ad",
dataType: 'json',
async: false,
success: function (){
alert('success');
return false;
},
error: function(){
alert('error');
return false;
}
});

Categories