114

It seems like CORS error is well-known issue in the web field. But I tried flutter web for the first time ever and I faced critical error.

The code below worked well in app version when it was running on iOS device, but when i tested the same code on Chrome with web debugging from beta channel, it encountered CORS error.

Other Stack Overflow answers explained how to solve the CORS issue with server-side files of their projects, but I have totally no idea what is server thing and how to deal with their answers. The error message from Chrome console is below:

[ Access to XMLHttpRequest at 'https://kapi.kakao.com/v1/payment/ready' from origin
'http://localhost:52700' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. ]

So, what I want to do is to solve above 'Access-Control-Allow-Origin header' issue ONLY WITH DART CODE! Code below is what I've tried to solve these issues only with my main.dart.

onPressed: () async {
      var res =
          await http.post('https://kapi.kakao.com/v1/payment/ready', encoding: Encoding.getByName('utf8'), headers: {
        'Authorization': 'KakaoAK $_ADMIN_KEY',
        HttpHeaders.authorizationHeader: 'KakaoAK $_ADMIN_KEY',
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, HEAD",
      }, body: {
        'cid': 'TC0ONETIME',
        'partner_order_id': 'partner_order_id',
        'partner_user_id': 'partner_user_id',
        'item_name': 'cool_beer',
        'quantity': '1',
        'total_amount': '22222',
        'vat_amount': '2222',
        'tax_free_amount': '0',
        'approval_url': '$_URL/kakaopayment',
        'fail_url': '$_URL/kakaopayment',
        'cancel_url': '$_URL/kakaopayment'
      });
      Map<String, dynamic> result = json.decode(res.body);
      print(result);
    },

Even though I actually had the header "Access-Control-Allow-Origin": "*" which most other answers recommended, the Chrome console printed same error message. Weird thing is that the same code made successful request in mobileApp version. So I think this is only problem with flutter WEB VERSION.

Hope somebody can figure it out and suggest only-dart code to resolve the issue in my main.dart!

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
tsitixe
  • 1,851
  • 3
  • 14
  • 24
  • This could be the solution you are looking for https://stackoverflow.com/a/37765371/13758642 – JLarana Jul 20 '21 at 10:11
  • Using [Osman Tuzcu](https://stackoverflow.com/users/10757031/osman-tuzcu)'s answer, I created [flutter_cors](https://pub.dev/packages/flutter_cors) to make the process easier. – Rexios Jan 11 '22 at 02:14
  • Hope this https://stackoverflow.com/a/72321040/17798537 can help you :) – Sittiphan Sittisak Jul 05 '23 at 08:36

28 Answers28

316

1- Go to flutter\bin\cache and remove a file named: flutter_tools.stamp

2- Go to flutter\packages\flutter_tools\lib\src\web and open the file chrome.dart.

3- Find '--disable-extensions'

4- Add '--disable-web-security'

joe
  • 8,383
  • 13
  • 61
  • 109
Osman Tuzcu
  • 3,378
  • 1
  • 7
  • 7
90

Since Flutter 3.3.0

I implemented the option to add any browser flag to the flutter command.

flutter run -d chrome --web-browser-flag "--disable-web-security"

Or for drive command:

flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d web-server --web-browser-flag="--disable-web-security"

Note: This is just for development and testing. Flutter is executed explicitly on the client's browser! You should NOT and you can NOT disable it in production (as stated by @Tommy), as it is a security feature of the browser, and not meant to be changed in dart code. You have to enable CORS on your web server, which is providing the resources of your Flutter app, to ensure it works for everyone.

If you use dart language without Flutter on the server side with shelf, then see this response.

User Rebo
  • 3,056
  • 25
  • 30
  • How can we use this flag in launch.json? – aytunch Feb 20 '23 at 21:53
  • 9
    You can add `args` to your [launch config](https://docs.flutter.dev/development/tools/vs-code#run-app-in-debug-profile-or-release-mode): `{"name": ..., "request": "launch", "type": "dart", "args": ["--web-browser-flag=--disable-web-security"]}` – User Rebo Feb 21 '23 at 00:46
  • is it possible to add this flag to run configuration in android studio? – Abdulaziz Alnahhas Apr 20 '23 at 08:31
  • 1
    Of course @Abdulaziz: just add the flag to the "Additional run args" in your Run configuration: https://stackoverflow.com/a/64686348/5164462 – User Rebo Apr 26 '23 at 07:23
22

I think disabling web security as suggested will make you jump over the current error for now but when you go for production or testing on other devices the problem will persist because it is just a workaround, the correct solution is from the server side to allow CORS from the requesting domain and allow the needed methods, and credentials if needed.

Tommy
  • 221
  • 2
  • 7
11

This is a CORS (cross-origin resource sharing) issue and you do not have to delete/modify anything. You just have to enable the CORS request from your server-side and it will work fine.

In my case, I have created a server with node.js and express.js, so I just added this middleware function that will run for every request.

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Methods", "GET,PUT,PATCH,POST,DELETE");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

And BOOOOM! I received the data.

You just have to look at the settings to enable CORS for your server.

Ali Murtaza
  • 414
  • 4
  • 9
10

run/compile your Flutter web project using web-renderer. This should solve the issue both locally and remotely:

flutter run -d chrome --web-renderer html
flutter build web --web-renderer html
Praharsh Bhatt
  • 556
  • 5
  • 24
6

march 2023 update

i'm using google cloud functions v2 on google cloud run for my functions. Instead of calling CORS-sensitive apis in my flutter client or running a whole node js client app, i'm calling my functions written in js(running on google cloud functions v2 node js 18 env). So that the only http.dart to make call to google cloud run will be the main process of flutter client, which would help the original problems to be solved. Of course there are fees for using google cloud run, but i believe the fees are quite reasonable to run the whole functions for our services [:


Server side engine like node js or django is really needed to work with flutter web with bunch of external apis. Actually there's high possibility of same CORS error when we try to use internal api because of the CORS mechanism related to port number difference.

There are bunch of steps and answers from SO contributors that recommend to use chrome extensions to avoid CORS errors, but that is actually not cool for users. All the users should download the browser extensions to use the single website from us, which wouldn't be there if we used true server engines.

CORS is from browser as far as i know, so our flutter ios and android apps with same api code don't give those CORS errors. First time i encountered this error with flutter web, i believed i can deal with CORS in my app code lines. But that is actually not healthy way for users and long term dev plans.

Hope all flutter web newbies understand that web is quite a wild field for us. Even though i'm also newbie here, i highly recommend all the flutter web devs from 1.22.n stable to learn server side engines like node js. It is worth try.

And if u came so far down to this line of my self-answer, here's a simple guide for flutter web with node js. Flutter web is on stable channel but all those necessary infra are not fully ready for newbies like me. So be careful when you first dive into web field, and hope you re-check all the conditions and requirements to find out if you really need web version of your flutter app, and also if you really need to do this work with flutter. And my answer was yes lol

https://blog.logrocket.com/flutter-web-app-node-js/

tsitixe
  • 1,851
  • 3
  • 14
  • 24
  • 1
    So what do we do when you use Firebase as the backend and still get the error?! – SIMMORSAL Jun 03 '21 at 20:30
  • @SIMMORSAL i'm not pretty sure of what your Firebase-related error is. I've not gotten myself that far away combining node js engine and Firebase products. But if you've actually got through the error in a certain situation, then a new SO thread might be open with tags like flutter-web, cors, firebase, and firebase-, and would be grateful if you comment the new thread's link here [: – tsitixe Jun 04 '21 at 03:53
  • 1
    I figured out the problem https://stackoverflow.com/a/67830000/4457315 ... Thaanks anyways. – SIMMORSAL Jun 04 '21 at 23:24
6

If you run a Spring Boot server, add "@CrossOrigin" to your Controller or to your service method.

@CrossOrigin
@PostMapping(path="/upload")
public @ResponseBody ResponseEntity<Void> upload(@RequestBody Object object) {
    // ...
}

I know the question explicitly asked for a solution "with dart code" only, but I was not able to fix the exception with dart code (for example by changing the header).

Bobin
  • 278
  • 5
  • 15
6

The disabling web security approaches work well in development, but probably not so well in production. An approach that worked for me in production dart code involves avoiding the pre-flight CORS check entirely by keeping the web request simple. In my case this meant changing the request header to contain:

'Content-Type': 'text/plain'

Even though I'm actually sending json, setting it to text/plain avoids the pre-flight CORS check. The lambda function I'm calling didn't support pre-flight OPTIONS requests.

Here's some info on other ways to keep a request simple and avoid a pre-flight request

Tim R
  • 71
  • 2
  • 6
6

After hours of testing, the following works perfectly for me.

Add the following to the PHP file:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");

This allow the correct connection with the HTTP GET POST with no issue from flutter for me.

I discovered this in the following discussion:

XMLHttpRequest error Flutter

CNK
  • 567
  • 5
  • 6
5

https://docs.flutter.dev/development/platform-integration/web-images

flutter run -d chrome --web-renderer html
flutter build web --web-renderer html
justcodepy
  • 59
  • 1
  • 3
  • 3
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 19 '22 at 11:08
  • n production mode, not even in chrome. It will work only if your site is hosted in firebase hosting. – Thiago Silva Jul 06 '23 at 11:52
4

This official solution worked for me on Chrome only (Source). But I had to run it first every time.

flutter run -d chrome --web-renderer html

And disabling web security also worked (Source). But the browsers will show a warning banner.

But In case you are running on a different browser than Chrome (e.g. Edge) and you want to keep 'web security' enabled. You can change the default web renderer in settings in VS Code

File ==> Preferences ==> Settings ==> Enter 'Flutter Web' in the Search Bar ==> Set the default web renderer to html

3

Update:

I recommend to use User Rebo's answer. It is now possible to pass --disable-web-security as a browser flag to run & drive commands!


Original outdated answer:


Alternative solution for MacOS & Android Studio (without modifying Flutter source)

We use a similar approach as Osman Tuzcu. Instead of modifying the Flutter source code, we add the --disable-web-security argument in a shell script and just forward all other arguments that were set by Flutter. It might look overly complicated but it takes just a minute and there is no need to repeat it for every Flutter version.

1. Run this in your terminal

echo '#!/bin/zsh
# See also https://stackoverflow.com/a/31150244/410996
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
set -e ; /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --test-type --disable-web-security "$@" ; set +e &
PID=$!
wait $PID
trap - SIGINT SIGTERM EXIT
wait $PID
' > ~/chrome_launcher
chmod 755 ~/chrome_launcher

This adds a chrome_launcher script to your user folder and marks it executable.

2. Add this line to your .zshrc (or .bashrc etc.):

export CHROME_EXECUTABLE=~/chrome_launcher

3. Restart Android Studio

If a simple restart does not work, use Invalidate Caches / Restart in Android Studio to force loading of changes.

Notes

The script also adds the --test-type flag to suppress the ugly warning about the disabled security features. Be aware that this option might also suppress other error messages! The CHROME_EXECUTABLE takes only the path to an executable file it is not possible to set arguments there. Without trapping exit signals and killing the process group, the Google Chrome instance was not killed when you hit the Stop Button in Android Studio.

RobDil
  • 4,036
  • 43
  • 52
  • Does it work on released web build of flutter? – scienticious Mar 02 '22 at 19:42
  • For your production app you will have to set appropriate CORS headers on your files. – RobDil Mar 02 '22 at 21:26
  • This won't work for production environments...the given snippet disables CORS only for the chrome browser on your pc for testing purposes, but if you publish your webpage, your client will have CORS activated (as it should be). – Ramiro G.M. Dec 12 '22 at 21:26
  • Of course it does not! (see my comment above) It would be dangerous if anyone could just disable important browser security features from their website... – RobDil Dec 13 '22 at 22:34
3

I am getting the same error with php api so i add the php code these lines ;

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
Noman Uddin
  • 182
  • 9
3

If you are using FVM, I suggest to use flutter_cors package

dart pub global activate flutter_cors
fluttercors --disable

If you face

zsh: command not found: fluttercors

You need to add it to PATH. In my case, I'm using zsh, I add it to .zshrc by

vim ~/.zshrc

Press I to start editing and paste export PATH="$PATH":"$HOME/.pub-cache/bin" to the top of the file

enter image description here

Then press ESC and type :wq to save the .zshrc file. Now you're good to go

enter image description here

Now, just need to run your flutter web normally. It will trigger Chrome without CORS.

ANDYNVT
  • 531
  • 4
  • 19
  • This worked for me. However, it's worth noting that I had to pass the `--flutter-path=/root/dir/of/flutter/version` to `fluttercors` . Otherwise, at least under some conditions (mainly, if you have multiple versions are have not set some ENV vars), you'll get this error: > $ fluttercors --disable ``` Unhandled exception: FileSystemException: Cannot open file, path = './packages/flutter_tools/lib/src/web/chrome.dart' (OS Error: No such file or directory, errno = 2) ``` – Jesse James Portnoy Apr 06 '23 at 17:01
  • From the devs: Note This script only disables CORS checks for local testing, and will not help with CORS issues in production. Do not ask for help with production CORS issues as that is outside the scope of this project. – Thiago Silva Jul 06 '23 at 11:57
1

I think you may not doing this in right way. The cors headers should be added in HTTP response header while you added them in you reuqest header obviously.

for more information check out the documentation https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#what_requests_use_cors

ostcollect
  • 11
  • 1
1

The below solution is great if you are only communicating with a local NodeJS server.

  1. Install NodeJS
  2. Create a basic NodeJS express project
    • Create a folder to put you NodeJS project in
      • ex: C:\node_project\
      • in PowerShell run: npm init in the folder
        • fill in your desired values
        • entry point: must be app.js for this example to work
      • in PowerShell run: npm install express in the folder
      • create a app.js file in the folder
// init express
const express = require("express");
const app = express();

// set the path to the web build folder
app.use(express.static("C:/Users/your_username/path_to_flutter_app/build/web"));

const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
    console.log(`Server listening on port ${PORT}...`);
});
  • The value "C:/Users/your_username/path_to_flutter_app/build/web" must be changed to the web build folder in your flutter app.
  • The app can be accessed through your browser once the app is built, the node server is running, and the browser is at the correct address
    • Build the app
      • open PowerShell and navigate to the flutter project's root ex: C:/Users/your_username/path_to_flutter_app/
      • run flutter build web
    • turn on the node server
      • open PowerShell and navigate to the NodeJS server folder ex: C:\node_project\
      • run: node app.js
    • Open in your browser
      • Enter http://localhost:8080/ into the browser

Note that everytime you change your flutter app's dart code you will need to re-run flutter build web

CatTrain
  • 214
  • 2
  • 5
1

Wrong Server on Target Port

I feel silly for even admitting this, but I had some other local server running on the targeted port. I've no clue why the server seemed to boot on the same port, or why the iOS app seemed to work, but now that I'm hitting the actual server it's working fine.

I was also getting some 404's mixed in, but originally thought that was due to the CORs error.

Maybe someone else has this same issue and this helps them.

CTS_AE
  • 12,987
  • 8
  • 62
  • 63
1

In my case, The problem was in laravel backend code which did not support CORS, So I added the CORS into backend project then it worked successfully in test and live.

Ahmed Sa'eed
  • 173
  • 2
  • 3
  • 12
1

The 5th step of Osmans answer should be to add the option

'--disable-site-isolation-trials',

Only this works for me.

Chrome version 106.0.5249.119

Filip
  • 39
  • 4
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33005128) – teik Oct 28 '22 at 08:58
1

It Worked With Me By The Following Code : in conn.php file put like this :

<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");

$connect = new mysqli("localhost","db_user","db_password","db_name");

if($connect){
     
}else{
    echo "Connection Failed";
    exit();
}
1

For me none of the solutions above worked on production as it was expected. Altough there is one solution I can suggest which uses CORS proxy to avoid CORS issues on flutter web on production. You can find CORS proxies on this website.

Basically you bypass all the unnecessary headers which your browser appends to your requests, so you may not encounter the same CORS issues when making request to another API. Hope it helps!

Havlik Miki
  • 41
  • 1
  • 5
0

This is a CORS (cross-origin resource sharing) issue and you just need to enable the CORS request from your server-side.

In my case it is Asp.Net MVC Web API and adding below code to Application_BeginRequest at Global.asax worked for me:

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:7777/");

if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
    //These headers are handling the "pre-flight" OPTIONS call sent by the browser
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET");
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "content-type");
    HttpContext.Current.Response.End();
}

Use desired urls , Methods and Headers

Also There is no need to change anything in Web.config

Ali Izadyar
  • 140
  • 1
  • 2
  • 13
0

If anyone looking for an equivalent of the accepted answer (Osman's) when working with dart web (webdev), here's what worked for me on Dart 2.17.6 (a bit more complex but in case you needed a quick fix, it might be handful).

  1. Find webdev executable (this helps) then you see something like this:

webdev

The snapshot file (generated if not exist, as you see) is executed when you want to run app in browser. It contains the code that dart runs when launching chrome (using browser_launcher dart package).

  1. Backup and remove the snapshot file (location in the screenshot above) so it can be regenerated in next run.

  2. Locate browser_launcher package in your pub cache (also you might find location of browser_launcher by searching in the snapshot file) and edit lib\src\chrome.dart, find '--disable-extensions' and add '--disable-web-security'.

  3. Run your app and remove the backup created in step 2.

navid
  • 1,022
  • 9
  • 20
0

If you are working with django in the side of the service, you can configure CORS with 'corsheaders', in this link you can find whole the documentation to setup your back end and recognice your requests.

https://pypi.org/project/django-cors-headers/

0
  1. Go to flutter\bin\cache and remove a file named: flutter_tools.stamp
  2. Go to flutter\packages\flutter_tools\lib\src\web and open the file chrome.dart.
  3. Find '--disable-extensions'
  4. Add '--disable-web-security'
vishnu reji
  • 193
  • 2
  • 11
0

For development debugging purpose below solution worked for me (WIll NOT WORK FOR PRODUCTION)

  1. Delete flutter_tools.stamp file exists in below location flutter\bin\cache

  2. Open chrome.dart which exists in below location flutter\packages\flutter_tools\lib\src\web

  3. Find '--disable-extensions' line & add below line after that with comma '--disable-web-security',

  4. Go to your proj & hit flutter upgrade & pub get (Tools>Flutter>) in android studio

shashank J
  • 67
  • 7
0

Personally, I needed to run my flutter app in production as a chrome web app. The ultimate solution was to create a cloud function that routed the API call.

You can explore Firebase or whatever backend service you use to solve this.

Legend
  • 21
  • 4
-3

USE THIS

http.post('https://cors-anywhere.herokuapp.com/https://kapi.kakao.com/v1/payment/ready', ... )

It's work fine for me !!

from (cors-anywhere.herokuapp.com)

Hmida
  • 55
  • 2