杰瑞科技汇

Python postMessage如何实现跨域通信?

Of course! The term "Python postmessage" can refer to two main things, as it's not a single built-in Python function. It depends on the context:

Python postMessage如何实现跨域通信?-图1
(图片来源网络,侵删)
  1. Posting a message from a Python web server to a web browser (using the window.postMessage API).
  2. Sending a message between different Python processes or threads (using a queue or messaging library).

Let's break down both scenarios with clear examples.


Scenario 1: Python Web Server to Browser Communication (The postMessage API)

This is the most common interpretation. window.postMessage is a web API that allows a script on one page to send a cross-origin message to another window. A Python web server (like Flask or Django) can't call postMessage directly, but it can send data to the browser, which can then use JavaScript to call postMessage.

The typical flow is:

  1. Browser (Page A): Opens a new window/tab (Page B).
  2. Python Server: Serves the HTML/JS for both pages.
  3. Python Server: Receives some data (e.g., from a user action).
  4. Python Server: Sends this data back to Page A (or Page B) via a WebSocket or an AJAX request.
  5. Browser (Page A/JS): Receives the data and uses window.postMessage() to send it securely to Page B.

Key Concepts for postMessage

  • targetWindow.postMessage(message, targetOrigin):
    • message: The data you want to send. It's best to use JSON.stringify() to send objects.
    • targetOrigin: The origin of the window you want to send the message to (e.g., https://example.com). This is a critical security feature to prevent your message from being sent to a malicious site. Use with extreme caution.
  • Listening for Messages: The target window must listen for the message event: window.addEventListener('message', handlerFunction).
  • Security: Always check the event.origin in your message handler to ensure the message is coming from a trusted source.

Example: Flask Server + JavaScript

Let's build a simple example where one page opens another and sends it a message.

Python postMessage如何实现跨域通信?-图2
(图片来源网络,侵删)

Project Structure:

/my_project
|-- app.py
|-- templates/
|   |-- index.html      # The sender page
|   |-- message_target.html # The receiver page

The Python Server (app.py)

This Flask server will serve the two HTML pages. It doesn't do much in this simple example, but it's the foundation.

# app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
    """Serves the page that will send the message."""
    return render_template('index.html')
@app.route('/target')
def target():
    """Serves the page that will receive the message."""
    return render_template('message_target.html')
if __name__ == '__main__':
    # Run on port 5000, accessible from other machines on the network
    app.run(host='0.0.0.0', port=5000, debug=True)

The Sender Page (templates/index.html)

This page has a button. When clicked, it opens the target page and then sends a message to it.

<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">PostMessage Sender</title>
</head>
<body>
    <h1>PostMessage Sender</h1>
    <button id="sendMessageBtn">Send Message to Target Window</button>
    <p id="status"></p>
    <script>
        const sendBtn = document.getElementById('sendMessageBtn');
        const statusEl = document.getElementById('status');
        let targetWindow = null;
        sendBtn.addEventListener('click', () => {
            // 1. Open the target window
            // IMPORTANT: Use the same port and host your server is running on
            targetWindow = window.open('http://127.0.0.1:5000/target', '_blank');
            // 2. Prepare the message data
            const messageData = {
                user: 'Alice',
                action: 'login',
                timestamp: new Date().toISOString()
            };
            // 3. Send the message after a short delay to ensure the target window is loaded
            setTimeout(() => {
                if (targetWindow) {
                    // Use the specific target origin for security!
                    targetWindow.postMessage(messageData, 'http://127.0.0.1:5000');
                    statusEl.textContent = 'Message sent!';
                } else {
                    statusEl.textContent = 'Failed to open target window.';
                }
            }, 1000);
        });
    </script>
</body>
</html>

The Receiver Page (templates/message_target.html)

This page listens for incoming messages and displays them.

<!-- templates/message_target.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">PostMessage Target</title>
</head>
<body>
    <h1>PostMessage Target</h1>
    <p id="messageLog">Waiting for a message...</p>
    <script>
        const messageLog = document.getElementById('messageLog');
        // Listen for messages from other windows
        window.addEventListener('message', (event) => {
            // --- SECURITY CHECK ---
            // Always verify the origin of the sender!
            // In this case, we only trust messages from our own server.
            if (event.origin !== 'http://127.0.0.1:5000') {
                console.error('Received message from untrusted origin:', event.origin);
                return;
            }
            // --- END SECURITY CHECK ---
            console.log('Message received:', event);
            // The data is in event.data
            const data = event.data;
            messageLog.innerHTML = `
                <strong>Received a message from ${event.origin}:</strong><br>
                User: ${data.user}<br>
                Action: ${data.action}<br>
                Timestamp: ${data.timestamp}
            `;
        });
    </script>
</body>
</html>

How to Run This Example:

  1. Install Flask: pip install Flask
  2. Save the files as shown in the project structure.
  3. Run the server: python app.py
  4. Open your web browser and go to http://127.0.0.1:5000.
  5. Click the "Send Message..." button. A new tab will open.
  6. In the new tab, you will see the message appear after a second.

Scenario 2: Inter-Process Communication (IPC) in Python

If you mean sending messages between different Python scripts or threads, you don't use postMessage. Instead, you use standard Python concurrency and networking tools.

Here are the most common methods:

Using queue.Queue (For Threads)

A queue is the standard way for threads to communicate safely in Python.

producer.py (Producer Thread)

import queue
import threading
import time
# A shared queue
data_queue = queue.Queue()
def producer():
    """Produces data and puts it into the queue."""
    for i in range(5):
        message = f"Message {i} from producer"
        print(f"Producer: Putting '{message}' into the queue.")
        data_queue.put(message)
        time.sleep(1)
    print("Producer: Finished. Sending None to signal end.")
    data_queue.put(None) # Signal the consumer to stop
def consumer():
    """Consumes data from the queue."""
    while True:
        message = data_queue.get() # Blocks until an item is available
        if message is None: # Check for the signal to stop
            print("Consumer: Received None. Exiting.")
            break
        print(f"Consumer: Got '{message}'. Processing...")
        # Simulate work
        time.sleep(2)
        print(f"Consumer: Finished processing '{message}'.")
        data_queue.task_done() # Signal that the item is processed
# Start the consumer thread
consumer_thread = threading.Thread(target=consumer)
consumer_thread.start()
# Start the producer (which runs in the main thread here)
producer()
# Wait for the consumer thread to finish
consumer_thread.join()
print("All done.")

Using Sockets (For Processes or Networked Machines)

Sockets allow you to communicate between completely separate processes, even on different computers.

server.py (Simple Echo Server)

import socket
HOST = '127.0.0.1'  # Standard loopback interface address (localhost)
PORT = 65432        # Port to listen on (non-privileged ports are > 1023)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    print(f"Server listening on {HOST}:{PORT}")
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            print(f"Server received: {data.decode('utf-8')}")
            conn.sendall(data) # Echo the message back
print("Server closed.")

client.py (Simple Client)

import socket
HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 65432        # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    message = "Hello from Python client!"
    print(f"Client sending: {message}")
    s.sendall(message.encode('utf-8'))
    data = s.recv(1024)
print(f"Client received: {data.decode('utf-8')}")

To run this:

  1. Start the server in one terminal: python server.py
  2. Run the client in another terminal: python client.py

Summary: Which one do you need?

Context Method / Technology Key Libraries/Tools
Python sends data to a web browser JavaScript window.postMessage API Flask/Django, JavaScript
Python sends data to another Python script on the same machine Sockets (for processes), multiprocessing.Queue (for processes), queue.Queue (for threads) socket, multiprocessing, queue
Python sends data to another Python script on a different machine Sockets socket
Python sends data to a different application (e.g., a microservice) REST API, gRPC, Message Queues (RabbitMQ, Kafka) requests, grpc, pika, kafka-python
分享:
扫描分享到社交APP
上一篇
下一篇