bounty还有6天到期。回答此问题可获得+100声望奖励。brownfox希望引起更多注意这个问题:我期望Web应用程序版本能够像调试Linux版本一样与服务器通信以发送和接收消息,以便我可以将其部署在某个地方。
我正在努力学习Webdev,作为我第一个项目的一部分,我构建了一个简单的聊天机器人应用程序。该应用程序由一个Python-Flask后端(运行在localhost/5000上)和一个Flutter应用程序前端组成。Flutter应用程序接受我们的输入,将其发送到Flask服务器,并将响应打印给我们。
当我在本地以调试模式运行应用程序时,它按预期正常工作。但是,当我使用
flutter build web
字符串
然后尝试通过创建Python服务器从/build/web/运行应用程序
python -m http.server 8081
型
出现问题,Web应用程序正在浏览器中启动:但是,现在它不能从运行在localhost/5000的服务器发送和接收消息。我得到一个错误:x1c 0d1x的数据
flutter.js:368 Exception while loading service worker: Error: Service Worker API unavailable.
The current context is NOT secure.
Read more: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts
at FlutterServiceWorkerLoader.loadServiceWorker (flutter.js:130:11)
at FlutterLoader.loadEntrypoint (flutter.js:366:33)
at (index):46:23
(anonymous) @ flutter.js:368
0.0.0.0/:1 Access to XMLHttpRequest at 'http://127.0.0.1:5000/api/chat' from
origin 'http://0.0.0.0:8081' has been blocked by CORS policy:
The request client is not a secure context and the resource is in more-private address space `local`.
main.dart.js:6506 Uncaught Error
at Object.alx (main.dart.js:6573:24)
at TE.$1 (main.dart.js:73160:53)
at abl.adR (main.dart.js:36153:34)
at abl.DP (main.dart.js:36155:21)
at a95.$0 (main.dart.js:35896:11)
at Object.r4 (main.dart.js:5825:40)
at az.mx (main.dart.js:35827:3)
at Object.ayw (main.dart.js:5908:8)
at a4N.$1 (main.dart.js:35938:9)
at a8N.$1 (main.dart.js:39265:21)
127.0.0.1:5000/api/chat:1 Failed to load resource: net::ERR_FAILED
型
它基本上说,由于CORS安全策略,我无法从源'http://0.0.0.0:8081'与'http://127.0.0.1:5000/api/chat'通信。当我尝试运行相同的Web应用程序时,通过禁用浏览器安全性,我不再收到此错误,Web应用程序能够与服务器通信。
chromium-browser --disable-web-security
型
如何在不牺牲安全性的情况下解决这个问题?我希望在修复此问题后在线部署应用程序。
为什么会这样?下面是Github repo的链接,其中包含完整的代码:https://github.com/sri-gpt/simple_chat_app的
我正在使用:
- Ubuntu版本22.04 LTS
- Flutter3.13.0-0.2.pre
- dart 3.1.0
- DevTools 2.25.0
- flask 2.3.2
- Flask-Cors 4.0.0
- Python 3.9
示例代码:Python Flask服务器
from flask import Flask, request, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route('/')
def home():
return 'ServerDEployed'
@app.route('/about')
def about():
return 'About'
@app.route('/api/chat', methods=['POST'])
def chat():
data = request.get_json()
input_text = data.get('input_text')
return jsonify({"response_mal": str("response_recived:")+str(input_text)})
if __name__ == '__main__':
app.run(debug=True)
型
以下是Flutter应用程序的主.dart文件:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(const ChatApp());
}
class ChatApp extends StatelessWidget {
const ChatApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Chat_app',
theme: ThemeData(
primarySwatch: Colors.indigo, // Change primary color
fontFamily: 'Montserrat', // Add custom font (Montserrat can be replaced with your preferred font)
),
home: const MyHomePage(title: 'Chat_app'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _messages = <Map<String, dynamic>>[];
final _controller = TextEditingController();
final double fontText = 24.0; // <-- This is your pseudo variable for font size
Future<void> _sendText() async {
if (_controller.text.isEmpty) {
return;
}
setState(() {
_messages.add({"text": _controller.text, "type": "outgoing"});
});
final url = Uri.parse('http://127.0.0.1:5000/api/chat');
final response = await http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'input_text': _controller.text,
}),
);
if (response.statusCode == 200) {
final Map<String, dynamic> data = jsonDecode(response.body);
setState(() {
_messages.add({"text": data["response_mal"], "type": "incoming"});
_controller.text = "";
});
} else {
throw Exception('Failed to send message');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title, style: TextStyle(fontSize: fontText)), // <-- Apply font size here.
),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: _messages.length,
itemBuilder: (_, int index) {
final message = _messages[index];
final isOutgoing = message["type"] == "outgoing";
return Container(
margin: const EdgeInsets.symmetric(vertical: 5),
padding: const EdgeInsets.all(10),
alignment:
isOutgoing ? Alignment.centerRight : Alignment.centerLeft,
child: Text(
message["text"],
style: TextStyle(fontSize: fontText), // <-- Apply font size here.
),
decoration: BoxDecoration(
color: isOutgoing ? Colors.orange[100] : Colors.blue[100],
borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 5,
offset: Offset(0, 2),
),
],
),
);
},
),
),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.all(8.0),
child: TextField(
controller: _controller,
onSubmitted: (_) => _sendText(),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Enter your message',
),
style: TextStyle(fontSize: fontText), // <-- Apply font size here.
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: ElevatedButton( // Change the send button to ElevatedButton
onPressed: _sendText,
child: Icon(Icons.send),
),
),
],
),
],
),
);
}
}
型
1条答案
按热度按时间ryevplcw1#
然而,当我通过禁用Web安全性
$chromium-browser --disable-web-security
来运行Chromium浏览器时,应用程序工作正常。所以这似乎是由某些CORS安全策略引起的。如何在不牺牲安全性的情况下解决这个问题?
在调试模式下运行应用时,应用可能没有强制执行CORS规则。然而,当你构建和服务Web应用时,CORS会成为一个因素,特别是当你的Flutter应用和Flask后端来自不同的来源时(在这种情况下,是本地主机上的不同端口)。
尝试并包含
corydolphin/flask-cors
,这是一个用于处理跨域资源共享(CORS)的Flask扩展,使跨域 AJAX 成为可能。不使用默认的
CORS(app)
,您可以指定允许哪些源向Flask后端发出请求。例如:字符串
这将允许来自
http://0.0.0.0:8081
上托管的Flutter Web应用程序的请求,但拒绝其他请求。确保在运行时将Flask应用绑定到
0.0.0.0
,以便外部请求可以访问,而不仅仅是来自localhost
的请求。型
但是错误
Exception while loading service worker: Error: Service Worker API unavailable.
表明服务工作者在不安全的上下文(HTTP)上服务时存在问题。考虑使用HTTPS为您的Web应用程序提供服务。
您可以按照Harrison Kinsley中的“Securing your Flask website with SSL for HTTPS using Let's Encrypt”作为示例。