I am learning laravel and I have just created a middleware with a very little session work. but I am getting below error:
FatalThrowableError in VerifyCsrfToken.php line 136: Call to a member
function setCookie() on null
Here is the middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class Adminlogin {
public function handle($request, Closure $next) {
echo 1;
if (!$request->session()->has('userid')) {
return view('admin.auth.login');
}
return $next($request);
}
}
In this scenario response()->view() returns the specified view with the status code 200, but you are able to modify the response in many ways.
From the documentation: If you need control over the response's status and headers but also need to return a view as the response's content, you should use the view method: https://laravel.com/docs/5.3/responses
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
You shouldn't return a view from your middleware. Instead, try redirecting to a route that returns that view.
Like -
return redirect()->route('login');
Related
I've Laravel route with GET & POST as below
Route::get("test1","Api\TestController#test1");
Route::post("test1","Api\TestController#test1");
Now I'm trying to check some condition & if it remain true then I want to call controller else i want to show error without even going into controller.
Like:
Route::get("test1",function(){
$aaa=$_SERVER['REQUEST_URI'];
if(preg_match("/sender_id=TEST/is", $aaa)){
#Call_controller: "Api\TestController#test1"
}else{
echo "some error found"; die();}
});
How to call controller inside function of route.
I don't want to check this in controller because its a API & when i'm getting 10000+ hits per second, calling a function inside laravel load multiple dependences resulting wastage of server resources.
Same has to be done with GET & POST
While you can call the controller using (new Api\TestController())->test1(), the right way to do is:
Create a middleware (say "MyMiddleware") and add your logic in the handle() method:
public function handle($request, Closure $next)
{
$aaa=$_SERVER['REQUEST_URI'];
if (preg_match("/sender_id=TEST/is", $aaa)) {
return $next($request);
}
abort(403);
}
Now use the middleware in the route:
Route::get("test1","Api\TestController#test1")->middleware(MyMiddleware::class);
Since both your route functions are the same, you can use middleware.
Create check middleware php artisan make:middleware check
class check
{
public function handle($request, Closure $next)
{
if(preg_match("/sender_id=TEST/is", $request->getUri())) {
return $next($request);
}
else{
return "some error found";
}
}
}
And in route
Route::group(['middleware' => 'check'], function () {
Route::get("test1","Api\TestController#test1");
Route::post("test1","Api\TestController#test1");
});
I am implementing a Rest API.
It turns out that when using Postman I send a GET request to a route which receives as a parameter account_id = 100
http://127.0.0.1:8000/api/balance?account_id=100
ID 100 exists but postman keeps returning 404 error with return "0".
I am using Laravel 8 and I think my problem is in the Handler. I show you the BalanceController controller and also the Handler class.
BalanceController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Account;
class BalanceController extends Controller
{
public function show(Request $request)
{
$accountId = $request->input('account_Id');
$account = Account::findOrFail($accountId);
return $account->balance;
}
}
Handler.php class register Method
public function register()
{
$this->renderable(function (NotFoundHttpException $e, $request) {
return response()->json('0',404);
});
}
The idea is that when I make this request, I will return the balance of said ID with the response 200, I repeat the ID = 100 exists since I create it by POST request at another time with the logic in another controller.
api routes.php
<?php
use Illuminate\Support\Facades\Route;
Route::post('/reset', [App\Http\Controllers\ResetController::class, 'reset']);
Route::get('/balance', [App\Http\Controllers\BalanceController::class,'show']);
Route::post('/event', [App\Http\Controllers\EventController::class, 'store']);
I would suggest that you implement this in Laravel's way. In your api.php, change your route so that it accepts a parameter like below.
Notice that {account_id} is then replaced with the actual ID number when a program hits this API route.
Route::get('/balance/{account_id}', [App\Http\Controllers\BalanceController::class,'show']);
and then, in your show() function, Add a second parameter like below:
public function show(Request $request, $account_id)
{
$account = Account::findOrFail($account_id);
return $account->balance;
}
I'm trying to change the message from 500 errors if certain conditions are met. I have this middleware in a file called ApiAfter.php:
<?php
namespace App\Http\Middleware;
use App\Helpers\Helper;
use App\Helpers\LogHelper;
use Carbon\Carbon;
use Closure;
use DateTime;
use Exception;
use Illuminate\Http\Response;
class ApiAfter
{
public function handle($request, Closure $next) {
return $next($request);
}
public function terminate($request, $response) {
// move everything in handle function to this
// logging the results of the request
$response = $this->fixFiveHundred($request, $response);
// I do some other stuff here
return $response;
}
private function fixFiveHundred($request, $response) {
if ($response->status() !== 500) return $response;
try {
if (!empty($response->original['message']) && $response->original['message'] === "Server Error") {
if (!empty($response->exception)) {
$newMessage = $response->exception->getMessage();
return response($newMessage, 500); // this is the line of code I'm having trouble with
}
}
} catch(Exception $e) {
return $response;
}
return $response;
}
}
On the line that says return response($newMessage, 500);, I've tried lots of different things but nothing is actually changing the response. Can you not change a response in the Terminate function?
You should avoid handling exception in a custom middleware. Laravel provides a simple class that allows simple customization. Have a look to "render method" of Laravel Error Handling in official docs.
Can you not change a response in the Terminate function?
Short answer: No.
The terminate function in a middleware runs after the response was sent to the browser. Thus, you can't modify the response.
As #Roberto Ferro pointed, the right place to handle custom response for exceptions is using the render in the Exception Handler
I am trying to do a small rest api which based on Lumen. Everything is ok for this sample:
routes/web.php
$router->post('foo/', function () {
return response('[]', 400)
->header('Content-Type', 'application/json');
});
postman receives this response:
400 - bad request. That's ok. But if I try to do the same with a controller php file:
routes/web.php
$router->post('accounts/', 'AccountController#register');
app/Http/Controllers/AccountController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class AccountController extends Controller {
public function __construct() {}
public function register(Request $request): string {
return response()->json(['message' => 'failed'], 400);
}
}
status code is: 200? But why?
Headers came in body response...
Can you advice something to solve this case?
Defining function's return type like string you tell php to make everything (unless strict_types declared) to convert anything to string. I presume somewhere in Response class there's a __toString method which outputs data as you see in your picture. So, just remove return type declaration. Or change it to Response. It is Response class's responsibility to process data and output it as required, not your controller:
public function register(Request $request)
{
return response()->json(['message' => 'failed'], 400);
}
I understand how to redirect users using redirect() method, but this method returns a 302 code and the browser must make a second HTTP request. Is it possible to internally forward the request to a different controller and action?
I'm doing this check in middleware so my handle function looks like this:
public function handle($request, Closure $next)
{
if (auth()->user->age <= 20) { //example
//internally forward the user to a different controller#action
}
return $next($request);
}
}
You can use call method as:
app()->call('App\Http\Controllers\ControllerName#funName')
Or
app('App\Http\Controllers\ControllerName')->funName();
So your middleware will look as:
if (auth()->user->age <= 20) {
return app()->call('App\Http\Controllers\ControllerName#action');
}
You can use redirect() helper method like this:
public function handle($request, Closure $next)
{
if (auth()->user->age <= 20) { //example
return redirect()->route('some_route_name');
}
return $next($request);
}
Inside your routes file, the route should be defined as:
Route::get('users/age/', 'ExampleController#method_name')->name('some_route_name');
Hope this helps!