I'm trying to make a DELETE request within a Laravel app using ajax
I have a function to make the request - using the right verb - to a resource but keeps coming up method not allowed:
Here's my ajax request:
$.ajax({
type: 'DELETE',
url:'/user/58',
data: {
'_method': 'DELETE',
'id': id
},
dataType: 'json',
success: function (data) {
// do something with ajax data
if (data.result) {
return true;
}
return false;
},
error: function (xhr, ajaxOptions, thrownError) {
console.log('error...', xhr);
return false;
//error logging
},
complete: function () {
//afer ajax call is completed
}
});
id is supplied within a function and for the test is 58.
Watching the network panel in Chrome I can see it starts with the expected url of user/58 but then quickly gets shortened to user
I know that to get the resource route to pick up the request it needs to be user/58 and the method DELETE so it will go to the destroy method and because of this it is being routed to the Index method which expects a GET request hence the method not allowed.
Why is my request url being changed?
What is the correct approach to make a DELETE request in Laravel?
Thanks
Edit:
Here's my route:
Route::group( [ 'middleware' => [ 'auth' , 'admin' ] ] , function ()
{
Route::resource( 'user' , 'UserController' );
} );
The csrf token is being taken care of in the headers - fairly certain this isn't the cause of problem as I do not get an invalid token exception
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Thanks
Two possible things that can happen here, I need to write this in a longer post than a comment so hopefully I got it right.
First thing that pops in my mind is an auth check that fails while doing the ajax request. At least I would redirect you back to the main resource if you wouldn't have enough rights.
However, my second guess is maybe even more likely. Have you thought of the X-CSRF-TOKEN that you need to send with an ajax request? See https://laravel.com/docs/5.2/routing#csrf-x-csrf-token
From the docs:
In addition to checking for the CSRF token as a POST parameter, the Laravel VerifyCsrfToken middleware will also check for the X-CSRF-TOKEN request header. You could, for example, store the token in a "meta" tag:
<meta name="csrf-token" content="{{ csrf_token() }}">
Once you have created the meta tag, you can instruct a library like jQuery to add the token to all request headers. This provides simple, convenient CSRF protection for your AJAX based applications:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Related
I am creating APIs into laravel 5.6 for angular.
Form data is sending to API with OPTIONS method.
How can I get this data into the controller?
I have tested like this.
jquery ajax
$.ajax({
url:'domain.com/laravel_app/api/register_user',
type:"options",
dataType:'json',
data:{name:'Joe'},
success:function(r)
{
console.log(r);
}
})
Laravel route
Route::match(['post', 'options'], '/register_user/', 'UserController#register_user');
Laravel controller
public function register_user(Request $request)
{
print_r($request->all());
$arr1['status']='SUCCESS';
return json_encode($arr1);
}
All is working fine with "post" method but not with "options"
This seems to be an issue with jQuery ignoring the spec on the OPTIONS verb and sending your data as the request body.
You should be able to bypass this by doing:
$.ajax({
url:'domain.com/laravel_app/api/register_user?'+$.param({name: 'Joe'}),
type:"options",
dataType:'json',
success:function(r)
{
console.log(r);
}
})
However keep in mind that according to the spec:
The HTTP OPTIONS method is used to describe the communication options for the target resource.
What you are using this request here does not seem to be used to describe communication options for the target resource so you should not be using the OPTIONS method for this.
In my Laravel 5.2 application, I'm trying to post some URLs via ajax in a loop but I get problems with both:
No supported encrypter found. The cipher and / or key length are invalid.
and
TokenMismatchException
Javascript code:
urls.each(function(url) {
var data = {
urls: url.value
};
$.ajax({
type: "POST",
url: "/ajax/checkUrl",
data: data,
headers: {'X-CSRF-TOKEN': '{!! csrf_token() !!}'},
success: function (data) {
var result = $.parseJSON(data);
console.log(result['msg']);
},
error: function (xhr, ajaxOptions, thrownError) {
console.log('Error: ' + thrownError);
}
});
});
routes.php
Route::group(['domain' => env('APP_URI')], function() {
Route::group(['middleware' => ['auth']], function () {
Route::post('ajax/checkUrl', 'AjaxController#checkUrl');
});
});
My AjaxController method is just following each URL with cURL, get some data and passing it back to the view.
Usually, I get the error
production.ERROR: exception 'RuntimeException' with message 'No supported encrypter found. The cipher and / or key length are invalid.' in C:\wamp\www\app\vendor\laravel\framework\src\Illuminate\Encryption\EncryptionServiceProvider.php:45
It works first but after ~50 ajax requests, some of them starts to fail with 500 (Internal Server Error).
I have tried with:
Excluded the ajax URL in VerifyCsrfToken Middleware.
Modified VerifyCsrfToken Middleware as some people at Stackoverflow suggested
Generated a new App key
In my config/app.php I have:
'key' => env('APP_KEY'),
'cipher' => 'AES-256-CBC',
My code works fine standalone outside the Laravel application so I don't know why I get these errors, even if I exclude the URL from CSRF protection?
These errors occurs on localhost. The production server generates 401 Unauthorized after ~100 ajax requests and sometimes logs me out.
Any suggestions why this occurs?
I have a Laravel app that I recently uploaded on the server.
From this Question I found that I should add these to end of htaccess file (after all laravel configurations) in public directory:
<Limit GET POST PUT DELETE>
Allow from all
</Limit>
But server can not recognize requests that sent via PUT or DELETE methods and shows this error :
501
Not Implemented
The requested method is not implemented by the server.
Apache version is 2.2.31 and operating system is linux.
What is problem and does remain something that I should be add?
Update:
This is a part of my routes related to issue:
Route::group(['prefix' => 'post'], function () {
Route::resource('/category', 'CategoryController');
});
In the other hand I used a $.delete user defined function like this to send DELETE requests:
$.delete = function (url, data, callback, type) {
if ($.isFunction(data)) {
type = type || callback,
callback = data,
data = {}
}
return $.ajax({
url: url,
type: 'DELETE',
success: callback,
data: data,
dataType: type
});
}
And I used it to delete a category by it's ID:
$.delete('http://mysite.ir/post/category/20'+ , {}, function (res) {
// console.log(res);
}, 'json');
And destroy method that delete selected category:
public function destroy ($id, Request $request)
{
Category::destroy($id);
return ['success' => true, 'msg' => 'category removed.'];
}
It might be something you also need to change in your apache config file?
I am using laravel 5 POST route in an AJAX call, I have defined it as,
Route::post('user/save-draft', ['as' => 'user/save-draft', 'uses' => 'UserController#saveDraft']);
I am also using Route::resource for the same controller above this save-draft route as,
Route::resource('user', 'UserController', ['except' => 'index']);
I am posting a form using AJAX with loading icon, what I am having strange here is that, data get save in the database, but I receive 404 error in the console like,
jquery.js:9664 POST http://www.example.com/user/save-draft 404 (Not Found)
So strange, and loading icon never get disappear which I do in ajax.done function.
While, my AJAX call is something like that,
var postData = {};
postData['frmSaveDraft'] = $frmSaveDraft.serialize();
startAjaxLoading()
$.ajax({
url: "http://www.example.com/user/save-draft",
type: "POST",
data: postData,
success: function (data) {
alert('success')
stopAjaxLoading();
}
});
UPDATE: Sorry, I missed url in AJAX here in above question,
Any thoughts ?
In controller method, I was returning response as,
echo json_encode(array('response' => true)); exit;
which was causing this issue may be exit keyword.
I have returned the response like,
return Response::json(array('response' => true));
which works great.
How can we check in Laravel 5.2 if a request is a valid ajax request. In codeigniter ,we could check it like $this->input->is_ajax_request(). Does, Laravel 5.2 has something similar?
Also, I would like to know that how can we validate a request for csrf token. Is it fine if I let my webpage render through the 'web' middleware generating a csrf token and then pass this token as ajax request parameter? Would Laravel take care of validating the token or is there an alternate way around this?
I have checked the laravel 5.2 documentation, and since this is the first time I am dealing with laravel framework, it seems like the documentation assumes that the reader already has a familiarity with earlier versions of the framework. To a new comer like me this is little overwhelming.
Thanks in advance. Please let me know if you need more inputs from me.
Prakhar
I think this may help you to undestand a very basic way of using AJAX with Laravel.
It's a really old piece of code, but it works jajajaja
Controller side:
/**
* #param Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function getRamos(Request $request)
{
$check = Ramo::find($request->input('ramo'));
$subramos = Subramo::where('ramo_id', $check->id)->get(['nombre_subramo']);
if($request->ajax()){
return response()->json([
'subramos' => $subramos
]);
}
}
In the front:
<script>
$(document).ready(function(){
$('#ramo').change(function(){
var ramo, token, url, data;
token = $('input[name=_token]').val();
ramo = $('#ramo').val();
url = '{{route('getRamos')}}';
data = {ramo: ramo};
$('#subramos').empty();
$.ajax({
url: url,
headers: {'X-CSRF-TOKEN': token},
data: data,
type: 'POST',
datatype: 'JSON',
success: function (resp) {
$.each(resp.subramos, function (key, value) {
$('#subramos').append('<option>'+ value.nombre_subramo +'</option>');
});
}
});
});
});
</script>
Considering "#ramo" as a select input and in use of the style / html package where the token is passed as a hidden input.
In Laravel 5.2 (I hope any body get help from this code for Ajax)
Get ajax request in function , two examples of function is under:
First Example
public function getLev() {
if (!Request::ajax())
return false;
$result = Input::all();
$lev_id = (int) $result['lev_id'];
$invoiceid = (int) $result['invoiceid'];
return SuppliersController::getLev($invoiceid,$lev_id);//you can do any thing with your variables
//function is working in my case, you case take idea from this function
}
Second Example
public function deleteInvoice() {
if (Request::ajax()) {
$data = Input::all();
return delete_invoice($data['invoice_id'], $data['reason_text']);//you can do any thing with your variables
}
return false;
//function is working in my case, you case take idea from this function
}
Include these files on top of the page/controller where you write above ajax related functions:
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Request;
How can we check in Laravel 5.2 if a request is a valid ajax request. In codeigniter ,we could check it like $this->input->is_ajax_request(). Does, Laravel 5.2 has something similar?
The Request class has an ajax() function, so $request->ajax() or Request::ajax() (depending on how you're getting the request in your controller) will do the trick.
Also, I would like to know that how can we validate a request for csrf token. Is it fine if I let my webpage render through the 'web' middleware generating a csrf token and then pass this token as ajax request parameter? Would Laravel take care of validating the token or is there an alternate way around this?
Yes, pass the token with the AJAX call and make sure your routes have the CSRF middleware (try a request without a token - it should throw an error). Examples are in the docs for this: https://laravel.com/docs/5.2/routing#csrf-x-csrf-token
Anytime you define a HTML form in your application, you should include a hidden CSRF token field in the form so that the CSRF protection middleware will be able to validate the request.
To generate a hidden input field _token containing the CSRF token, you may use the csrf_field helper function:
So to use AJAX request with POST method, you need to pass hidden CSRF token field along with ajax data:
<script>
var token="<?php echo csrf_token(); ?>";
$.ajax({
url:url,
method:'POST',
data:{
'_token':token,
'id':1
}
})
</script>