Fix missing CORS headers for GraphQL persisted queries in AEM as a Cloud Service

This article describes how to resolve missing CORS headers on GraphQL persisted query responses in Adobe Experience Manager as a Cloud Service when CDN caching interferes. The solution involves updating cache-control headers to prevent CDN caching and ensure CORS headers are present.

Description description

Environment

  • Adobe Experience Manager as a Cloud Service Publish or Preview
  • GraphQL persisted-query endpoint: /graphql/execute.json/*
  • Cross-origin browser access through the Adobe-managed CDN

Issue/Symptoms

  • A browser reports a CORS error when a cross-origin application requests a GraphQL persisted query.
  • The request includes an Origin header, but the CDN response doesn’t include the required Access-Control-Allow-Origin header.
  • Repeated requests from different origins receive a cached response without the required CORS header. The response headers show a cache HIT and a nonzero Age.
  • Dispatcher caching for the persisted-query endpoint is disabled, but the Adobe-managed CDN still serves a cached response.
  • An OSGi CORS policy is configured in AEM, but the Publish response still lacks the CORS header.

Cause

The Adobe-managed CDN cached a GraphQL persisted-query response without Access-Control-Allow-Origin and served that cached response to later requests for the same URL. Disabling Dispatcher caching doesn’t disable Adobe CDN caching. For Publish and Preview, configure CORS in the Dispatcher vhost; the Publish and Preview services don’t use the OSGi CORS policy for this configuration.

Resolution resolution

Follow the steps below to resolve the issue:

  1. Review the Dispatcher configuration and verify that caching is not enabled for the GraphQL persisted query endpoint /graphql/execute.json/*. The configuration variable that controls this behavior is typically CACHE_GRAPHQL_PERSISTED_QUERIES. Ensure that the variable is undefined or configured to prevent caching for this path.

  2. Update the Dispatcher vhost configuration to use mod_headers and set the Cache-Control header to private, no-store, no-cache, must-revalidate, max-age=0 for the GraphQL persisted query endpoint.

    code language-none
    Header set Cache-Control “private, no-store, no-cache, must-revalidate, max-age=0”
    
  3. Apply the configuration changes and reload or restart the Dispatcher service.

  4. Test the GraphQL persisted query endpoint by sending a request that includes an Origin header.

  5. Verify that the response includes the expected Access-Control-Allow-Origin header.

  6. Verify that the x-cache response header returns MISS instead of HIT, confirming that the response is not being served from the CDN cache.

  7. Review the AEM CORS policy configuration and verify that com.adobe.granite.cors.impl.CORSPolicyImpl is configured to allow the required origins for the endpoint.

  8. If the CDN has already cached a response that does not include the required CORS header, purge or invalidate the cache for the affected endpoint to ensure that subsequent requests receive the correct headers.

  9. Verify that requests to the GraphQL persisted query endpoint return the expected CORS headers and are processed successfully.

recommendation-more-help
experience-cloud-kcs-help-kbarticles