vendor/can/rest/src/Can/RestBundle/EventListener/RequestBodyListener.php line 52

Open in your IDE?
  1. <?php
  2. namespace Can\RestBundle\EventListener;
  3. use Can\RestBundle\CanRestBundle;
  4. use Can\RestBundle\Http\Exception\UnsupportedMediaTypeHttpException;
  5. use Can\RestBundle\Http\HttpConfiguration;
  6. use Can\RestBundle\Http\Method;
  7. use Can\RestBundle\Http\MethodSupport;
  8. use Symfony\Component\HttpFoundation\Request;
  9. use Symfony\Component\HttpKernel\Event\RequestEvent;
  10. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  11. use Exception;
  12. /**
  13.  * Some of the HTTP methods do not define request bodies. Servers MUST examine
  14.  * all requests for a body, even when a body was not expected. In cases where
  15.  * a request body is present but would be ignored by a server, the server MUST
  16.  * reject the request with 415 (Unsupported Media Type).
  17.  *
  18.  * This informs the client (which may have been attempting to use an extension)
  19.  * that the body could not be processed as the client intended.
  20.  *
  21.  * @group core
  22.  *
  23.  * @package can/rest-bundle
  24.  * @author lechecacharro <lechecacharro@gmail.com>
  25.  */
  26. class RequestBodyListener
  27. {
  28.     /**
  29.      * @var HttpConfiguration
  30.      */
  31.     protected $configuration;
  32.     /**
  33.      * RequiredBodyListener constructor.
  34.      *
  35.      * @param HttpConfiguration $configuration
  36.      */
  37.     public function __construct(HttpConfiguration $configuration)
  38.     {
  39.         $this->configuration $configuration;
  40.     }
  41.     /**
  42.      * @param RequestEvent $event
  43.      */
  44.     public function onRequest(RequestEvent $event): void
  45.     {
  46.         // Skip any check if the configuration states that we should
  47.         // allow unexpected entities in the body of requests which have
  48.         // no semantic defined for such entity
  49.         if ($this->configuration->isAllowUnexpectedEntities()) {
  50.             return;
  51.         }
  52.         if (! $event->isMasterRequest()) {
  53.             return;
  54.         }
  55.         $request $event->getRequest();
  56.         if (! $request->attributes->get(CanRestBundle::ATTR_SERVICE_ZONE)) {
  57.             return;
  58.         }
  59.         try {
  60.             $method Method::getMethod($request->getMethod());
  61.         } catch (Exception $e) {
  62.             // This should not ever happen, as the RequestMethodListener
  63.             // should handle this case
  64.             throw new MethodNotAllowedHttpException(MethodSupport::getHttpMethods(0));
  65.         }
  66.         $hasContent $this->hasContent($request);
  67.         $request->attributes->set(CanRestBundle::ATTR_REQUEST_CONTENT$hasContent);
  68.         if ($hasContent && ! $method->mayHaveRequestBody()) {
  69.             throw new UnsupportedMediaTypeHttpException(sprintf(
  70.                 'No semantic defined for the request body entity of a %s request',
  71.                 $method->getName()
  72.             ));
  73.         }
  74.     }
  75.     /**
  76.      * @param Request $request
  77.      *
  78.      * @return bool
  79.      */
  80.     private function hasContent(Request $request): bool
  81.     {
  82.         // DO NOT use $request->getContent(), as in case of POST or PUT requests,
  83.         // it would read the php://input fully using file_get_contents(), which
  84.         // can be expensive if the request body is too large
  85.         $contentLength $request->headers->get('Content-Length'0);
  86.         if (is_array($contentLength)) {
  87.             $contentLength = (int) reset($contentLength);
  88.         }
  89.         return $contentLength 0;
  90.     }
  91. }