tech.sinayaka.com

pythonのwssサーバーにhtmlで接続する

2023-03-22
2026-07-08
5分
950語
Python python
目次

    最近pythonニンゲンなので、webアプリ(ブラウザ)でpythonを使えるように、 framework虚弱体質なのでFlaskなどに頼らない第一歩としてpythonでsecureなwebsocketを構築しました。

    • クライアント → HTML(Javascript)
    • サーバー → Apache + SSL + python

    サーバーの/var/www/wssにindex.htmlを設置し、 Javascriptで同一サーバー内のwebsocketへアクセスし、pythonを動かすのが目標です。

    diagram
    diagram

    クライアント

    クライアントはJavascriptで接続します。

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>WSS Client</title>
      </head>
      <body>
        <h1>WSS Client</h1>
        <form>
          <input type="text" id="message" placeholder="Enter message" />
          <button type="submit">Send</button>
        </form>
    
        <ul id="messages"></ul>
    
        <script>
          const ws = new WebSocket("wss://HOST:9001");
    
          ws.onopen = function () {
            console.log("Connected to WSS server");
          };
    
          ws.onmessage = function (event) {
            const messages = document.getElementById("messages");
            const li = document.createElement("li");
            li.appendChild(document.createTextNode(event.data));
            messages.appendChild(li);
          };
    
          document.querySelector("form").addEventListener("submit", function (event) {
            event.preventDefault();
            const input = document.getElementById("message");
            ws.send(input.value);
            input.value = "";
          });
        </script>
      </body>
    </html>

    サーバー(Apacheの設定)

    とりあえずhttp接続できるようにし、websocketサーバーへのproxyも記述しておきます。 websocketサーバーへの接続は、ホスト名とポート指定だけするので、 ProxyPassディレクティブの/wssはなんでも構わないのですが、/だけだとエラーになるので適当に。

    <VirtualHost *:80>
        ServerName HOST
        DocumentRoot /var/www/wss
        <Directory "/var/www/wss">
            Options -Indexes FollowSymLinks
            Order allow,deny
            Allow from all
        </Directory>
        ProxyPass /wss ws://localhost:9001/
    </VirtualHost>
    

    apacheを再読み込みし、設定したindex.htmlにブラウザからhttpアクセスできることを確認します。 この時、コンソールログにはwebsocket接続エラーが出ていると思います。

    http access
    http access

    確認できたらcertbotを利用してLet’s EncryptのSSL証明書を取得しておきます。
    certbotを使えばカンタンに無料でSSL証明書を作成でき、webサーバーの設定も行ってくれるので便利な時代です。

    secureなwebsocketserverではSSL証明書を読み込む必要がありますが、2通りの方法の選択を迫られます。

    一般ユーザーでwebsocketserverを動かし、/etc/letsencrypt/archive/HOST/cert1.pem/etc/letsencrypt/archive/HOST/privkey1.pemを一般ユーザーが読み込めるようにするか、rootでwebsocketserverを動かすのかです。
    一般ユーザーで動かす場合は下記のように証明書置き場を閲覧可能にし、privateキーファイルも閲覧可能にする必要があります。

    chmod 711 /etc/letsencrypt/archive
    chmod 644 /etc/letsencrypt/archive/HOST/privkey1.pem

    外部から接続できるようにポート設定もしておきます。

    -A INPUT -m state --state NEW -m tcp -p tcp --dport 9001 -j ACCEPT
    firewall-cmd --permanent --add-port=9001/tcp
    firewall-cmd --reload

    サーバー(pythonプログラム)

    とりあえず、接続テスト用のwebsocketserverの本体のプログラムです。どこに設置してもいいです。

    import asyncio
    import ssl
    import websockets
    
    # SSL/TLS証明書のパスを指定します
    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    ssl_context.load_cert_chain(
    '/etc/letsencrypt/archive/HOST/cert1.pem',
    '/etc/letsencrypt/archive/HOST/privkey1.pem')
    
    # WebSocket接続を処理するコルーチンです
    async def handler(websocket, path):
        async for message in websocket:
            # クライアントからのメッセージを受信します
            print(f"Received message: {message}")
    
            # クライアントにメッセージを送信します
            response = f"Response to {message}"
            await websocket.send(response)
            print(f"Sent message: {response}")
    
    # サーバーの起動とWebSocket接続の待機を行います
    async def main():
        async with websockets.serve(handler, 'HOST', 9001, ssl=ssl_context):
            print("Server started")
            await asyncio.Future()  # サーバーが終了しないように無限ループします
    
    # asyncioイベントループを開始します
    #asyncio.run(main()) # python3.7以上の場合はこの行だけでOK
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()
    

    接続テスト

    websocketserverを起動します。

    >>python wss.py
    Server started
    

    Webブラウザでアクセスします。これまでの設定が問題なければ、コンソールログには「Connected to WSS server」と出ているはずです。

    connect ok
    connect ok

    テキストボックスに「hello」と打ち込み「Send」すると、応答が返ってきます。

    response
    response

    サーバーのコンソールにもログが残っているはずです。

    >>python wss.py
    Server started
    Received message: hello
    Sent message: Response to hello

    おわりに

    webブラウザからpythonを使うためにwebsocketserverを構築してみました。 ここからseleniumでスクレイピングしたり、機械学習を利用するWebアプリを作ることができます。
    このままでは誰でも利用できてしまうので、IPアドレスで規制したりサインインシステムで覆ったりしなければなりません。




    Copyright 2026
    サイトマップ