如何解决颤振网页应用程序错误只有省道代码?

CORS 错误似乎是网络领域的一个众所周知的问题。但是我第一次尝试上网,我面临着严重的错误。

下面的代码在 iOS 设备上运行时在应用程序版本中运行良好,但是当我在 Chrome 上通过 beta 通道的 web 调试测试同样的代码时,它遇到了 CORS 错误。

其他关于堆栈溢出的答案解释了如何使用其项目的服务器端文件解决 CORS 问题。但我完全不知道什么是服务器的东西,也不知道如何处理他们的答案。来自 Chrome 控制台的错误消息如下

【由原始 https://kapi.kakao.com/v1/payment/ready“ http://localhost:52700”访问 XMLhttpRequest 已被 CORS 策略阻止: 对飞行前请求的响应没有通过访问控制检查: 请求资源上没有“访问控制-允许-原始”头文件。】

因此,我想要做的是解决上述“访问控制-允许-起源头”问题只与省道代码!下面的代码是我用 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);
},

尽管我实际上有其他大多数答案推荐的标题 "Access-Control-Allow-Origin": "*",Chrome 控制台还是打印了相同的错误消息。奇怪的是,同样的代码在 mobileApp 版本中成功请求了。所以我认为这是唯一的问题与扑动网络版本。

希望有人可以解决这个问题,并建议只-省道代码来解决我的主要问题。省道! !感谢您阅读[ :

108246 次浏览

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

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'

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/

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).

Update

I recommend to use Rexios's answer. His package makes it very convenient to modify the Flutter source code.


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.

Using Osman Tuzcu's answer, I created flutter_cors to make the process easier.

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

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

flutter run -d chrome --web-renderer html
flutter build web --web-renderer html

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

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.

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

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.

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

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

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.

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.

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");

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

Hi Your error states about the headers that is not present. So it could be that your server is already setup for cors. My error is as follows. Error: XMLHttpRequest error. C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patc h/core_patch.dart 963:28 get current packages/http/src/browser_client.dart 69:22 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1685:54 runUnary C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 147:18 handleValue C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 766:44 handleValueCallback C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 795:13 _propagateToListeners C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 557:7 [_complete] C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream_pipe.dart 61:11 _cancelAndValue C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream.dart 1530:7 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ ddc_runtime/operations.dart 334:14 _checkAndCall C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ ddc_runtime/operations.dart 339:39 dcall C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/html/dart2js/html_dart2js.dart 37309:58

at Object.createErrorWithStack (http://localhost:1681/dart_sdk.js:5093:12)
at Error._throw (http://localhost:1681/dart_sdk.js:20399:18)
at Error.throwWithStackTrace (http://localhost:1681/dart_sdk.js:20396:18)
at async._AsyncCallbackEntry.new.callback (http://localhost:1681/dart_sdk.js:40921:18)
at Object._microtaskLoop (http://localhost:1681/dart_sdk.js:40778:13)
at _startMicrotaskLoop (http://localhost:1681/dart_sdk.js:40784:13)
at http://localhost:1681/dart_sdk.js:36261:9

Yes it looks like it is a well known issue. But all the answers I get on the web is or only going to work in debug or do not work at all. As far as I can figure it out you have to enable it on your server side. Do anyone know how to enable it on server side so production web app can work? Running apache with direct admin on it. Not locally on pc but online. Not looking for a temporary solution but looking for a solution that will work when in production. Thank you