0

In my Apigility project I have different Rest resources, all of them extends my class ResourseAbstract and in there I extend the AbstractResourceListener as Apigility needs.

So for example my resource User:

<?php
namespace Marketplace\V1\Rest\User;

use ZF\ApiProblem\ApiProblem;
use Marketplace\V1\Abstracts\ResourceAbstract;

class UserResource extends ResourceAbstract
{
    public function fetch($id)
    {
        $result = $this->getUserCollection()->findOne(['id'=>$id]);
        return $result;
    }
}

And ResourceAbstract:

<?php

namespace Marketplace\V1\Abstracts;

use ZF\Rest\AbstractResourceListener;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use ZF\ApiProblem\ApiProblem;

class ResourceAbstract extends AbstractResourceListener implements ServiceLocatorAwareInterface {

}

Now, I need to run a function each time an http request is made, if I query /user in my browser the UserResource class will get instantiated and so the ResourceAbstract, my "solution" to get something to run on each call was to use a constructor inside ResourceAbstract, and this "works":

function __construct() {
    $appKey = isset(getallheaders()['X-App-Key']) ? getallheaders()['X-App-Key'] : null;
    $token = isset(getallheaders()['X-Auth-Token']) ? getallheaders()['X-Auth-Token'] : null;
    //some code
    return new ApiProblem(400, 'The request you made was malformed');
}

The thing is I need to return an ApiProblem in some cases (bad headers on the http request), but as you know constructor function does not return parameters. Another solution will be to thrown an exception but in Apigility you are supposed to ise ApiProblem when there is an api problem. Is the constructor approach correct? How will you solve this?

DomingoSL
  • 14,920
  • 24
  • 99
  • 173
  • Out of curiosity, why would you use custom headers instead of using Authentication header with custom auth scheme? – Xerkus Mar 02 '15 at 04:05
  • You seem to solve authentication issues in the constructor of your Resource listener. You should seriously consider separating authentication from your resource listeners. It is better to to check authentication before dispatching your controllers. – Wilt Mar 02 '15 at 08:03

2 Answers2

0

Throwing an exception would be a solution, as long as you catch it on the parent portion of the code.

Are you using the ZEND MVC with your apigility project ?

If yes, you could consider hooking up a call that will be executed before the MVC does the dispatching.

If you want to look on the feasability of that approach, you can check that question asked on stackoverflow : Zend Framework 2 dispatch event doesn't run before action

Community
  • 1
  • 1
alfallouji
  • 1,160
  • 8
  • 12
0

I've not used this library, however it looks as if you can attach a listener to 'all' events by either extending the 'dispatch' method or adding your own event listener with high priority. The controller then listens for the returned 'ApiProblem'.

Attaching a listener is probably a better idea, in your custom class extending AbstractResourceListener (or from within it's service factory) you can then attach the event.

abstract class MyAbstractResource extends AbstractResourceListener
{

    public function attach(EventManagerInterface $eventManager)
    {
        parent::attach($eventManager);

        $eventManager->attach('*', [$this, 'checkHeaders'], 1000);
    }

    public function checkHeaders(EventInterface $event)
    {
        $headers = getallheaders();

        if (! isset($headers['X-App-Key'])) {

            return new ApiProblem(400, 'The request you made was malformed');
        }

        if (! isset($headers['X-Auth-Token'])) {

            return new ApiProblem(400, 'The request you made was malformed');
        }
    }
}

The above would mean that any event triggered would first check if the headers are set, if not a new ApiProblem is returned.

AlexP
  • 9,906
  • 1
  • 24
  • 43
  • I got an error: Declaration of Marketplace\V1\Abstracts\ResourceAbstract::attach() must be compatible with Zend\EventManager\ListenerAggregateInterface::attach(Zend\EventManager\EventManagerInterface $events) in C:\WT-NMP\WWW\MarketPlaceApi\module\Marketplace\src\Marketplace\V1\Abstracts\ResourceAbstract.php – DomingoSL Feb 28 '15 at 19:28
  • You will need to declare the namespaces, eg. `use Zend\EventManager\EventManagerInterface` etc – AlexP Mar 01 '15 at 18:38