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

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