I create Laravel+Vue simple REST API web-app.
In Vue component I have a method with an api request.
I simplified this to see the core of the problem:
phpValidate() {
axios
.post("api/validate", self.programmer)
.then(function(response) {
console.log(response.status);
});
}
In the controller I have a method validateIt(), which handle this "api/validate" request.
It returns:
return array('status' => $status, 'data' => $data);
The $status can be equal to 200 or 422, depends on the input data.
The problem is that from some point, it began to return $status of 200 always.
Even if I delete all the code from the method validateIt() and just leave two lines:
$status = 422;
return array('status' => $status);
I still receive 200.
If I delete the whole method in controller, it gives an Internal Server Error 500.
So, the route and function name is correct.
When I put it back, I can write there whatever I like, it doesn't have any sence - it still returns 200!
If I use debugger, I can see that at the end of validateIt() method it returns 422.
But, when I get the response in phpValidate() I see again 200.
Unbelievable!
I tried:
npm run dev
and
php artisan cache:clear
doesn't help!
Also I tried to restart the server and use different browsers, doesn't help.
Actually, this is not a problem of caching.
It looks like the variable name STATUS is reserved.
Doesn't matter what value you give to $status in the controller method.
The $status always contains the actual status of the request and you can't change it manually. Even if the method is empty it will return $status 200 because the request was sucessfull.
The solution is to use another variable name for your own data.
I had the same problem and to solve it add version where you include your vue frontend file,do it like this it will never cache again:
<script src="{{ asset('js/app.js?version='.date("ymdhis").'') }}"></script>
and you should make sure that your vue server is running use npm run watch or npm run dev
Related
I made the below controller to demonstrate the issue of handling 500 errors I am having with dingo api in laravel. I want to be able to detect when a 500 error will be thrown so it never makes it to the client (as it is too much details to share with the client and they should only be logged by Laravel).
The methodgetUser() returns a 500 error intentionally due to the typo firsgt()
class TestController extends Controller {
public function getUser() {
$data = User::firsgt(); //returns 500 error
return $data;
}
}
This is what the client sees:
In my controllers, I handle errors manually by returning a success/error json response from within the controllers, but if an error occurs that I did not expect, the api returns it and it has too much details for the client to see. Instead, these unexpected errors should bubble up to some sort of handler to return a generic error occurred response. In Laravel, setting APP_DEBUG = false in .env works for laravel (but not for dingo api), this has no effect and the full error is returned to the client. Looking for a safety net for errors that slip through the cracks.
How can we return an error message like 'Error occurred' instead of the too much details for client 'Call to undefined method App\User::firsgt()'?
Note: I don't want to handle it one by one for each controller method, but instead capture any 500 before it is returned to client, and return the custom 500 generic message 'Error occurred'
You should check your dingo config and set these two parameters to false.
APP_DEBUG=false
API_DEBUG=false
If you still encounter the issue, just as suggested in the comment ensure you are in production.
Finally if you are still having the same issues (which by now normally should not exist after setting those fields to false) then you might be interested in checking this issue (date back since 2015).
The fix from one of the comment says (verbatim):
app(\Dingo\Api\Exception\Handler::class)->register(function (\Exception $exception) {
if (!env('API_DEBUG') && !$exception instanceof \Symfony\Component\HttpKernel\Exception\HttpException) {
// Whatever other handling you want goes here..
// Mimic the normal API response with a different message
return \Response::make([
'message' => 'Internal server error',
'status_code' => 500,
], 500);
}
});
Beware that I didnt test this myself.
If you haven't already done yet, publish dingo config file
php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
Then, open config/api.php and edit the errorFormat value to whatever message you want.
Replace :message with a generic message
I am making an ajax post request to the server, posting json data. In firebug I can see the network post call going through along with the json data.
In Laravel I was trying to do a simple var dump of the $_POST data and have just wasted a fair bit of time being confused as to why this should be completely empty. However, when I use the Request facade, my data is there.
ie. this just gives me an empty array:
public function test(){
Log::info($_POST);
}
...yet this prints my data, as I expect:
public function test(Request $request){
Log::info($request->all());
}
Why?
Edit
Thanks, #Webdesigner. The http verb is definitely post, as my method is called in my routes file via
Route::post('/image-upload', 'EntryController#test'); // Note "post" verb
I don't think $request->post() is valid in Laravel 5.4 as this throws an BadMethodCallException: Method post does not exist. error. However, I can confirm that
Log::info($request->method()); // POST
also tells me the method is post.
Very strange. I guess you're right that some part of the app is overwriting the $_POST global, though I have no idea why/where/how. Probably not relevant, but this call is being made from Angular 4.
Thanks for your help anyway!
This is not the normal behavior of Laravel. I tested this on a fresh Laravel 5.5 site and just did a Form submit and an Ajax POST request to the same Route.
Both give me the same result. A POST Request should have at least the CSRF Token as _token with a value.
One other point is $request->all() is not only the the content of $_POST so to have a fair compression you should try $request->post().
BTW only because you did a POST request do not mean that the data is send by the POST Method, it could be that the data you see in $request->all() is from $_GET and $_COOKIE, etc and only the Method was a POST.
Last but not least there it the option that some part of your APP is deleting the content of the Superglobal Variables. $_POST and the others are not like constants, so they can be changed during runtime e.g. $_POST = [];
I don't thing that there is a difference in Laravel 5.4.27.
I can't get even a simple a Laravel post route to return anything. If I switch to get it works fine. Chrome network tab shows the request is a 200 code, but the response is empty even if I dd() something.
Route::post("/login", function(){
dd("test");
});
Also the request is definitely reaching the route correctly, as I can write a file (file_put_contents), but I can't get any return from the post route, whether is a return response()->json(), dd(), var_dump, or just echo.
I am using laravel's RESTful resource routes and controllers.
I testing my api with PostMan and/or RestClient(firefox)
Everything was fine before I added laravel's controller validation. Now it respond with very strange responses like: status code 0, or even executes the code with not valid data. Or even shows strange results taken from the database (which are not included to the controller at all).
That's creepy.
For example:
public function store(Request $request) {
$this->validate($request, [
'room_id' => 'required|integer',
'body' => 'required'
]);
exit; // Stop the process after the validation...
// ... Logic to STORE the MESSAGE in the database ...
return response(null, 204);
}
This store function must only validate the data and respond with an error if validation fails,
But when I execute it from PostMan, It returns response with list of all rooms which belongs to this user. This is creepy, I cannot realize why this is happening.
When I use the jQuery.ajax() method with the same request options, it works fine. It validates the data and stores the message in the database.
Question : Is there a way to deal with postman?
Question : Is PostMan dangerous? Since the server respond with database info (which is not included to the controller responses).
If you take a closer look at laravel's validation document it says that when data is submitted via HTML form,the validate method would redirect you to a previous page and the error would be flashed into the session, if the validation fails. Although, you will be able to access these error messages in your view using the $error variable. Therefore you will need to submit the data via ajax in-order to get the JSON error message.
When validatioin failed, Laravel needs to know you are sending ajax request or you explicitly want json respond, otherwise it redirects you to previous page.
You can check my answer here
https://stackoverflow.com/a/38478362/6246592
G'day,
I'm having issues with PUT requests made via Chrome Postman to a controller, the PUT data is not present, POST data works fine.
I had performed a composer update prior to ensure that the latest version of vendor products where available and even removed bootstrap/compiled.php.
Is anybody else having similar issues?
The update function with both section_id and data being empty in the response:
public function update($id)
{
$section_id = Input::get('section_id');
$data = Input::all();
return Response::json(array('id' => $id, 'section_id' => $section_id, 'data' => $data));
}
I've debugged the code all the way to ParameterBag.php and $this->request's parameter list is empty, I'm not sure what's supposed to contain any values but all through the code the input values are empty. Not sure what to do now, short of using post instead of put.
PUT parameters don't work "out of the box" because PHP itself has some security restrictions around them. See: http://www.php.net/manual/en/features.file-upload.put-method.php
Laravel does implement a common workaround for this, though.
In Postman (or your form, or curl, or whatever client you're using), simply add a URL parameter name: "_method" value: PUT
Example 1:
?_method=PUT
Example 2:
<input type="hidden" name="_method" value="PUT" />
Laravel uses the symfony Http Foundation which checks for the _method variable and if it's present it routes based on its value, instead of the actual HTTP method used.
You have to send a POST request with adding an extra parameter _method with value PUT and it will works fine.