vendor/shopware/storefront/Controller/StoreApiProxyController.php line 66

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Controller;
  3. use Shopware\Core\Framework\Api\ApiDefinition\DefinitionService;
  4. use Shopware\Core\Framework\Feature;
  5. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  6. use Shopware\Core\Framework\Routing\Annotation\Since;
  7. use Shopware\Core\Framework\Routing\Exception\InvalidRequestParameterException;
  8. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  9. use Shopware\Core\PlatformRequest;
  10. use Shopware\Core\SalesChannelRequest;
  11. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\RequestStack;
  14. use Symfony\Component\HttpFoundation\Response;
  15. use Symfony\Component\HttpKernel\HttpKernelInterface;
  16. use Symfony\Component\HttpKernel\KernelInterface;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. /**
  19.  * @Route(defaults={"_routeScope"={"storefront"}})
  20.  *
  21.  * @deprecated tag:v6.5.0 - will be removed
  22.  */
  23. class StoreApiProxyController
  24. {
  25.     public const INHERIT_ATTRIBUTES = [
  26.         SalesChannelRequest::ATTRIBUTE_DOMAIN_LOCALE,
  27.         SalesChannelRequest::ATTRIBUTE_DOMAIN_SNIPPET_SET_ID,
  28.         SalesChannelRequest::ATTRIBUTE_DOMAIN_CURRENCY_ID,
  29.         SalesChannelRequest::ATTRIBUTE_DOMAIN_ID,
  30.         SalesChannelRequest::ATTRIBUTE_THEME_ID,
  31.         SalesChannelRequest::ATTRIBUTE_THEME_NAME,
  32.         SalesChannelRequest::ATTRIBUTE_THEME_BASE_NAME,
  33.         PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT,
  34.         PlatformRequest::ATTRIBUTE_CONTEXT_OBJECT,
  35.     ];
  36.     private KernelInterface $kernel;
  37.     private RequestStack $requestStack;
  38.     /**
  39.      * @internal
  40.      */
  41.     public function __construct(KernelInterface $kernelRequestStack $requestStack)
  42.     {
  43.         $this->kernel $kernel;
  44.         $this->requestStack $requestStack;
  45.     }
  46.     /**
  47.      * @Since("6.3.2.0")
  48.      * @Route("/_proxy/store-api", name="frontend.store-api.proxy", defaults={"XmlHttpRequest"=true})
  49.      *
  50.      * @deprecated tag:v6.5.0 - will be removed, use a custom controller instead
  51.      */
  52.     public function proxy(Request $requestSalesChannelContext $context): Response
  53.     {
  54.         Feature::triggerDeprecationOrThrow(
  55.             'v6.5.0.0',
  56.             'The storefront API-Route "/_proxy/store-api" is deprecated and will be removed in v6.5.0.0. Please write a custom controller that uses the store-api internally.'
  57.         );
  58.         $storeApiRequest $this->setupStoreApiRequest($request$context);
  59.         return $this->wrapInStoreApiRoute($storeApiRequest, function () use ($storeApiRequest): Response {
  60.             return $this->kernel->handle($storeApiRequestHttpKernelInterface::SUB_REQUEST);
  61.         });
  62.     }
  63.     private function setupStoreApiRequest(Request $requestSalesChannelContext $context): Request
  64.     {
  65.         $path $request->query->get('path');
  66.         if ($path === null || !\is_string($path)) {
  67.             throw new MissingRequestParameterException('path');
  68.         }
  69.         $url parse_url($path);
  70.         if ($url === false) {
  71.             throw new InvalidRequestParameterException('path');
  72.         }
  73.         $query null;
  74.         if (isset($url['query'])) {
  75.             parse_str($url['query'], $query);
  76.         }
  77.         $requestPath $url['path'] ?? '';
  78.         if (!\in_array(DefinitionService::STORE_APIexplode('/'$requestPath), true)) {
  79.             throw new InvalidRequestParameterException('The proxy controller can only be used for store-api routes');
  80.         }
  81.         $server array_merge($request->server->all(), ['REQUEST_URI' => $requestPath]);
  82.         $subRequest $request->duplicate($querynull, [], nullnull$server);
  83.         $subRequest->attributes->set(SalesChannelRequest::ATTRIBUTE_STORE_API_PROXY'1');
  84.         $subRequest->headers->set(PlatformRequest::HEADER_LANGUAGE_ID$request->headers->get(PlatformRequest::HEADER_LANGUAGE_ID$context->getLanguageIdChain()[0]));
  85.         $subRequest->headers->set(PlatformRequest::HEADER_ACCESS_KEY$context->getSalesChannel()->getAccessKey());
  86.         $subRequest->headers->set(PlatformRequest::HEADER_CONTEXT_TOKEN$context->getToken());
  87.         $subRequest->attributes->set(PlatformRequest::ATTRIBUTE_OAUTH_CLIENT_ID$context->getSalesChannel()->getAccessKey());
  88.         foreach (self::INHERIT_ATTRIBUTES as $inheritAttribute) {
  89.             if ($request->attributes->has($inheritAttribute)) {
  90.                 $subRequest->attributes->set($inheritAttribute$request->attributes->get($inheritAttribute));
  91.             }
  92.         }
  93.         $subRequest->attributes->set(SalesChannelRequest::ATTRIBUTE_IS_SALES_CHANNEL_REQUESTtrue);
  94.         if ($request->hasSession()) {
  95.             $subRequest->setSession($request->getSession());
  96.         }
  97.         return $subRequest;
  98.     }
  99.     private function wrapInStoreApiRoute(Request $request, callable $call): Response
  100.     {
  101.         $requestStackBackup $this->clearRequestStackWithBackup($this->requestStack);
  102.         $this->requestStack->push($request);
  103.         try {
  104.             return $call();
  105.         } finally {
  106.             $this->restoreRequestStack($this->requestStack$requestStackBackup);
  107.         }
  108.     }
  109.     private function clearRequestStackWithBackup(RequestStack $requestStack): array
  110.     {
  111.         $requestStackBackup = [];
  112.         while ($requestStack->getMainRequest()) {
  113.             $requestStackBackup[] = $requestStack->pop();
  114.         }
  115.         return $requestStackBackup;
  116.     }
  117.     private function restoreRequestStack(RequestStack $requestStack, array $requestStackBackup): void
  118.     {
  119.         $this->clearRequestStackWithBackup($requestStack);
  120.         foreach ($requestStackBackup as $backedUpRequest) {
  121.             $requestStack->push($backedUpRequest);
  122.         }
  123.     }
  124. }