moh_abk
moh_abk

Reputation: 2164

Route protection - Laravel

So I have a route with 3 parameters like so

Route::get('search-restaurant/{location}/{day}/{time}', 'WebController@search_restaurant');

For every request to this route, I want to verify these parameters in some way or another.

For the time parameter I've seen documentation of how to attach a regex to it but no documentation in 5.2 but even if I found the docs I need to verify others as well

So basically I have tried two different ways to check and verify the parameters but none are working.

Method 1 - Conroller

public function search_restaurant ($location, $day, $time) {

    if($day != 'today' || $day != 'tomorrow') {
        abort(500);
    } elseif (!in_array($location, $locations)) {
        abort(500);
    } elseif (!preg_match("/(2[0-3]|[01][0-9])([0-5][0-9])/", $time) && $time != "asap") {
        abort(500);
    } elseif ($day == "tomorrow" && $time == "asap") {
        abort(500);
    } else {
    .....//rest of code - send to view
    }
}

Method 2 - Middleware

public function handle($request, Closure $next)
{

    $location = $request->route('location');
    $day = $request->route('day');
    $time = $request->route('time');

    $locations = Array('central','garki-1','garki-2','wuse-2','wuse-1','gwarimpa','maitama','asokoro');

    if($day != 'today' || $day != 'tomorrow') { // check string
        abort(500);
    } elseif (!in_array($location, $locations)) { // check against array
        abort(500);
    } elseif (!preg_match("/(2[0-3]|[01][0-9])([0-5][0-9])/", $time) && $time != "asap") { // check agains regex
        abort(500);
    } elseif ($day == "tomorrow" && $time == "asap") { // check against string
        abort(500);
    }

    return $next($request);
}

As you can see I'm simple doing simple if..else statements on the variables but the conditions seem to always be true. I have tried these rules one by one also but every time they fail and I get sent to 500 page.

Any guidance appreciated

Upvotes: 1

Views: 132

Answers (2)

user3774430
user3774430

Reputation:

First of all, you might want to go back to the basics of conditionals.

If you need to verify 3 parameters, you would need to do 3 if

if ($param1 === $validLocation) {}
if ($param2 === $validDay) {}
if ($param3 === $validTime) {}

The way if...elseif...else conditionals work, is that, once the first condition is fulfilled, the rest of the conditions will not be checked anymore.

// if this condition is true, PHP will not check for further `elseif` or `else
if($day != 'today' || $day != 'tomorrow') {
    abort(500);
} elseif (!in_array($location, $locations)) {
    abort(500);
} else {
    //rest of code - send to view
}

I apologize for getting off-topic, but yes, in 5.2 docs, the regex might have been removed or moved somewhere else, but you can still find those docs in 5.1

Nevertheless, I would recommend you to use constraints in your route instead of checking it in your controller or middleware.

Route::get('test/{location}/{day}/{time}', function ($location, $day, $time) {
    dd($location, $day, $time);
})->where([
    'location' => 'central|garki-1|garki-2|wuse-2|wuse-1|gwarimpa|maitama|asokoro',
    'day' => 'today|tomorrow',
    'time' => 'asap|(2[0-3]|[01][0-9])([0-5][0-9])',
]);

The above route will check for regex on all the parameters before passing it to the Closure or Controller@action (modify as needed)

Here is the link to the 5.1 docs in case you needed it.

Upvotes: 1

Marcin Nabiałek
Marcin Nabiałek

Reputation: 111829

The first problem I've already notice is the following condition:

if($day != 'today' || $day != 'tomorrow') { // check string
    abort(500);
}

It will be always true so you'll always get 500 error page.

Now, if someone use today as $day it will be if (false || true) it it evaluates to true, same if it's tomorrow.

You should change here operator from || to '&&':

if($day != 'today' && $day != 'tomorrow') { // check string
    abort(500);
}

or use in_array here

if(!in_array($day, ['today','tomorrow'])) { // check string
    abort(500);
}

But there's one more thing. You should rather don't do it in your Controller or Middleware. You can user route parameters as in 5.1 (https://laravel.com/docs/5.1/routing#route-parameters) - I haven't tested it but it should work or (this is recommended) you should use for example Form Validation Request to accomplish that.

Upvotes: 0

Related Questions