Reputation: 339
On the server side I am receiving a request with a Uri path the client would like to access with a token in the header. My server will look at the hostname
and token
and make sure they are valid. If they aren't, I want to stop the client from accessing the API endpoint.
Here is the function
$app->before(function(Request $request) use ($app) {
$host = $request->getHost();
$token = $request->headers->get('token');
if(!$app['isValidTokenService']($token)) {
$app['monolog']->addInfo(sprintf("%s is a invalid token", $token));
return $app->abort(401,'Unauthorized - bad credentials');
//return new Response('Unauthorized - invalid ****',401);
}
if(!$app['isValidHostService']($host)) {
$app['monolog']->addInfo(sprintf("%s is a invalid host", $host));
return $app->abort(401,'Unauthorized - invalid host');
//return new Response('Unauthorized - invalid ****',401);
}
return 'test';
});
I tried doing a return new Response('Unauthorized - invalid ****',401);
which allowed the user to still access the end point. The $app->abort() seems to be working like a charm but its not responding to the client with anything which I am assuming its not the proper way of handling this situation.
How do I properly handle this situation to deny access to the API endpoint and return a proper error code to my client.
Upvotes: 0
Views: 244
Reputation: 3590
Sorry Joshua, I couldn't reproduce your problem:
$ mkdir silex-test
$ cd silex-test
$ composer require silex/silex phpunit/phpunit
$ mkdir tests
Now create a file inside the tests folder appTest.php:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Silex\Application;
class appTest extends \PHPUnit_Framework_TestCase
{
public function testBeforeFilterPriorToRouteMatching()
{
$app = new Application();
$app->before(function () {
return new Response('before');
});
$app->get('/', function() { return new Response('you should never see me!'); });
$request = Request::create('/');
$this->assertEquals('before', $app->handle($request)->getContent(), "before test didn't canceled the execution!");
}
}
Now just execute the test:
$ vendor/bin/phpunit tests/appTest.php
PHPUnit 4.8.7 by Sebastian Bergmann and contributors.
.
Time: 201 ms, Memory: 6.00Mb
OK (1 test, 1 assertion)
As you can see the controller for the / route was never called, so Silex is working as expected.
This only brings me the question: Which version are you using? (I've tried this with 1.3 and dev-master which is 2.0@dev) This PR (a little dated, though) solved and issue with the before middleware.
In the above code, I've tried to shown that the return new Response('before')
does indeed cancels all other execution. If you take a look at the assertion:
$this->assertEquals('before', $app->handle($request)->getContent(), "before test didn't canceled the execution!");
I compare the result of handling one request to the / URI which should return the string you should never see me!
but it return the string before
because the before
filter returns a response with the string before
and the controller code for the route path / is never called.
If you want to double check, change the controller code to:
$app->get('/', function() {
echo "You'll never see me as this is not called because of the before filter";
return new Response('you should never see me!');
});
And check that running the test (vendor/bin/phpunit tests/appTest.php
) never outputs the string You'll never see me as this is not called because of the before filter because the controller code is never called.
Upvotes: 2