Zend Framework 2 Restful web service: common functionality across controllers - php

Im making a restful web service with Zend FW 2. How can I create a system, that checks ie. API key everytime REST is called? Checking the key in every controller in every function of course is not the way to go, so Im looking for something "global".
Thanks!

Assuming all your rest methods are in one controller you can listen to that controllers dispatch event, using a high priority so checks are done early...
Register the listener in your modules bootstrap, for example assuming you added an ApiController to the Application module
public function onBootstrap(EventInterface $e)
{
$app = $e->getApplication();
// get the shared events manager
$sem = $app->getEventManager()->getSharedManager();
// listen to dispatch event when triggered by the ApiController
$sem->attach('Application\Controller\ApiController', 'dispatch', function($e) {
// do your api key checks
// if checks fail get the response from the controller
$controller = $e->getTarget();
$response = $controller->getResponse();
$response->setStatusCode(401);
// return $response, short circuiting dispatch event
return $response;
}, 9000); // 9000 = high priority, do this early
}
Point of note, the event passed to your closure contains as its target an instance of your controller, so if you need to get services from the ServiceManager to do your api checks you can do so just like you would in the controller itself, ie...
$controller = $e->getTarget();
$sm = $controller->getServiceLocator();

Related

Cake PHP3 validate rest API header parameters

I'm developing REST API with cake PHP3 for the mobile application.
Every request header has custom parameter call X-App-Key for the verify mobile app. (Unique ID for the app - X-App-Key : '123456789')
I need to check that parameter value before give access to API endpoints.
How do it check from bootstrap.php or any other place. (in controllers).
Can this use cakephp Dispatcher Filters for validate and filter requests ?
Yes Dispatch Filters would be a good option here. If your application is going to serve browser requests as well, controller would be better. For Dispatch Filters, you can do it like :
1) config\bootstrap.php
DispatcherFactory::add('ApiHeader');
2) src\Routing\Filter\ApiHeaderFilter.php
namespace App\Routing\Filter;
use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
class ApiHeaderFilter extends DispatcherFilter
{
public function beforeDispatch(Event $event)
{
$request = $event->data['request'];
$xAppKey = $request->header('X-App-Key');
if ($xAppKey != '123456789') {
// throw exception or message
exit;
}
}
}
You can also use TableRegistery for database query :
use Cake\ORM\TableRegistry;
...
$tableModel = TableRegistry::get('table_name');
$xAppKeys = $tableModel->find('all', ...
Reference Links :
Request Headers &
Dispatch Filters

Symfony2. Force a service to get instanced

I'm working with symfony 2.8, I'm facing a situation where a service must be instanced even if it is not requested somewhere.
Why ? Because this Core service configure tagged services that are transfered by method calling into Core ( I did this in a compiler pass ).
And then, if I request one of these tagged services without request Core, it will not be configured and then be unusable.
Here is the compiler pass :
$coreDefinition = $container->findDefinition(
'app.improvements.core'
);
$taggedAppliers = $container->findTaggedServiceIds('app.improvement.applier');
foreach ($taggedAppliers as $id => $tags) {
$coreDefinition->addMethodCall(
'registerApplier',
[new Reference($id)]
);
}
$taggedImprovements = $container->findTaggedServiceIds(
'app.improvement'
);
// Only method found to initialize improvements.
foreach ($taggedImprovements as $id => $tags) {
$coreDefinition->addMethodCall(
'registerImprovement',
[new Reference($id)]
);
}
To sum up, the Appliers registers Improvement and Core registers Appliers. The core associate improvements with appliers because each improvement must be registered in a specific applier that the core stores.
The problem I that when I only request a Applier, its improvements are not registered into it because the core isn't instancied.
Thank you.
Design problems aside, the easiest way to instantiate a service is to use an event listener. In your case you would listen for the kernel.request and pull your service from the container.
class RequestListener
{
public function onKernelRequest(GetResponseEvent $event)
{
$event->getKernel()->getContainer()->get('service_id');
}
}

How to avoid outside of request scope exception in silex application?

After restructuring my silex1.2 application, I am now getting hit by:
exception 'RuntimeException' with message 'Accessed request service
outside of request scope. Try moving that call to a before handler or
controller.' in
../vendor/silex/silex/src/Silex/Application.php:150
I used to setup the appilcation's config this way:
$app = new Silex\Application();
$app->register(new ServiceControllerServiceProvider());
$app->register(new ConfigServiceProvider($configFile));
$fileFinder = new \Symfony\Component\Finder\Finder();
foreach ($fileFinder->in($configPath . 'country') as $file) {
/* #var SplFileInfo $file */
$app->register(new ConfigServiceProvider($file->getRealPath()));
}
I now wanted to replace the foreach loop by injecting a specific value which I get from the user's request. So I wanted to access $request->query->get('country'); yet I cannot since app['request'] is out of scope at that point.
I don't understand the error message, as in:
When and why are request objects out of scope in silex?
How am I supposed to move the call before handler and controllers when it is the very first thing I do on setting up my application?
Basically, I want to access request data early on on in order to get one value. How can I achieve that in order to bootstrap application accordingly?
You try to use Request before it is initialized, before $app->run().
You can manually initialize Request:
$app = new \Silex\Application();
$app['request'] = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
.....
$app->run($app['request']);
or make lazy loading in service providers:
$app['object1'] = $app->share(function ($app) {
return new Object1($app['request']->query->get('country'));
});
...
and somewhere in controller get these variable as $app['object1']

return from onBootStrap() in zend

I am calling one function from onBootStrap() to authorize user, in that function I am using header information to verify the user.
If this is not correct, I want to stop execution here(onBootStrap()) without even calling the actual API and return some response to the user .
User should get some response because then only user can know what's the problem.
How I can return response from there?
Simply said, onBootstrap is not sufficient for this. Usually, you have two stages in your application. The first is bootstrapping, the second is running. During run you can authorize users and return responses, during bootstrap this is not possible.
The reason is simple, you might have another module overriding it's behaviour. If you stop bootstrapping after your module, you can stop the execution of these modules. It's better to move the logic to run. This run stage is defined with various listeners, of which the first is route. There isn't much going on after bootstrap and before route, so in terms of performance it's neglectable.
A code example:
use Zend\Mvc\MvcEvent;
use Zend\Json\Json;
class Module
{
public function onBootstrap($e)
{
$app = $e->getApplication();
$em = $app->getEventManager();
$em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($app) {
// your auth logic here
if (!$auth) {
$response = $e->getResponse();
$response->setStatusCode(403);
$response->setContent(Json::encode(array(
'error' => 12345,
'message' => 'You are not authorized for this request',
));
return $response;
}
}, PHP_INT_MAX);
}
}
The listener is attached at an very early stage (PHP_INT_MAX) so the check happens as first in the complete route stage. You can also choose for quite a high number (like, 1000) so you can hook in this event before user authorization.

PHP: Am I mixing up event-driven programming with signals-aware interfaces (Signal and Slots / Observer Pattern)?

I've seen a lot of people saying that Symfony2, Zend Framework 2 and others are event-driven.
On the desktop world, by event-driven programming I understand that the application will notify its observers whenever its state changes.
Since PHP applications are state-less there's no way to do such thing. I.E. Having observers tied to the view observing changes while the user uses the interface. Instead it needs a new request process in order to update the view. So, it's not an event but a whole new request.
On the other hand there's a similar concept: Event-driven architecture.
Here you can read both:
http://en.wikipedia.org/wiki/Event-driven_programming
http://en.wikipedia.org/wiki/Event-driven_architecture
And here the other one:
http://en.wikipedia.org/wiki/Signal_programming
A signal is a notification to a process that an event occurred.
Signals are sometimes described as software interrupts. Signals are
analogous to hardware interrupts in that they interrupt the normal
flow of execution of a program; in most cases, it is not possible to
predict exactly when a signal will arrive.
Stackoverflow [singals] tag description
Moreover, what I used to call event-driven seems to be more related to the Signals and Slots Pattern introduced by Qt (observer pattern implementation)
As an example, there's the Prado Framework which claims to be event-driven:
http://www.pradosoft.com/demos/quickstart/?page=Fundamentals.Applications (Application Lifecycles section)
http://www.pradosoft.com/docs/manual/System/TApplication.html#methodonEndRequest
IIRC, this isn't an event-driven application, but instead just plug-in hooks (signals and slots) used by classes that implements the observable Interface. I mean, considering the way desktop applications use events and the way state-less applications use events (as plugi-ns): The first use events for the whole application, including views, the last just for server-side operations.
One is more related to Aspect-oriented programming (with signals and slots) and the other is not specifically tied to cross-cutting concerns/AOP. In other words, it's more related to the application state.
So, what is in fact the relation between these terms and how they differ from each other?
Event-driven programming
Event-driven architecture
Signals and Slots Pattern
Are these terms just generic patterns? Hence, everything that implements the observer pattern can be considered event-driven?
UPDATE
Zend Framework 2
The article about AOP I've linked above
( http://mwop.net/blog/251-Aspects,-Filters,-and-Signals,-Oh,-My!.html )
was written by Matthew Weier O'Phinney (ZF Leader). IIRC, it doesn't
have mentions about "event-driven", just signal and slots.
Symfony 2
The Symfony2 EventDispatcher component description doesn't have mentions about
being for "event-driven" applications:
http://symfony.com/doc/current/components/event_dispatcher/introduction.html
It only contains references to "Events" (which, indeed, are handled by Signal and Slots).
Both frameworks seem to use the Intercepting Filter Pattern within the Signal and Slots in order to handle synchronous events during the request process.
Disclaimer: It's a long answer, but I think it's worth the read with
all its references. And IMHO it leads to a conclusive answer.
I've been struggling upon this subjects the last couple of days and, if I've read all correctly, the answer is:
Event-driven !== Request-driven
"[...] I find this the most interesting difference in event
collaboration, to paraphrase Jon Udell: request driven software speaks
when spoken to, event driven software speaks when it has something to say.
A consequence of this is that the responsibility of managing state
shifts. In request collaboration you strive to ensure that every piece
of data has one home, and you look it up from that home if you want
it. This home is responsible for the structure of data, how long it's
stored, how to access it. In the event collaboration scenario the
source of new data is welcome to forget the data the second it's
passed to its Message Endpoint."
Martin Fowler - Event Collaboration (Queries section)
Based on that assertion, IIRC, modern PHP frameworks implements the Observer Pattern + Intercepting Filters + Singal and Slots, in order to trigger some events during the request cycle.
But, despite the fact that it adopts some ideas of event-driven architectures, it doesn't seems to support that the whole framework is event-driven (i.e. Symfony2 is an event-driven framewrok).
We are used to dividing programs into multiple components that
collaborate together. (I'm using the vague 'component' word here
deliberately since in this context I mean many things: including
objects within a program and multiple processes communicating across a
network.) The most common way of making them collaborate is a
request/response style. If a customer object wants some data from a
salesman object, it invokes a method on the salesman object to ask it
for that data.
Another style of collaboration is Event Collaboration. In this style
you never have one component asking another to do anything, instead
each component signals an event when anything changes. Other
components listen to that event and react however they wish to. The
well-known observer pattern is an example of Event Collaboration.
Martin Fowler - Focus on events (section: Using events to
collaborate)
I think that PHP applications are more closely to be event-driven than request-driven only when the focus are on events. If those applications/frameworks are only using events for cross-cutting concerns (AOP), then it's not event-driven. In the same way you would not call it test-driven or domain-driven just because you have some domain objects and unit tests.
Real world examples
I've picked some examples to show why those frameworks are not fully event-driven. Despite AOP events, everything is request-driven:
Note: Although, it can be adapted to be event-driven
Zend Framework 2
Let's examine the \Zend\Mvc\Application component:
It implements the \Zend\EventManager\EventManagerAwareInterface and relies on the \Zend\Mvc\MvcEvent which describes the possible events:
class MvcEvent extends Event
{
/**##+
* Mvc events triggered by eventmanager
*/
const EVENT_BOOTSTRAP = 'bootstrap';
const EVENT_DISPATCH = 'dispatch';
const EVENT_DISPATCH_ERROR = 'dispatch.error';
const EVENT_FINISH = 'finish';
const EVENT_RENDER = 'render';
const EVENT_ROUTE = 'route';
// [...]
}
The \Zend\Mvc\Application component itself is event-driven because it doesn't communicates directly with the other components, but instead, it just triggers events:
/**
* Run the application
*
* #triggers route(MvcEvent)
* Routes the request, and sets the RouteMatch object in the event.
* #triggers dispatch(MvcEvent)
* Dispatches a request, using the discovered RouteMatch and
* provided request.
* #triggers dispatch.error(MvcEvent)
* On errors (controller not found, action not supported, etc.),
* populates the event with information about the error type,
* discovered controller, and controller class (if known).
* Typically, a handler should return a populated Response object
* that can be returned immediately.
* #return ResponseInterface
*/
public function run()
{
$events = $this->getEventManager();
$event = $this->getMvcEvent();
// Define callback used to determine whether or not to short-circuit
$shortCircuit = function ($r) use ($event) {
if ($r instanceof ResponseInterface) {
return true;
}
if ($event->getError()) {
return true;
}
return false;
};
// Trigger route event
$result = $events->trigger(MvcEvent::EVENT_ROUTE, $event, $shortCircuit);
if ($result->stopped()) {
$response = $result->last();
if ($response instanceof ResponseInterface) {
$event->setTarget($this);
$events->trigger(MvcEvent::EVENT_FINISH, $event);
return $response;
}
if ($event->getError()) {
return $this->completeRequest($event);
}
return $event->getResponse();
}
if ($event->getError()) {
return $this->completeRequest($event);
}
// Trigger dispatch event
$result = $events->trigger(MvcEvent::EVENT_DISPATCH, $event, $shortCircuit);
// Complete response
$response = $result->last();
if ($response instanceof ResponseInterface) {
$event->setTarget($this);
$events->trigger(MvcEvent::EVENT_FINISH, $event);
return $response;
}
$response = $this->getResponse();
$event->setResponse($response);
return $this->completeRequest($event);
}
That's event-driven: You have no clue looking at the code of which router, dispatcher and view renderer will be used, you only know that those events will be triggered. You could hook almost any compatible component to listen and process the events. There's no direct communication between components.
But, there's one important thing to note: This is the presentation layer (Controller + View). The domain layer indeed can be event-driven, but that's not the case of almost all applications you see out there. **There's a mix between event-driven and request-driven:
// albums controller
public function indexAction()
{
return new ViewModel(array(
'albums' => $this->albumsService->getAlbumsFromArtist('Joy Division'),
));
}
The controller component is not event-driven. It communicates directly with the service component. Instead the services should subscribe to events risen by controllers, which is part of the presentation layer. (I'll point out the references about what would be an event-driven domain model at the end of this answer).
Symfony 2
Now let's examine the same on the Symfony2 Application/FrontController: \Symfony\Component\HttpKernel\HttpKernel
It indeed has the main events during the request: Symfony\Component\HttpKernel\KernelEvents
/**
* Handles a request to convert it to a response.
*
* Exceptions are not caught.
*
* #param Request $request A Request instance
* #param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
*
* #return Response A Response instance
*
* #throws \LogicException If one of the listener does not behave as expected
* #throws NotFoundHttpException When controller cannot be found
*/
private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
{
// request
$event = new GetResponseEvent($this, $request, $type);
$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
if ($event->hasResponse()) {
return $this->filterResponse($event->getResponse(), $request, $type);
}
// load controller
if (false === $controller = $this->resolver->getController($request)) {
throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo()));
}
$event = new FilterControllerEvent($this, $controller, $request, $type);
$this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event);
$controller = $event->getController();
// controller arguments
$arguments = $this->resolver->getArguments($request, $controller);
// call controller
$response = call_user_func_array($controller, $arguments);
// view
if (!$response instanceof Response) {
$event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
$this->dispatcher->dispatch(KernelEvents::VIEW, $event);
if ($event->hasResponse()) {
$response = $event->getResponse();
}
if (!$response instanceof Response) {
$msg = sprintf('The controller must return a response (%s given).', $this->varToString($response));
// the user may have forgotten to return something
if (null === $response) {
$msg .= ' Did you forget to add a return statement somewhere in your controller?';
}
throw new \LogicException($msg);
}
}
return $this->filterResponse($response, $request, $type);
}
But besides of being "event-capable" it communicates directly with the ControllerResolver component, hence it's not fully event-driven since the beginning of the request process, though it triggers some events and allows some components to be pluggable (which is not the case of the ControllerResolver that's injected as a constructor parameter).
Instead, to be a fully event-driven component it should be as in ZF2 Application component:
// Trigger dispatch event
$result = $events->trigger(MvcEvent::EVENT_DISPATCH, $event, $shortCircuit);
Prado
I haven't enough time to investigate the source code, but at first it doesn't seems to be built in a SOLID way. Either way, what's a controller on MVC-alike frameworks, Prado calls it a TPage (Not sure yet):
http://www.pradosoft.com/demos/blog-tutorial/?page=Day3.CreateNewUser
And it indeed communicates directly with components:
class NewUser extends TPage
{
/**
* Checks whether the username exists in the database.
* This method responds to the OnServerValidate event of username's custom validator.
* #param mixed event sender
* #param mixed event parameter
*/
public function checkUsername($sender,$param)
{
// valid if the username is not found in the database
$param->IsValid=UserRecord::finder()->findByPk($this->Username->Text)===null;
}
[...]
}
I understand that the TPage is an event listener and can be pluggable. But it doesn't make your domain model event-driven. So I think that, in some extent, it's more close to the ZF2 proposal.
Event-driven examples
To finish this long answer, here's what a full-blown event-driven application would have:
Decoupling applications with Domains Events
http://www.whitewashing.de/2012/08/25/decoupling_applications_with_domain_events.html
Event sourcing
http://martinfowler.com/eaaDev/EventSourcing.html
Domain Event Pattern
http://martinfowler.com/eaaDev/DomainEvent.html
Event Collaboration
http://martinfowler.com/eaaDev/EventCollaboration.html
Event Interception
http://martinfowler.com/bliki/EventInterception.html
Message Endpoint
http://www.enterpriseintegrationpatterns.com/MessageEndpoint.html
... and so on
PHP is not stateless, HTTP is. To state it simply, we have essentially built a layer on top of a stateless technology upon which we can implement stateful designs. Taken together, PHP and your datastore of choice have all the tools they need to build an application design based on event driven patterns via the tokenization of sessions.
In a highly generalized way, you can think of HTTP as being for the web what BIOS has been for desktop computing. In fact, take this just a little bit further, and you can easily see the implicit event-driven nature of the web. You said "it's not an event but a whole new request", and I return with, "a whole new request is an event", and I mean that in the design pattern sense of the word. It has concrete semantic meaning relating to your user's interaction with your application.
Essentially, through patterns like MVC and Front Controller (and by the mechanism of HTTP cookies and PHP sessions), we simply restore session state, and then respond to the event, modifying that state accordingly.
I like to contemplate the essence of REST: Representational State Transfer... but I would add that we should not forget the implicit implication that state is only transferred when a UI event has occurred. So we maintain the contracts we have with HTTP that we "speak" only in "Representational States" of our model (i.e. a document, JSON, etc), but that is only our dialect. Other systems choose to speak in canvas coordinates, signal db, etc.
edit/more thoughts
So I've been pondering it for a while and I think there is a concept which illustrates a little of the ambiguity when discussing these patterns in the realm of PHP via HTTP: determinism. Specifically, once a request is received, the path of PHP execution is deterministic, and this is exactly why it's remarkably difficult to consider an "event-driven" architecture in PHP. My notion is that we should consider one level higher than PHP, to the larger "session" of interaction with the user.
In desktop computing, we use runloops and a state-ful context to "wait" for events. However, I will argue that the web is actually an improvement over this architecture (in most cases) but ultimately the same pattern. Instead of a runloop and infinite-duration state, we bootstrap our state when an event occurs and then process that event. And instead of just keeping that state in memory and waiting for the next event, we archive that state and close the resources. It could be considered less efficient in one sense (that we need to load state at every "event"), but it could also be called more efficient in that there is never idle state in memory for no reason. We only load state which is actually being consumed/manipulated
So in this way, think of PHP via HTTP as being event driven at the macro level, while resting assured that any given execution is indeed deterministic and not actually event driven at all. However, we implement a front-controller and MVC pattern so that we can provide application developers with the familiar structure of even driven hooks. When you are working with a decent framework, you simply say "I want to know when a user registers, and the user should be available to me to modify at that time". This is event-driven development. It should not concern you that the framework has bootstrapped the environment for (almost) the sole purpose of calling your hook (vs. the more traditional notion that the environment was already there and you were simply notified of an event). This is what it means to develop PHP in an event-driven way. The controllers determine (based on the request) which event is occurring, and uses whichever mechanism it is designed to use (i.e. observer pattern, hook architecture, etc) to allow your code to handle the event, respond to the event, or whatever nomenclature is most appropriate for your particular framework's semantics.

Categories