플러터 웹의 XMLHttpRequest 오류 [CORS AWS API 게이트웨이 사용]
참고: 이것은 Flower와 아무런 관련이 없으며 API 게이트웨이를 Lambda Proxy로 설정했다는 사실과도 모든 관련이 없음이 밝혀졌습니다
Flutter 웹 애플리케이션에서 API 엔드포인트를 치려고 하는데, 매번 오류가 발생하고 다음 오류가 발생합니다.
센서 데이터 가져오기 오류: DioError [DioErrorType].응답]: XMLHttpRequest 오류입니다.
나는 SO(like 및 )에 대해 이 문제를 논의하는 몇 가지 질문이 있다는 것을 알고 있으며 해결책은 서버 측에서 CORS 지원을 활성화하는 것인 것 같습니다. 저는 AWS API 게이트웨이를 사용하여 API를 구축하고 있으며, 제 API에서 CORS 지원을 활성화하기 위한 지침을 따랐다. 여기 API 게이트웨이 콘솔에서 CORS 설정이 있습니다.
"액세스-제어-허용 헤더"의 텍스트는
'내용 유형, X-Amz-날짜,'권한 부여, X-Api-Key, X-Amz-Security-Token'
API 게이트웨이에서 CORS를 활성화하는 것은 도움이 되지 않는 것처럼 보였지만, API를 누르려고 할 때 여전히 플러터 웹 앱에서 같은 오류가 발생하고 있다.
재미있는 것은 내가 크롬에서 API를 치면 API가 완벽하게 잘 작동한다는 것이다(즉, 브라우저에 API URL을 붙여넣고 엔터를 누른다). 플러터 웹 앱에서 API를 치려고 할 때만 실패합니다.
질문:. API 게이트웨이에서 CORS 지원을 활성화하여 플러터 웹 앱이 API를 사용할 수 있도록 하려면 어떻게 해야 합니까?
이것은 나에게 효과가 있었다, 나는 람다 함수에 아래 헤더를 추가했다
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*", // Required for CORS support to work
"Access-Control-Allow-Credentials": true, // Required for cookies, authorization headers with HTTPS
"Access-Control-Allow-Headers": "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale",
"Access-Control-Allow-Methods": "POST, OPTIONS"
},
body: JSON.stringify(item)
};
제 서버가 nginx를 사용하고 있어서 제 API 서버의 사이트 지원 구성 파일의 서버 블록에 다음 두 줄을 추가하여 문제를 해결했습니다:
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, HEAD";
내 앱은 사용만 하기 때문에 상황에 따라 다른 방법을 추가해야 할 수도 있습니다.
참고 항목:
나는 백엔드를 위해 Nodejs를 사용하고 있습니다. Dio에서 포스트 요청을 보냈을 때 다음 오류가 있었습니다:
플러터가 localhost:5500에서 실행되고 nodejs 서버가 localhost:3000에서 실행된다고 가정하자. 따라서 서로 다른 포트에서 실행되고 있으므로 브라우저가 요청을 처리하지 못한다. 그것이 바로 이러한 문제를 해결하기 위해 CORS 또는 프록시를 사용하는 것입니다.
이는 주로 브라우저와 관련된 문제임을 기억하십시오. 만약 당신이 우체부를 이용하고 같은 요청을 보낸다면, 당신은 모든 것이 효과가 있다는 것을 알게 될 것입니다.
CORS라는 NPM 패키지를 설치했습니다.
npm i cors
그럼, 그걸 사용하기 시작해봐요...
const cors = require("cors");
app.use(cors());
그렇게 하는 것만으로도 너의 실수는 해결될 것이다. 그리고 더 이상 추가할 필요는 없습니다.
호스트 계정에서 CORS를 활성화하려면 CORS in을 활성화합니다. 호스팅 계정의 파일에 다음 행을 추가하여 활성화할 수 있습니다.
<IfModule mod_headers. ...
Header set Access-Control-Allow-Origin "*"
</IfModule>
이것은 당신의 백엔드와 프론트엔드 모두의 문제입니다. 인증 헤더를 추가하는 동안 오류가 발생했습니다. 당신은 두 가지 일을 해야 합니다.
- 플러터 프론트엔드에서 내용 유형을 json으로 지정합니다.
- 노드 백엔드에 CORS를 허용합니다.
프론트엔드
var request = await http.post(
Uri.parse(url),
headers: {
"auth-token": idToken, // whatever headers you need(I add auth)
"content-type": "application/json" // Specify content-type as JSON to prevent empty response body
},
body: jsonEncode(<String, String>{
'name': name,
'email': email,
})
백엔드
const cors = require('cors'); //Setup CORS
app.use(cors({
origin: '*',
allowedHeaders: 'X-Requested-With, Content-Type, auth-token',
})); //Add authentication token header
app.use("/api/user", authRoute); // Flutter Web calls this endpoint
서버 쪽에 접근할 수 없다면 역방향 프록시를 설정하는 것이 좋습니다. 도커 컨테이너에서 실행되는 최소한의 구성으로 annx proxy를 사용했습니다.
도커- compose.yml:
version : '3'
services :
nginx:
image: nginx:latest
container_name: nginx_container
ports:
- 3000:3000
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
nginx.conf:
events {
}
http {
server {
listen 3000;
location / {
proxy_pass http://original_address_and_port/;
}
}
}
그러면 http://localhost:3000을 API base로 사용하여 개발하면 nginx에서 원래 주소와 포트로 요청을 보냅니다.
다음 단계를 사용하여 문제를 해결할 수 있습니다:
나는 백엔드를 위해 Nodejs를 사용하고 있습니다. HTTP에서 게시 요청을 보냈을 때 "XMLHtpRequest 오류"라는 오류가 있었습니다.
1): 노드 종속성에 설치
npm 코르스를 설치하다
2단계: 코드 라인
3단계 다음에 다음 단계로 ip를 추가한다
4단계 앱/안드로이드 스튜디오에 추가
이것이 나에게 효과가 있었다:
Step 1: npm install cors
코르스 설치 후 정의
Step 2: const cors = require('cors')
미들웨어를 추가하여 코르를 활성화합니다
Step 3: app.use(cors())
https 끝점이 있는 것을 잊었습니다
이 "XMLHtpRequest 오류"에 3시간이 걸렸습니다...
아마도 많은 개발자들에게 명백할 것이지만 내 상황에서 나는 https에서 http 엔드포인트로 CORS 요청을 하고 있었다.
작동하려면 다른 답변 위에 (CORS 활성화, 오리진 * 허용, 요청에 머리글 추가).
작동하게 만든 전체 코드(nginx, 노드 익스프레스 서버 및 플러터 웹 사용):
서버
응징크스
nginx config 파일에서 다음 행을 추가합니다:
location / {
#ALLOW CORS#
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
#END OF ALLOW CORS#
try_files $uri $uri/ =404;
백엔드
index.js
const app = express()
const cors = require('cors');
app.use(cors());
// usual stuff
(cors를 설치해야 합니다: 백엔드 디렉토리에)
server.js
const app = require('./index')
const fs = require('fs')
const https = require('https')
const port = process.env.PORT || 3000;
var options = {
key: fs.readFileSync('./certs/privkey.pem'),
cert: fs.readFileSync('./certs/fullchain.pem'),
};
var server = https.createServer(options, app).listen(port, function(){
console.log("Express server listening on port " + port);
});
클라이언트 앱을 플러터합니다:
Future<String> testRequest() async {
Uri uri =
Uri(scheme: 'https', port: 3000, host: 'mywebsite.com', path: 'folder'); // to reach this endpoint: 'https://mywebsite.com:3000/folder'
var headers = {
"Access-Control-Allow-Origin": "*",
'Content-Type': 'application/json',
'Accept': '*/*'
};
try {
http.Response response = await http.get(uri, headers: headers);
return response.body;
} catch (e) {
return inspect(e).toString();
}
}
NB: 엔드포인트에 대한 사용자 지정 경로가 있습니다
그래서 백엔드에 인증서와 https를 추가한 후에 마침내 작동하고 있었다.
해라
floter\bin\cache로 이동하고 floter_tools.stamp 파일을 제거합니다
floter\packages\flutter_tools\lib\src\web open file chrome.dart로 이동하여 편집 '--disable-web-security' 줄 옆에 '--disable-web-security'를 추가합니다
리쿤의 대답은 통하지 않는다. --disable-web-security가 지원되지 않는다고 합니다.
이것이 나의 흥분된 의사 소견이다:
• Flutter version 3.13.8 on
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 6c4930c4ac (12 days ago), 2023-10-18 10:57:55 -0500
• Engine revision 767d8c75e8
• Dart version 3.1.4
• DevTools version 2.25.0
'개발하자' 카테고리의 다른 글
호스트를 Kubernetes의 서비스 경로로 리디렉션할 수 있습니까? (0) | 2023.10.31 |
---|---|
펄럭이는 지속적인 티커 (1) | 2023.10.31 |
테라폼으로 aws에 도메인을 등록할 수 있나요? (1) | 2023.10.30 |
Terraform CIDR 블록 변수 유효성 검사 (0) | 2023.10.29 |
적용 변경 없이 Terraform 상태를 업데이트하는 방법 (0) | 2023.10.28 |