Today I needed to protect a group of routes from everything except my testing environment. I need to run PHPUnit tests that depend on certain routes, but I don’t want those routes to be available anywhere else. I’ll share in this blog post what I did to get what I need.
Assumptions in this tutorial:
You already have Laravel 5 installed on your computer and you are running the app in “testing” mode (e.g. PHPUnit testing)
Introduction
In Laravel, Middleware filters requests that are coming into our application. One of the pre-made Middleware in Laravel 5.2 is Authenticate
, which looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class Authenticate { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null $guard * @return mixed */ public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->guest()) { if ($request->ajax() || $request->wantsJson()) { return response('Unauthorized.', 401); } else { return redirect()->guest('login'); } } return $next($request); } } |
Inside the handle() method, it checks if the request is using AJAX -or- is asking for JSON, and if either condition returns TRUE, it blocks access and returns ‘Unauthorized’ as response. Otherwise, client is redirected to the ‘login’ route, which should happen when client is requesting via web browser.
What I did to make my grouped routes available only in testing environment (in my case, when running PHPUnit) was create a new Middlewave. I’ll show you how. 🙂
Create a new file under Http/Middleware
and name it TestingEnvOnly.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php namespace App\Http\Middleware; use \App\Http\Controllers\API\ApiLogsController; use Closure; use \Log; /** * Check if phpunit is the one running the app */ class TestingEnvOnly { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if(env('APP_ENV') == "testing"){ return $next($request); } else { return response('Unavailable.', 401); } } } |
In the handle method, we check if app environment is set to testing, and if so, we allow the request to access the requested route. Otherwise, the request should fail and repond with ‘Unavailable’.
Now, let’s register this Middleware to Http/Middleware
. Add the following to the $routeMiddleware
array:
1 |
'testing' => \App\Http\Middleware\TestingEnvOnly::class |
It’s time to add a testing-only route:
1 2 3 4 5 6 7 |
<?php Route::group(['middleware' => ['testing']], function(){ Route::get("testing_env_only", function(){ echo "This should be visible only for testing environment"; }); }); |
If you use PHPUnit like I do, you can test our new Middleware by creating this test method:
1 2 3 4 5 |
<?php public function testNewMiddleware(){ $content = $this->call("GET", "/api/v1/testing_env_only")->getContent(); var_dump($content); } |
I’m only using var_dump so that we can easily see the printed string response which should say “This should be visible only for testing environment” when you run PHPUnit.
Now, in your web browser, visit the route your set for /api/v1/testing_env_only
. It should say ‘Unauthorized’.
Here’s how the files I edited in Laravel look like now:
I’m using Laravel 5.2 and these are codes I uploaded at Gist