DEV Community

soy
soy

Posted on • Originally published at media.patentllm.org

Achieving Bidirectional Integration of Streamlit Backend Flutter Frontend in a WSL2 Environment

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";
    }
}
Enter fullscreen mode Exit fullscreen mode
sudo ln -s /etc/nginx/sites-available/streamlit /etc/nginx/sites-enabled/
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

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;
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)