/**
  * Create a Failed API Response from an Exception
  *
  * The HttpKernel exception catcher tries to enforce an error HTTP response code.
  * This can be avoided by using the X-Status-Code header.
  *
  * @param GetResponseForExceptionEvent $event
  */
 public function onKernelException(GetResponseForExceptionEvent $event)
 {
     $request = $event->getRequest();
     $pathConfig = $this->configCompiler->compileApiConfig($request);
     if (null === $pathConfig) {
         // This is not an API endpoint.
         return;
     }
     $exception = $event->getException();
     // Check if this is an OPTIONS request.
     if ($exception instanceof MethodNotAllowedHttpException && $request->getMethod() === Request::METHOD_OPTIONS) {
         // A MethodNotAllowedHttpException implies that the route exists but not for the requested HTTP method.
         // In the case of a an OPTIONS request (CORS preflight) we send a 200 OK instead of a 404 Not Found.
         $response = $this->responseGenerator->generateSuccessResponse();
         // Explicitly set the 200 OK status code as the X-Status-Code header so the HttpKernel allows the 200.
         /** @see Symfony\Component\HttpKernel\HttpKernel::handleException() */
         $response->headers->set('X-Status-Code', Response::HTTP_OK);
         // The MethodNotAllowedHttpException exception is populated with the methods that do exist for a route.
         // Use these existing methods in the Allow header.
         $exceptionHeaders = $exception->getHeaders();
         $response->headers->set('Allow', isset($exceptionHeaders['Allow']) ? $exceptionHeaders['Allow'] : null);
         $event->setResponse($response);
         return;
     }
     $httpCode = null;
     $errorCode = null;
     $errorTitle = null;
     $errorData = null;
     // Determine the API error code, API error title, and HTTP status code
     // depending on the type of exception thrown.
     if ($exception instanceof ApiResponseExceptionInterface) {
         // There is a separate HTTP status code that can also be set on the exception. The default is 400.
         $httpCode = $exception->getHttpStatusCode();
         $errorCode = $exception->getCode();
         $errorTitle = $exception->getMessage();
         $errorData = $exception->getErrorData();
     } elseif ($exception instanceof HttpExceptionInterface) {
         // Use the code from the Symfony HTTP exception as both the API error code and the HTTP status code.
         $httpCode = $exception->getStatusCode();
         $errorCode = $exception->getStatusCode();
         $errorTitle = Response::$statusTexts[$exception->getStatusCode()];
     } elseif ($exception instanceof AuthenticationException) {
         // Authentication exceptions use 401 for both the API error code and the HTTP status code.
         $httpCode = Response::HTTP_UNAUTHORIZED;
         $errorCode = Response::HTTP_UNAUTHORIZED;
         $errorTitle = Response::$statusTexts[Response::HTTP_UNAUTHORIZED];
     } elseif ($exception instanceof AccessDeniedException) {
         // Authorization exceptions use 403 for both the API error code and the HTTP status code.
         $httpCode = Response::HTTP_FORBIDDEN;
         $errorCode = Response::HTTP_FORBIDDEN;
         $errorTitle = Response::$statusTexts[Response::HTTP_FORBIDDEN];
     } else {
         // All other errors use 500 for both the API error code and the HTTP status code.
         $httpCode = Response::HTTP_INTERNAL_SERVER_ERROR;
         $errorCode = Response::HTTP_INTERNAL_SERVER_ERROR;
         // The API error title is determined based on the environment.
         if ($this->debug) {
             // For debug environments, exception messages and trace get passed straight through to the client.
             $message = sprintf('exception \'%s\' with message \'%s\' in %s:%s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine());
             $errorTitle = $message;
             $errorData = $exception->getTraceAsString();
         } else {
             // For non-debug environments, use the corresponding generic HTTP status message as the API error title.
             $errorTitle = Response::$statusTexts[Response::HTTP_INTERNAL_SERVER_ERROR];
         }
     }
     $response = $this->responseGenerator->generateErrorResponse($httpCode, $errorCode, $errorTitle, $errorData);
     $event->setResponse($response);
 }
 public function testSuccessResponseWithSpecificSerializer()
 {
     $factoryMock = \Mockery::mock(SerializerAdapterFactory::class)->shouldReceive('createSerializerAdapter')->once()->with('other_serializer')->andReturn(new JsonEncodeSerializerAdapter())->getMock();
     $generator = new ApiResponseGenerator($factoryMock);
     $generator->generateSuccessResponse('foobar', null, [], 'other_serializer');
 }