Dlaczego przeglądarka blokuje front headless Magento?
Gdy przenosisz frontend na osobną domenę — stawiając Next.js, Nuxt czy dedykowane PWA na store.example.com, a backend Magento 2 zostawiasz pod api.example.com — trafiasz na ścianę. Przeglądarka natychmiast blokuje wywołania API na mocy reguły Same-Origin Policy, a powtarzalne, kilkukilobajtowe zapytania GraphQL niepotrzebnie zapychają łącze i obciążają procesor serwera. Bez poprawnej obsługi nagłówków CORS i kompresji zapytań GraphQL Twój nowoczesny headless jest wolniejszy od klasycznego monolitu.
Rozdzielenie warstwy prezentacji od logiki biznesowej Adobe Commerce / Magento 2 to architektonicznie doskonały krok, ale silnik ten powstał z myślą o serwowaniu monolitycznych widoków z poziomu bloków layoutu i szablonów .phtml. Domyślny punkt wejścia dla zapytań API (REST oraz GraphQL pod adresem /graphql) nie ma wbudowanego elastycznego mechanizmu zarządzania polityką współdzielenia zasobów między źródłami. Skutek? Czerwona konsola deweloperska i całkowity paraliż aplikacji klienta.
Czym jest CORS w Magento i jak działa zapytanie preflight?
Mechanizm CORS (Cross-Origin Resource Sharing) to zabezpieczenie wbudowane w przeglądarki internetowe. Jeśli skrypt działający pod domeną A próbuje pobrać dane z domeny B, przeglądarka przed wysłaniem właściwego żądania (lub w jego trakcie) sprawdza, czy domena B w ogóle sobie tego życzy. W przypadku zapytań GraphQL, które zazwyczaj niosą niestandardowe nagłówki (np. autoryzacyjne lub specyficzne Content-Type: application/json), przeglądarka wysyła najpierw tzw. zapytanie preflight metodą HTTP OPTIONS.
Domyślne Magento 2 w wielu konfiguracjach serwerowych nie odpowiada na OPTIONS poprawnymi nagłówkami albo zwraca kod 405/404, co natychmiast zabija proces po stronie frontendu. Aby przeglądarka dopuściła ruch, backend musi zwrócić zestaw konkretnych nagłówków HTTP:
- Access-Control-Allow-Origin: wskazuje dokładnie, która domena ma prawo odpytywać API (np.
https://frontend.twojsklep.pl). - Access-Control-Allow-Credentials: flaga o wartości
true, niezbędna, jeśli zapytania GraphQL mają przesyłać ciasteczka sesyjne, nagłówki autoryzacji klienta (Bearer token) lub identyfikatory koszyka. - Access-Control-Allow-Headers i Access-Control-Allow-Methods: definicja dozwolonych metod (POST, GET, OPTIONS) oraz nagłówków (Authorization, Content-Type, Store).
- Access-Control-Max-Age: czas w sekundach, przez jaki przeglądarka może cache’ować odpowiedź preflight bez ponownego odpytywania serwera przed każdym strzałem.
Krytyczna pułapka bezpieczeństwa: Pokusa skonfigurowania nagłówkaAccess-Control-Allow-Origin: *na serwerze jest ogromna, gdy deweloper chce „żeby po prostu zaczęło działać”. Jednak specyfikacja W3C zabrania łączenia gwiazdki (wildcard) z nagłówkiemAccess-Control-Allow-Credentials: true. Jeśli spróbujesz to zrobić, przeglądarka bezwzględnie odrzuci odpowiedź, a autoryzowane zapytania koszykowe i logowanie użytkowników przestaną działać. Origin musi być jawnie zdefiniowany.
Do zarządzania tym mechanizmem z poziomu panelu administracyjnego Magento stworzyliśmy fork i aktualizację modułu CORS Requests, który pozwala na precyzyjne definiowanie dozwolonych domen per Store View bez konieczności hardcodowania reguł w konfiguracji Nginx czy Varnish.
Po co persisted queries (APQ) w architekturze GraphQL?
Drugim fundamentalnym problemem Magento headless jest specyfika samego GraphQL. W tradycyjnym REST API wysyłasz prosty request GET /rest/V1/products/123. Zapytanie jest krótkie, ma naturalny adres URL i może zostać z łatwością zapisane w pamięci podręcznej serwera brzegowego (Varnish, Fastly, Cloudflare CDN).
W GraphQL pojedyncze zapytanie o szczegóły produktu, warianty konfigurowalne, ceny i stany magazynowe potrafi ważyć od 3 do nawet 15 kilobajtów tekstu. Ponieważ payload jest duży, wysyła się go metodą POST. Metoda POST z definicji nie jest cache’owalna przez publiczne serwery proxy i CDN-y. W efekcie każde załadowanie karty produktu przez klienta generuje potężny ruch sieciowy i zmusza Magento do parsowania drzewa zapytań GraphQL od zera przy każdym pojedynczym wyświetleniu strony.
Rozwiązaniem tego problemu jest protokół Automatic Persisted Queries (APQ), spopularyzowany przez Apollo GraphQL. Mechanizm ten działa w ramach trzyetapowego protokołu (handshake):
- Pierwszy strzał (optymistyczny hash): Frontend zamiast wysyłać całe, wielokilobajtowe zapytanie, oblicza jego unikalny skrót SHA-256 i wysyła zapytanie metodą
GET /graphql?hash=abc123.... - Brak w pamięci (PersistedQueryNotFound): Jeśli Magento widzi ten skrót po raz pierwszy, odpowiada błędem o kodzie
PersistedQueryNotFound. - Rejestracja i cache: Frontend ponawia żądanie — tym razem wysyła pełną treść zapytania wraz ze skrótem SHA-256. Magento wykonuje zapytanie, ale jednocześnie paruje hash z treścią zapytania i zapisuje go w pamięci (Redis/Fastly).
- Wszystkie kolejne zapytania: Każdy kolejny klient wchodzący na tę samą podstronę wysyła już wyłącznie lekki hash przez metodę
GET. Ponieważ zapytanie leci przez GET z unikalnym parametrem w URL, serwer CDN (Cloudflare, Fastly) bez problemu zapisuje całą odpowiedź w cache na krawędzi sieci. Magento nie jest nawet dotykane.
Do wdrożenia tego procesu w ekosystemie Adobe Commerce służy nasz dopracowany moduł Automatic Persisted Queries.
Cmentarz modułów Magento: dlaczego musieliśmy stworzyć forki?
Gdy zaczynasz przeszukiwać sieć w poszukiwaniu rozwiązań tych dwóch problemów, trafiasz na dwa znane projekty: repozytorium creatuity/magento-2-cors-requests oraz danslo/magento2-module-automatic-persisted-queries. Niestety, rzeczywistość ekosystemu open-source bywa bezwzględna — oba projekty zostały porzucone w okolicach 2023 roku.
Oryginalne paczki nie deklarują kompatybilności ze współczesnymi wersjami Magento (2.4.7, 2.4.8, 2.4.9) ani z PHP 8.2, 8.3 i 8.4. Próba ich standardowej instalacji z repozytorium Packagist kończy się konfliktami zależności Composera, błędami krytycznymi przy kompilacji DI lub ostrzeżeniami o przestarzałych mechanizmach PHP. W module danslo istniał dodatkowo kuriozalny błąd architektoniczny: brak pliku etc/acl.xml, przez co nowo dodana sekcja konfiguracji w panelu administracyjnym Magento zwracała błąd braku uprawnień (403 Forbidden) nawet dla głównego administratora systemu.
W SISL prowadzimy aktywne wdrożenia e-commerce, dlatego nie możemy pozwalać sobie na niesprawdzone zależności. Przejęliśmy utrzymanie obu modułów, naprawiliśmy błędy uprawnień ACL, dostosowaliśmy kod do standardów typowania PHP 8.4 i weryfikujemy ich działanie na najnowszych wydaniach platformy.
Jak wdrożyć moduły CORS i APQ krok po kroku?
Ponieważ paczki na oficjalnym Packagiście wskazują na porzucony kod źródłowy, instalacja naszych utrzymywanych wersji wymaga dodania bezpośrednich repozytoriów VCS do pliku composer.json w Twoim projekcie Magento. Poniżej znajduje się kompletna procedura instalacji.
1. Instalacja modułu CORS Requests
Repozytorium modułu dostępne jest pod adresem: https://github.com/SISL-source/magento2-cors-requests.
composer config repositories.sisl-cors vcs https://github.com/SISL-source/magento2-cors-requests
composer require creatuity/magento-2-cors-requests:dev-main
bin/magento module:enable Creatuity_CorsRequests && bin/magento setup:upgradePo instalacji przejdź do panelu administracyjnego: Stores > Configuration > General > Web > CORS Requests. Wpisz pełny URL swojego frontendu (np. https://frontend.twojsklep.pl) i ustaw dozwolone nagłówki.
2. Instalacja modułu Automatic Persisted Queries (APQ)
Repozytorium modułu dostępne jest pod adresem: https://github.com/SISL-source/magento2-automatic-persisted-queries.
composer config repositories.sisl-apq vcs https://github.com/SISL-source/magento2-automatic-persisted-queries
composer require danslo/magento2-module-automatic-persisted-queries:dev-main
bin/magento module:enable Danslo_Apq && bin/magento setup:upgrade && bin/magento cache:enable apqW sekcji Stores > Configuration > Services > GraphQL > Automatic Persisted Queries możesz skonfigurować czas życia cache dla zarejestrowanych hashy oraz wybrać backend cache’ujący (zalecamy Redis).
Czy taka konfiguracja jest bezpieczna i produkcyjna?
Odpowiednio wdrożone moduły CORS i APQ to standard rynkowy w architekturze headless. Moduł CORS odrzuca zapytania z niezaufanych domen na wczesnym etapie cyklu życia aplikacji, co zapobiega atakom typu CSRF i nieuprawnionemu wykorzystywaniu API przez zewnętrzne serwisy. Z kolei APQ drastycznie redukuje podatność na ataki typu Denial of Service oparte na parsowaniu gigantycznych, zagnieżdżonych zapytań GraphQL, ponieważ serwer zamiast przetwarzać skomplikowaną składnię, serwuje dane bezpośrednio ze zoptymalizowanego cache.
Jeśli planujesz migrację swojego sklepu na architekturę headless, budujesz nowe PWA lub potrzebujesz audytu wydajności obecnego API GraphQL w Adobe Commerce, napisz do nas — pomożemy Ci uniknąć typowych błędów infrastrukturalnych.