Solution for CORS Issues
When making Streamlit accessible externally in a WSL2 environment, CORS errors can sometimes occur. This can be resolved by using Nginx, running on WSL2, as a proxy server.
Nginx Configuration
# /etc/nginx/sites-available/streamlit
server {
listen 80;
server_name your-domain.example.com;
location / {
proxy_pass http://localhost:8501;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}
}
sudo ln -s /etc/nginx/sites-available/streamlit /etc/nginx/sites-enabled/
sudo systemctl restart nginx
Bidirectional Communication from Flutter to Python
Due to Streamlit's characteristic of re-executing scripts on each request, WebSockets are used for real-time communication. Bidirectional communication was achieved using Flask-SocketIO.
Flutter Side (Dart)
class FlutterStreamlitBridge {
final WebSocketChannel channel;
Future<void> sendCommand(String command) async {
channel.sink.add(json.encode({"type":"command","data":command}));
}
Stream<String> receiveResponse() {
return channel.stream.map((message) {
final data = json.decode(message);
return data['result'] as String;
});
}
}
Python Side (Flask-SocketIO)
from flask import Flask
from flask_socketio import SocketIO, emit
import threading
app = Flask(__name__)
socketio = SocketIO(app)
@socketio.on('command')
def handle_command(data):
def process():
command_data = data.get('data')
result = f"処理結果: {command_data}"
socketio.emit('response', {'result': result})
thread = threading.Thread(target=process)
thread.start()
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0', port=5000)
Streamlit and the WebSocket server must run on different ports.
Production Deployment via Cloudflare Tunnel
Cloudflare Tunnel was utilized for migrating from the development environment to production. Cloudflare Tunnel is available even with a Free plan.
cloudflared tunnel create streamlit-tunnel
cloudflared tunnel run streamlit-tunnel --url http://localhost:8501
An SSL/TLS encrypted communication path is established, and Cloudflare's DDoS protection features are automatically applied.
Security Design
To prevent unauthorized access, email domain validation has been implemented.
import sqlite3
class EmailValidator:
def __init__(self, db_path):
self.conn = sqlite3.connect(db_path)
self.cursor = self.conn.cursor()
def validate_domain(self, email):
domain = email.split('@')[-1]
self.cursor.execute(
"SELECT 1 FROM allowed_emails WHERE domain = ?", (domain,)
)
return self.cursor.fetchone() is not None
Other security measures implemented include:
- OTP attempt limit (lockout after 5 failed attempts)
- Cookie-based session management
- Encrypted token storage
Summary
This post explained practical methods for integrating Streamlit and Flutter in a WSL2 environment. Key points include resolving CORS issues, real-time communication with WebSockets, and secure deployment using Cloudflare Tunnel. By combining an Nginx proxy with a WebSocket server, seamless integration between the frontend and backend can be achieved.
This article was generated by Nemotron-Nano-9B-v2-Japanese and formatted/validated by Gemini 2.5 Flash.
Top comments (0)