Vuejs: 400 BAD REQUEST on patch ajax with vue-resoure and Laravel - ajax

I don't know what I'm doing wrong, but my request URL for my Ajax Patch-request through Vue-resource is getting:
400 Bad Request
But this is only on the local environment!!! When I push it up to the server, it works!
Does anyone know why?
Here is my request:
var id = thing.id;
this.$http.patch('/api/things/' + id, thing).then(function(data){
console.log('edited to: '+data);
});
The request parameters should all be correct when looking at the Network tab in dev tools.
Here is my Route:
Route::resource('/api/things','ThingsPanelController');
Here is my Controller:
public function update(Request $request, $id)
{
Thing::findOrFail($id)->update([
'body'=>$request->body,
]);
return Response::json($request->all());
}
Could it be because the ID I added was 'api/things' + id and it sees it not as a wildcard in the route, but as a string! ?
This is my form I use. I prevent default and have the ajax request, so the form action shouldn't even be relevant...
<form action="update" #submit.prevent="doneEdit(thing)">
<input type="hidden" name="_method" value="PATCH">
<input type="text"
v-model="thing.body"
v-thing-focus="thing == editedThing"
#blur="doneEdit(thing)"
#keyup.esc="cancelEdit(thing)"
>
</form>

Check if the problem is persistent on your local server AS WELL AS your live server.
In this case the problem was only on the local server. Then just do this:
Stop artisan's serve, and execute: php artisan cache:clear
Then try again: php artisan serve and the problem should be solved.
The problem might be caused because of a program like CodeKit. Even though your php artisan serve would serve on ip 8000, CodeKit changes this for auto reload reasons. This messes up the ajax call uri's.

Related

Why is record not deleting and response is 303 in Laravel 9, Inertia and Vue3?

I have following code in route web.php file.
Route::resource('dailyrevenue', DailyRevenueController::class)->middleware('auth');
Then in my DailyRevenueController.php
public function destroy(DailyRevenue $revenue)
{
$revenue->delete();
return redirect()->back();
}
And in my vue3 code:
const submit = function (id) {
const check = confirm("Are you sure to delete ?")
if (check) {
Inertia.delete(route('dailyrevenue.destroy',id), {
id: id,
method: 'delete',
forceFormData: true
})
}
}
Finally in the template:
<template #cell(actions)="{item: tax}">
<form method="delete" #submit.prevent="submit(tax.id)">
<input type="hidden" name="_method" value="delete"/>
<button type="submit">Delete</button>
</form>
</template>
Now request reaches to the method. But nothing is deleted. The request sent is DELETE request. Instead of 302 response it sends back 303 (See others).
Community help is appreciated.
Thanks.
I found the solution. The reson behind it was the variable name. In url endpoint the variable name was decleared as dailyrevenue and in the method as $revenue.
You can find your url variable by typing php artisan route:list.
I found that the url variable name must match with variable name in method.
Hope this helps others too.

GET (405) method not allowed [duplicate]

Im trying to do a POST request with jQuery but im getting a error 405 (Method Not Allowed), Im working with Laravel 5
THis is my code:
jQuery
<script type="text/javascript">
$(document).ready(function () {
$('.delete').click(function (e){
e.preventDefault();
var row = $(this).parents('tr');
var id = row.data('id');
var form = $('#formDelete');
var url = form.attr('action').replace(':USER_ID', id);
var data = form.serialize();
$.post(url, data, function (result){
alert(result);
});
});
});
</script>
HTML
{!! Form::open(['route' => ['companiesDelete', ':USER_ID'], 'method' =>'DELETE', 'id' => 'formDelete']) !!}
{!!Form::close() !!}
Controller
public function delete($id, \Request $request){
return $id;
}
The Jquery error is http://localhost/laravel5.1/public/empresas/eliminar/5 405 (Method Not Allowed).
The url value is
http://localhost/laravel5.1/public/empresas/eliminar/5
and the data value is
_method=DELETE&_token=pCETpf1jDT1rY615o62W0UK7hs3UnTNm1t0vmIRZ.
If i change to $.get request it works fine, but i want to do a post request.
Anyone could help me?
Thanks.
EDIT!!
Route
Route::post('empresas/eliminar/{id}', ['as' => 'companiesDelete', 'uses' => 'CompaniesController#delete']);
The methodNotAllowed exception indicates that a route doesn't exist for the HTTP method you are requesting.
Your form is set up to make a DELETE request, so your route needs to use Route::delete() to receive this.
Route::delete('empresas/eliminar/{id}', [
'as' => 'companiesDelete',
'uses' => 'CompaniesController#delete'
]);
Your routes.php file needs to be setup correctly.
What I am assuming your current setup is like:
Route::post('/empresas/eliminar/{id}','CompanyController#companiesDelete');
or something. Define a route for the delete method instead.
Route::delete('/empresas/eliminar/{id}','CompanyController#companiesDelete');
Now if you are using a Route resource, the default route name to be used for the 'DELETE' method is .destroy. Define your delete logic in that function instead.
In my case the route in my router was:
Route::post('/new-order', 'Api\OrderController#initiateOrder')->name('newOrder');
and from the client app I was posting the request to:
https://my-domain/api/new-order/
So, because of the trailing slash I got a 405. Hope it helps someone
If you didn't have such an error during development and it props up only in production try
php artisan route:list to see if the route exists.
If it doesn't try
php artisan route:clear to clear your cache.
That worked for me.
This might help someone so I'll put my inputs here as well.
I've encountered the same (or similar) problem. Apparently, the problem was the POST request was blocked by Modsec by the following rules: 350147, 340147, 340148, 350148
After blocking the request, I was redirected to the same endpoint but as a GET request of course and thus the 405.
I whitelisted those rules and voila, the 405 error was gone.
Hope this helps someone.
If you're using the resource routes, then in the HTML body of the form, you can use method_field helper like this:
<form>
{{ csrf_field() }}
{{ method_field('PUT') }}
<!-- ... -->
</form>
It will create hidden form input with method type, that is correctly interpereted by Laravel 5.5+.
Since Laravel 5.6 you can use following Blade directives in the templates:
<form>
#method('put')
#csrf
<!-- ... -->
</form>
Hope this might help someone in the future.
When use method delete in form then must have to set route delete
Route::delete("empresas/eliminar/{id}", "CompaniesController#delete");
I solved that issue by running php artisan route:cache which cleared the cache and it's start working.
For Laravel 7 +, just in case you run into this, you should check if the route exists using
php artisan route:list
if it exists then you need to cache your routes
php artisan route:cache

Mixed Content on Vue-select Component

this is a bit of a weird one.
On my local development environment, this works perfectly, but once I go on a staging or live server - things don't go as smooth.
I am using the https://vue-select.org/ component for Vue.js to pull through options based on user input. When the select textarea is changed, I debounce the method and fire the string off to an API and pull back any results that are relative to the user's input. This then gets populated into an 'options' array which the select dynamically updates and uses.
The API link is specified using a variable from my .env file. On my local environment using Laravel Valet, this works fine.
When the site gets switched over to a live server, things get interesting. When I try and input a value into the select field, I get this result:
Mixed Content: The page at 'https://example.com/cv/1fa2383/edit' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example.com/api/job_title_names'. This request has been blocked; the content must be served over HTTPS.
Now, you would assume that this was because the request is being loaded over HTTP, not HTTPS. This is the weird part. Nowhere hardcoded, or defined as a variable is there HTTP requests, only HTTPS. I've quadruple tested this and re-written and even hard-coded HTTPS links but for some reason, the component keeps trying to load the request over HTTP.
It's really odd because it tries to fire two requests. One is a GET and the other is a POST. The POST is what my Axios script should be doing, but the GET request gets added for some unknown reason. There is no code built for a get request on this component as you will see below.
I'm at my witts end with this. Here's some information regarding my components and element references:
My env variables: (.test is my dev tld).
test is my dev tld
/api/ is what most of my axios requests go through.
APP_URL=http://example.test
APP_API_URL=http://example.test/api/
My input:
<label>
<span class="block font-bold mb-2 text-grey-500 text-sm">Job Title <i class="fad fa-question-circle leading-none text-blue-400" v-tooltip.top-center="'What was your role in this company?'"></i></span>
<v-select taggable :options="jobTitleOptions" #search="fetchJobTitleOptions" v-model="newEmployment.jobTitle" :filterable="false" class="dynamic-select" placeholder="Type a Job Title">
<template slot="no-options">
Type to find your job title...
</template>
</v-select>
</label>
My methods:
fetchJobTitleOptions (search, loading) {
loading(true);
this.searchJobTitles(loading, search, this);
},
searchJobTitles: _.debounce((loading, search, vm) => {
console.log('Job Title Url: ' + vm.jobTitleOptionsUrl);
if(search != '') {
axios.post(vm.jobTitleOptionsUrl, {
name: escape(search)
})
.then(response => {
let data = response.data;
vm.jobTitleOptions = data;
loading(false);
});
} else {
loading(false);
}
}, 500),
Computed:
jobTitleOptionsUrl: function() {
return this.url + 'job_title_names/'
},
My component reference:
apiurl is the value of APP_API_URL assigned to a different vue variable.
<edit-employment :apiurl="apiurl" :cvid="this.cv_id"></edit-employment>
Blade template:
#extends('layouts/app')
#section('content')
<edit-cv url="{{ env('APP_URL') }}" api="{{ env('APP_API_URL') }}" cvid="{{ $cv_id }}" urlslug="{{ $url_slug }}"></edit-cv>
#endsection
Using Vue tools, I can see that all the links are being referenced correctly, not one has HTTP prefixed before them.
I am running Nginx on my local environment, but Apache is running on my server. I'm not sure if that could help with some diagnosis?
Steps I've taken to try and solve this:
I have flushed all cache from the Laravel side of things successfully
I have returned the variables in Laravel and can confirm they return correctly.
I have re-written most variables to ensure that they're 100% correct
I have checked package versions to see if there are conflicts, of which there are not.
Any help would be greatly appreciated.
Thank you
I fixed this by double-checking my routes. When working with APIs and specifically Axios in Laravel, if you have a trailing / at the end of the route, this causes the request to 301. After removing the trailing slash, everything worked as it should.
So this route:
return this.url + 'job_title_names/'
Becomes this:
return this.url + 'job_title_names'

my delete query is not working in laravel

I am trying delete database data in Laravel. but this is not working my way.
my view page is
{{url('/deleteReview/'.$Review->id)}}
my web is
Route::post('/deleteReview/{id}','adminController#deleteReview');
my controller delete function is
public function deleteReview($id){
$deleteReview = Review::find($id);
$deleteReview->delete();
return redirect('/manageReview');
}
Are you trying to delete the review by opening the page /deleteReview/<id> in your browser? If so, this would be a GET request, so change the route to a get route:
Route::get('/deleteReview/{id}','adminController#deleteReview');
Please note as per the comments that a GET request should never change data server side. If data is changed using a GET request then there is a risk that spiders or browser prefetch will delete the data.
The correct way to do this in Laravel is using a POST request and use Form Method Spoofing to simulate a DELETE request. Your route entry would then look like this:
Route::delete('/deleteReview/{id}','adminController#deleteReview');
And your form would look like this:
<form action="/deleteReview/{{ $Review->id }}" method="POST">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
At Controller you should first set Validation for ID that you have to Delete. Create your own customize request handler such as DeleteRequest.
Once you get ID at Controller then used this code
public function deleteReview(DeleteRequest $id){
DB::table('reviews')->where('id', $id)->delete();
return redirect('/manageReview');
}
I hope it will work.

Laravel 419 on post requests after upgrade from 5.4

Did an upgrade from 5.4 to 5.7, after that every ajax post request is 419 with:
{message: "", exception: "Symfony\Component\HttpKernel\Exception\HttpException",…}
exception: "Symfony\Component\HttpKernel\Exception\HttpException"
file: "pathto/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php"
line: 204
message: ""
trace: [{,…}, {file: "pathto/public_html/app/Exceptions/Handler.php", line: 47, function: "render",…},…]
0: {,…}
class: "Illuminate\Foundation\Exceptions\Handler"
file: "pathto/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php"
function: "prepareException"
line: 176
type: "->"
Followed the upgrade instructions which especially mentioned about Cookie Serialization:
protected static $serialize = true;
Cleared cache, checked the file permissions are ok. Went down to 5.6, then to 5.5 laravel versions but no help. Changed the cookie name, tried incognito. Tried to even bypass all:
protected $except = [
"*"
];
But no change. What on earth could go wrong here?
Edit:
Ajax call:
var $_token = $('#token').val();
var url = '/delete';
$.ajax({
headers: {'X-XSRF-TOKEN': $_token},
type: "POST",
url: url,
data: ({data: data}), // set up earlier
success: function (data) {
}
});
Controller:
public function delete(Request $request)
{
$id = $request->input('data);
Post::where('id', $id)->delete();
}
Also tried with $('meta[name="csrf-token"]').attr('content')
This gave me:
payload is invalid
id token is taken from:
<?php
$encrypter = app('Illuminate\Encryption\Encrypter');
$encrypted_token = $encrypter->encrypt(csrf_token());
?>
<input id="token" type="hidden" value="{{$encrypted_token}}">
just add
{{ csrf_field() }}
to your blade template
something like
<form method="POST" action="/projects">
{{ csrf_field() }}
<div class="form-group">
<label for="title">Title</label>
<input id="title" class="form-control" type="text" name="title" placeholder="Project Title" required />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">
Create Project
</button>
</div>
</form>
Hard to tell without your controller and the actual ajax call... but I've had similar problems with this 419 error. There were two causes for me:
1) Failed token verification. To check, add this to your ajax call:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Though... your having tried to except everything should have allowed this through (assuming you had that line in the right place).
EDIT: If you are passing your X-XSRF-TOKEN from JavaScript, decode it using decodeURIComponent()
2) It's possible that your controller is trying to render the view without all the information it needs. Any chance you need to send a variable through to the view in the ajax controller function and it is missing? I realize this worked before, but there were some big changes to 5.5 (including the way CSRF was handled as above).
3) Just a general error that I've had, but it might be possible that the data is not transferring in the same way as it did with 5.4. Just check to see if the way the data is coming in to the controller is not error-ing out. IE do a dump from the controller before it gets back to the view and see what your browser reports is transferring
Old topic but I just got back to it now and figured it out.
Reason was that I was passing: XSRF-Token in older Laravel instead of CSRF-Token, the never versions don't seem to work with XSRF anymore. Switched to CSRF and that fixed it.

Resources