<?php
namespace Can\RestBundle\EventListener;
use Can\RestBundle\CanRestBundle;
use Can\RestBundle\Http\Exception\NotImplementedHttpException;
use Can\RestBundle\Http\Method;
use Can\RestBundle\Mapping\MappingException;
use Can\RestBundle\Mapping\MetadataStore;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Exception;
/**
* When a request method is received that is unrecognized or not implemented
* by an origin server, the origin server SHOULD respond with the 501 (Not
* Implemented) status code. When a request method is received that is known
* by an origin server but not allowed for the target resource, the origin
* server SHOULD respond with the 405 (Method Not Allowed) status code.
*
* @see https://tools.ietf.org/html/rfc7231#section-4.1
*
* @group core
*
* @package can/rest-bundle
* @author lechecacharro <lechecacharro@gmail.com>
*/
class RequestMethodListener
{
/**
* @var MetadataStore
*/
protected $store;
/**
* RequiredBodyListener constructor.
*
* @param MetadataStore $store
*/
public function __construct(MetadataStore $store)
{
$this->store = $store;
}
/**
* @param RequestEvent $event
*/
public function onRequest(RequestEvent $event): void
{
if (! $event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
if (! $request->attributes->get(CanRestBundle::ATTR_SERVICE_ZONE) ||
! $request->attributes->has(CanRestBundle::ATTR_SERVICE_NODE)) {
return;
}
try {
Method::getMethod($request->getMethod());
} catch (Exception $e) {
// When a request method is received that is unrecognized
// or not implemented by an origin server, the origin server
// SHOULD respond with the 501 (Not Implemented) status code
throw new NotImplementedHttpException(sprintf('Method %s is not implemented', $request->getMethod()));
}
$serviceNode = $request->attributes->get(CanRestBundle::ATTR_SERVICE_NODE);
try {
$metadata = $this->store->getMetadataFor($serviceNode);
} catch (MappingException $f) {
// This case is handled by the router component
return;
}
if (! $metadata->supportsOperation($request->getMethod())) {
// When a request method is received that is known by an origin
// server but not allowed for the target resource, the origin
// server SHOULD respond with the 405 (Method Not Allowed)
// status code
throw new MethodNotAllowedHttpException($metadata->getSupportedMethodNames());
}
}
}