flutter_cached_network_image icon indicating copy to clipboard operation
flutter_cached_network_image copied to clipboard

CORS errors on Flutter web

Open Kurczaak opened this issue 1 year ago • 18 comments

🐛 Bug Report

This bug happened to me after a while of using the package so it might not be easy to reproduce. I am unable to run my project due to CORS policies. This does not happen using Flutter's Image.network. I am fetching data from my Contentful CMS backend.

Expected behavior

Flutter web project run flawlesly

Reproduction steps

Run a Flutter Web app and try to load images from Contentful CMS backend.

Configuration

Version: 3.4.1

Platform:

  • [ ] :iphone: iOS
  • [ ] :robot: Android
  • [x] 🕸️ Web

Kurczaak avatar Sep 19 '24 14:09 Kurczaak

You can change the imageRenderMethodForWeb parameter to ImageRenderMethodForWeb.HttpGet instead of ImageRenderMethodForWeb.HtmlImage and that should fix your issue.

Remy2701 avatar Sep 20 '24 10:09 Remy2701

I'm still debugging this issue for my app so I'm not 100% sure on the specifics, but for what it's worth that fix did not work for me, and it appears the enum is a package other than this one I directly depend on.

pauljonescodes avatar Sep 22 '24 20:09 pauljonescodes

I'm currently not able to check it, but I recall I tried to go for other method but couldn't use the enum

Kurczaak avatar Sep 22 '24 20:09 Kurczaak

I solved my problem by using the HTML renderer, it appears the default may have changed in some Flutter version upgrade. It would also appear like this is deprecated by Flutter, so I'm not sure I'd advise this solution for others if it can be avoided. Further, I'm accessing an S3 bucket which I do not control, I believe I could solve this is I controlled the CORS configuration and allowed all hosts.

pauljonescodes avatar Sep 22 '24 21:09 pauljonescodes

Even with allow all hosts, images fail to load.

[
    {
        "origin": [
            "*"
        ],
        "method": [
            "GET"
        ],
        "maxAgeSeconds": 3600
    }
]

I wonder if it's because Wasm requires stricter headers. For example, deploying Wasm requires the server to serve these headers.

    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Cross-Origin-Embedder-Policy",
          "value": "credentialless"
        },
        {
          "key": "Cross-Origin-Opener-Policy",
          "value": "same-origin"
        }
      ]
    }

Wasm might require all files to be returned with

"responseHeader": ["Content-Type"],

rayliverified avatar Sep 26 '24 05:09 rayliverified

I encountered the following error: ImageCodecException: Failed to load network image.

Adding this helped resolve the issue: imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,

However, I am still facing another issue, GET https://lh3.googleusercontent.com/a/ACg8ocJEb--2bAckEYPPmMs8PL_tR031rtQ5pXJQF6ZNQWPQZBNnUw=s96-c 429 (Too Many Requests)

this is my cors

[ { "origin": ["*"], "method": ["GET"], "maxAgeSeconds": 3600 } ]

The images load fine on mobile, but I am encountering a 429 (Too Many Requests) error on the web.

max-anders avatar Oct 06 '24 16:10 max-anders

I encountered the following error: ImageCodecException: Failed to load network image.

Adding this helped resolve the issue: imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,

However, I am still facing another issue, GET https://lh3.googleusercontent.com/a/ACg8ocJEb--2bAckEYPPmMs8PL_tR031rtQ5pXJQF6ZNQWPQZBNnUw=s96-c 429 (Too Many Requests)

this is my cors

[ { "origin": ["*"], "method": ["GET"], "maxAgeSeconds": 3600 } ]

The images load fine on mobile, but I am encountering a 429 (Too Many Requests) error on the web.

I have the same problem. Have you found a solution?

luca1994ioma avatar Oct 09 '24 12:10 luca1994ioma

For me changing the method worked. I did have to add the cached_network_image_platform_interface dependency. I'm guessing if you use the get method you'll probably have to allow the requests on your backend.

Remy2701 avatar Oct 09 '24 15:10 Remy2701

@Remy2701

I have the same problem. Have you found a solution?

I've noticed that in my case only PNG images fails to load properly but everything seems to work fine in release mode for now

max-anders avatar Oct 28 '24 16:10 max-anders

@rayliverified

Did you try what you suggested ?

cedvdb avatar Nov 15 '24 10:11 cedvdb

Are you using firebase ?

15 Kas 2024 Cum 13:57 tarihinde cedvdb @.***> şunu yazdı:

@rayliverified https://github.com/rayliverified

Did you try what you suggested ?

— Reply to this email directly, view it on GitHub https://github.com/Baseflow/flutter_cached_network_image/issues/972#issuecomment-2478558090, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUTSNQ56BB46FPBBISYP3U32AXHR5AVCNFSM6AAAAABOQBGJ46VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINZYGU2TQMBZGA . You are receiving this because you are subscribed to this thread.Message ID: @.*** com>

enes-vural avatar Nov 15 '24 10:11 enes-vural

I have the same issue. What I can do now is use the flutter build web --web-renderer html command, but I'm not sure if this will trigger another problem.

Does anyone have a better way to fix this?

And I found that the header is incorrect.
The current header is Sec-fetch-mode: cors, but I think the value should be set to no-cors.

alazypig avatar Dec 06 '24 06:12 alazypig

Hey everyone, a current workaround is to switch to the beta / master channel and switch to Wasm single-threaded. https://x.com/kevmoo/status/1852518909079179503 image

rayliverified avatar Dec 06 '24 06:12 rayliverified

I have the same issue. What I can do now is use the flutter build web --web-renderer html command, but I'm not sure if this will trigger another problem.

Does anyone have a better way to fix this?

And I found that the header is incorrect. The current header is Sec-fetch-mode: cors, but I think the value should be set to no-cors.

I have implemented a solution to render this specific part using the HTML tag when running on the web platform. Here's the code:

import 'dart:html';
import 'dart:ui_web';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
// some other libraries

class UserAvatar extends StatelessWidget {
  final double width;
  final String? imageUrl;

  const UserAvatar({super.key, this.imageUrl = '', required this.width});

  @override
  Widget build(BuildContext context) {
    String photoSource = imageUrl ?? '';

    if (photoSource.isEmpty) {
      return ClipRRect(
        borderRadius: BorderRadius.circular(width),
        child: Image.asset(
          R.assetsImagesLogo,
          width: width,
          height: width,
          fit: BoxFit.cover,
        ),
      );
    }

    if (kIsWeb) {
      platformViewRegistry.registerViewFactory(photoSource, (_) {
        final element = ImageElement();

        element.src = photoSource;
        element.style.width = '100%';
        element.style.height = '100%';

        return element;
      });

      return ClipRRect(
          borderRadius: BorderRadius.circular(width),
          child: SizedBox(
              width: width,
              height: width,
              child: HtmlElementView(
                viewType: photoSource,
              )));
    }

    return ClipRRect(
      borderRadius: BorderRadius.circular(width),
      child: CachedNetworkImage(
          imageUrl: photoSource,
          width: width,
          height: width,
          placeholder: (context, url) => CircularProgressIndicator(
                color: SuperTheme.lightThemeColors['mainYellow'],
              ),
          errorWidget: (context, url, error) => Image.asset(
                R.assetsImagesLogo,
                width: width,
                height: width,
              )),
    );
  }
}

alazypig avatar Dec 06 '24 08:12 alazypig

@Remy2701 suggestion worked perfectly for me. cached_network_image_platform_interface isn't listed on pub.dev but running flutter pub add cached_network_image_platform_interface added the dependency to my Flutter project no problem.

buttonsrtoys avatar Jan 15 '25 20:01 buttonsrtoys

Shouldn't it be exported by the plugin though ?

cedvdb avatar Jan 16 '25 01:01 cedvdb

ImageRenderMethodForWeb.HttpGet doesnt work for me. Why is this such a hard problem to solve. its been a flutter issue for YEARS.

The only thing that works is the slower html renderer for web. ridiculous

colbymaloy avatar Jan 20 '25 12:01 colbymaloy

@colbymaloy You can write the following to fix CORS errors:

Image(
  image: NetworkImage(
    src,
    webHtmlElementStrategy: WebHtmlElementStrategy.prefer,
  ),
)

Added in PR https://github.com/flutter/flutter/pull/159917.

Wdestroier avatar Mar 08 '25 11:03 Wdestroier