Laravel 5 Route::when() replacement - php

Is there a way to provide in Laravel 5.5 what 4.2 had with:
Route::when('*-ajax', 'ajax');
I had an option to attach a filter to all ajax routes, and since then I know that filters have been replaced with middleware, but I am getting an error that:
Attribute [when] does not exist.

You can use Request::is(). Few details in the doc
It accept multiple params as well.
[edit] You also have Request::ajax() which returns true when you perform an ajax request

I found a solution in having implemented a global middleware for this:
public function handle($request, Closure $next)
{
$parsedUrl = parse_url($request->url());
if (key_exists('path', $parsedUrl) && strpos($parsedUrl['path'], '-ajax') !== false && !$request->ajax()) {
return response('Bad request', 400);
}
return $next($request);
}

Related

Laravel session for Custom Authentication

I am using one laravel 5.7 authentication with custom check and session.
I have 5 type of user types
Session::put('user_type', $user_type);
Session::put('user_id', $user_id);
When I tried to check session data in constructor I am facing one issue,Please hele me to solve this,
ErrorException (E_NOTICE) Trying to get property 'headers' of
non-object
public function __construct()
{
$this->middleware(function ($request, $next) {
$utype=Session::get('user_type');
if($utype != 'ProjectAdmin'){
return redirect()->route('login');
}else{
$this->objShareContract = shareContract::getShareContract(TRUE);
}
});
}
Middleware must return a Response. You are not returning a Response from this custom Closure based middleware. You have 2 logical paths and only one of them is returning a Response of some sort.
There are other middleware before this one that are expecting a Response to come back through the pipeline. That is what the return $next($request); is about.

Laravel Validation - Rule to disallow request parameters

In my Laravel 5.8 app I have many API routes which return paginated results. If I make a request to my API appending the following query string I can disable pagination.
http://api.test/users/?no_paginate=1
My question is... how can I disable no_paginate from being used on certain routes? I'd preferbly want some validation to go in the request class but I can't find anything in the docs for that.
You can do this using a Global Middleware.
Create a DisableNoPaginate Middleware:
php artisan make:middleware DisableNoPaginate
Then define what the middleware should do (DisableNoPaginate.php):
<?php
namespace App\Http\Middleware;
use Closure;
class DisableNoPaginate
{
public function handle($request, Closure $next)
{
//remove no_paginate param from request object
unset($request['no_paginate']);
return $next($request);
}
}
Arrange for the middleware to run on all routes (routes.php):
$app->middleware([
App\Http\Middleware\DisableNoPaginate::class
]);
Now the no_paginate query param should be stripped from all your incoming requests.
For the best approach to get users either paginate or get all listing by below code in UsersController
public function index($type = null, Request $request)
{
$builder = User::where(/*query*/);
if($type == "paginate") {
$items = $builder->paginate(10);
} else {
$items = $builder->get();
}
return view("users.index", ['users' => $items]);
}
Here is the route in web.php/api.php file
Route::get('/{type?}', ['as' => 'users.index', 'uses' => 'UsersController#index']);
Here url will be
http://api.test/users/paginate // get pagination response.
http://api.test/users // get response without pagination
I think this will help you.

Laravel request attribute add not appeard

I create a middleware that will add some few more fields into a request compared to origional like so.
public function handle($request, Closure $next)
{
$profile = Authentication::profile();
$request->attributes->add(['dataUser' => $profile]);
return $next($request);
}
And then in my controller, I dump all the request params with this code.
$request = Request::all();
But when I var_dump($request) the dataUser field is not exists, but strangelly when I call Request::get('dataUser') then it still returns the value.
I know I can use Request::get('dataUser') for solved but I just want to use $request = Request::all(); instead of use multiple static class.
What mistake have I made?
Thanks for the help.
You can add param to request like:
$request->request->add(['variable', 'value']);

Proper Technique to Post to Laravel API

I have a problem posting with Ember to my Laravel API. I keep getting COR's errors and when I try adding the proper headers to my store method the errors are still there. I have researched this for one an hour and no results. Any help would be greatly appreciated. Here is the code for my store() method...
$statusCode = 200;
$libraries = $request->all();
$library = Library::create($libraries);
$criteria = $library->toArray();
return Response::json([
'library' => $criteria],
$statusCode);
Try to do this
http/Middleware/VerifyCsrfToken.php
route start with api is allow here
e.g myapp.com/api/login
public function handle($request, Closure $next)
{
if (!$request->is('api/*'))
{
return parent::handle($request, $next);
}
return $next($request);
}

Laravel 5 null cookie crash

Scenario:
Same browser.
Tab 1: logging into my laravel application.
Tab 2: logging into my laravel application.
Tab 2: log off
Tab 1: Click a button that causes a redirect to a route that's protected by: Route::group(['middleware' => 'auth'], function () {
...
Result: Laravel 5 crashes before it gets to my code on:
Stack:
Symfony\Component\Debug\Exception\FatalErrorException Call to a member function setCookie() on null
vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php:184 __construct
vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:131 fatalExceptionFromError
vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:116 handleShutdown
vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:0 addCookieToResponse
vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php:72 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php:36 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php:40 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php:42 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:101 call_user_func:{/home/vagrant/dev/opus-web-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:101}
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:101 then
vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:115 sendRequestThroughRouter
vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:84 handle
public/index.php:53 {main}
public/index.php:0 [main]
Even when I remove the Route::group(['middleware' => 'auth'] group from my routes... going in tab 1 to the now open URLs will produce this error. I just don't get it.
How do I get rid of this?
I figured out the cause, but I'm just not sure about it. Hoping one of you will know.
In kernel.php:
I had the 'App\Http\Middleware\VerifyCsrfToken' defined in the $middleware black and not the $routeMiddleware. when I moved it to the $routeMiddleware I stopped getting that error.
Content of VerifyCsrfToken:
class VerifyCsrfToken extends BaseVerifier {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($request && (($this->isReading($request) || $this->excludedRoutes($request) || ($this->tokensMatch($request) && Auth::check()))))
{
return $this->addCookieToResponse($request, $next($request));
}
return view('sessionOver');
}
protected function excludedRoutes($request)
{
$routes = [
'deployPush' // webhook push for bitBucket.
];
foreach($routes as $route)
if ($request->is($route))
return true;
return false;
}
}
Seems to me that the problem is your logic in the check of the CSRF.
Here is the problem:
You are checking if the tokens match, and that function is as follow:
protected function tokensMatch($request)
{
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
if (! $token && $header = $request->header('X-XSRF-TOKEN')) {
$token = $this->encrypter->decrypt($header);
}
return Str::equals($request->session()->token(), $token);
}
But if you look closely you will see that in the return it checks for:
$request->session()->token()
But, the session is null so you will get an exception for trying to request a method from a null.
So, if I'm not mistaken, all you need to do is just to add an additional check to the if in the handle method.
Instead of this:
if ($request && ((
$this->isReading($request)
|| $this->excludedRoutes($request)
|| ($this->tokensMatch($request) && Auth::check())
)))
You should have this:
if ($request && ((
$this->isReading($request)
|| $this->excludedRoutes($request)
|| ($request->hasSession() && $this->tokensMatch($request) && Auth::check())
)))
This way, if there is no session it will not even check if tokens match and it will not crash there.
You may also consider refactor that part of the if statement to a function that by name it describes what you are checking for, and even the complete if statement to a function that says it all. Just for code clarity.
Is either that, or you may consider checking your other Middlewares, anyone that be touching the headers of the request and potentially be unsetting the headers.
If you take at the code of the handle function of the StartSession Middleware:
public function handle($request, Closure $next)
{
$this->sessionHandled = true;
if ($this->sessionConfigured())
{
$session = $this->startSession($request);
$request->setSession($session);
}
// ** HERE ALL OTHER MIDDLEWARES ARE BEING CALL
$response = $next($request);
if ($this->sessionConfigured())
{
$this->storeCurrentUrl($request, $session);
$this->collectGarbage($session);
// ** AFTER ALL OTHER MIDDLEWARES ARE CALLED THE FOLLOWING FUNCTION
// TOUCHES THE HEADER AND IS NULL
$this->addCookieToResponse($response, $session);
}
return $response;
}
So, it is possible that somewhere in any of any other middleware you are touching the header and leaving it null, as per your error says.
I hope that helps.
May be this will usefull for you .check in middleware some think similar like this
public function handle($request, Closure $next)
{
$response = $next($request);
if ( ! Auth::user()) // Your logic here...
abort(403, 'Unauthorized action.');
return $response;
}
Ref::https://laracasts.com/discuss/channels/general-discussion/disable-global-verifycsrftoken-and-use-as-middleware-doesnt-work-setcookie-on-null
in that discussion some cookie error discussed.that might help you
Experienced a similar issue specifically when returning a response from a middleware, and I realised it was caused by returning return view('my.view.blade') rather than return response()->view('my.view.blade').
So in short, don't return the view directly. Chain the view() helper to the response() helper.
return view('myview.blade'); //wrong
return response()->view('myview.blade'); //works

Categories