Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more

CORS Issues with React Application in Optimizely CMS 12

Vote:
 

Hi,

I am currently working on a React application that uses the Fetch API to retrieve documents from Episerver. However, we’re encountering CORS errors. I faced a similar issue with CMS 11, where I attempted several approaches to handle the issue, which I’ve detailed in another post

In CMS 12, CORS is built-in, but we are still experiencing CORS errors. It works in CMS 12 but the behavior is inconsistent compared to CMS 11, where the issue was constant.

My CMS 12 code snippet for CORS configuration is as follows:

 public void ConfigureServices(IServiceCollection services)
 {
     services.AddCors(options =>
     {
         options.AddPolicy("AllowSpecificOrigin", builder =>
         {
             builder.WithOrigins(_configuration["AllowedOrigins"]?.Split(",") ?? Array.Empty<string>())
                 .AllowAnyHeader().AllowAnyMethod();
         });
     });
 }

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 {
     app.UseCors("AllowSpecificOrigin");
 }

The _configuration["AllowedOrigins"] includes the sites calling Optimizely, defined in the appsettings from Passportal:

"AllowedOrigins": https://xyz-dev.xxx.com, https://uat.xxx.com

Note: I have also tried wild card character to see if that works but the issue is still inconsistent wherein the documents fetching works at 1 time & stops the next instance.

When I temporarily enable CORS at the WebApp level via the Azure Portal, the application works both in CMS 11 & 12. But when I attempt to implement CORS via code changes, the issue persists. It seems something might be cutting off the headers at the Cloudflare level or another point, but I can’t pinpoint it.

The challenge with this workaround is that I only have access to the lower environments, and while I can make the change there, Optimizely manages the production and business testing environments. They are not willing to implement this change, which brings me to their response:

Optimizely’s Response: "CORS is not a feature that can be configured on the DXP platform. This was a decision made by the product team, and the configurations must be done within the code base."

So reaching out to Optimizely support has not been helpful, as we're just going in circles without a resolution. We implemented an alternate solution in CMS 11, but we'd like to see CORS functionality work smoothly in CMS 12, given that it’s built-in.

Has anyone here encountered similar issues or have suggestions on how to resolve this in CMS12?

Any help would be greatly appreciated, as Optimizely support hasn’t been effective so far.

My client side script code :

<script type="text/javascript">
   async function downloadDocumentsfrom12() {
  const files = [
    { url: 'https://inte12.sitea.xxx.com/siteassets/Solution-Analytics/path/solution-documents/sample_explain.pdf', name: 'sample Explain' },
    { url: 'https://inte12.sitea.xxx.com/siteassets/Solution-Analytics/path/solution-documents/dummy.pdf', name: 'dummy' }
  ];
  try {
    const fetchPromises = files.map((file) =>
      fetch(file.url)
        .then(response => {
          if (!response.ok) {
            throw new Error(`Failed to fetch ${file.name} from ${file.url}`);
          }
          return response.blob();
        })
        .then(blob => {
          const url = URL.createObjectURL(blob);
          const link = document.createElement('a');
          link.href = url;
          link.download = `${file.name}.pdf`; 
          link.click();
          console.log(`${file.name} downloaded successfully`);
        })
        .catch(error => console.error(`Error downloading ${file.name}:`, error))
    );

    // Wait for all fetch promises to complete
    await Promise.all(fetchPromises);
  } catch (error) {
    console.error('Error in fetching one or more documents:', error);
  }
}

 

 

Regards,

Farhin

#336477
Edited, Feb 06, 2025 17:57
Vote:
 

Hi, you're creating a policy called AllowSpecificOrigin, but where and how are you using it?

#336478
Feb 06, 2025 19:58
Farhin - Feb 06, 2025 20:06
Sorry my bad. I updated the code section in my query post above in Configure Method().
Johan Petersson - Feb 06, 2025 20:12
If that is your configuration, then I'm pretty sure that's not your issue. Something else with the download code is the culprit.
Farhin - Feb 06, 2025 20:18
Download code is just a simple fetch call that I have included in my query post for your reference. If that is the case, it should not work all the time. Here the problem is it is inconsistent.
Johan Petersson - Feb 06, 2025 20:37
I wouldn't call that a "simple" fetch. You're also simulating a click on a download link. In the support case, it was mentioned that for this to work you also need to include a Content-Disposition header from the server for each file, see https://html.spec.whatwg.org/multipage/links.html#downloading-resources (the last paragraph), did you try that?
Farhin - Feb 06, 2025 20:52
How does adding it make any difference? Correct me if I am wrong here; My understanding is that Content-Disposition is an optional HTTP header that provides guidance to the browser or client on how to handle the response. Among other things, I know I have tried adding this on the front end, but it didn’t make any difference. The issue, however, is inconsistent in CMS 12—it works in one instance but not in another. When I go through the CORS blade in the Azure portal, it works just fine, so there is clearly something that is stripping the headers.
Johan Petersson - Feb 06, 2025 21:06
Thought it was worth a try, but since you're using createObjectUrl, it might not make sense. Speaking of which, note that all the documents will be allocated as strings https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static#usage_notes. This is probably not that optimal if users choose to download many and/or large documents at once.

Do you actually have to download the documents as blobs with fetch, can't you just set the href to the document URL?
Farhin - Feb 06, 2025 21:12
This is the workaround we're using for CMS 11 :-) Instead of using href calls, we do need to download them with fetch for a better UX experience. It's crucial that this works, rather than relying on a hyperlink.
Vote:
 

Do you mind posting your issue number?

#336479
Feb 06, 2025 20:02
Farhin - Feb 06, 2025 20:11
Issue # as in Optimizely ticket? Here you go; 1568635 & a follow up 1626294 since this has been going for more than 3+months
Vote:
 

I just pasted following in the browser console, and it doesn't download the images reliably. It just downloads the first image for me. Checking the network tab, I can see that both images are requested and the server is responding with correct CORS headers. This way of downloading documents is just not reliable.

const files = [
  {
    url: "https://fastly.picsum.photos/id/173/200/300.jpg?hmac=9Ed5HxHOL3tFCOiW6UHx6a3hVksxDWc7L7p_WzN9N9Q",
    name: "Image 1",
  },
  {
    url: "https://fastly.picsum.photos/id/1005/200/400.jpg?hmac=qFOCeB6Gj87mocLz5LEGRxB1R2sbbzgexrjTuF_wrpc",
    name: "Image 2",
  },
];
const fetchPromises = files.map((file) =>
  fetch(file.url)
    .then((response) => {
      if (!response.ok) {
        throw new Error(`Failed to fetch ${file.name} from ${file.url}`);
      }
      return response.blob();
    })
    .then((blob) => {
      const url = URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = `${file.name}.jpg`;
      link.click();
      console.log(`${file.name} downloaded successfully`);
    })
    .catch((error) => console.error(`Error downloading ${file.name}:`, error))
);

await Promise.all(fetchPromises);

 It's not the fetch that fails with above code, but rather the "hack" with a download link.

#336488
Feb 06, 2025 21:43
Farhin - Feb 07, 2025 10:49
I understand what you're trying to say, but the fact remains that the same fetch code works seamlessly every time I add the domain entry in the CORS blade within Azure. The inconsistent behavior stops as soon as I add it.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.