Python websockets 模块和 IIS 作为反向代理

标签 python iis websocket reverse-proxy iis-10

我在 localhost:5005 上运行 websokets 模块的 python websocket 服务器。来自 documentation page 的代码:

#!/usr/bin/env python

import asyncio
import websockets
import logging

logger = logging.getLogger('websockets')
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler())

async def echo(websocket):
    async for message in websocket:
        print(message)
        await websocket.send(message)

async def main():
    async with websockets.serve(echo, "localhost", 5005):
        await asyncio.Future()  # run forever

asyncio.run(main())

客户端可以通过连接到 URL ws://localhost:5005 来访问它。 websockets 模块中提供了示例客户端代码 documentation page .
目标 是使客户端能够通过充当反向代理的 IIS(Windows native 网络服务器)访问服务器,即通过 URL ws://localhost/app

IIS-10 设置:

  • 应用程序请求路由缓存 --> 服务器代理设置 --> 启用代理
  • 站点 --> 默认网站:我添加了一个名为app的应用
  • URL 重写:我添加了以下规则:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="ReverseProxy" stopProcessing="true">
                    <match url="(.*)" />
                    <action type="Rewrite" url="http://localhost:5005" logRewrittenUrl="true" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

一旦客户端尝试连接,它就会断开连接并且服务器抛出此异常:

= connection is CONNECTING
< GET / HTTP/1.1
< Cache-Control: no-cache
< Connection: Upgrade
< Pragma: no-cache
< Upgrade: websocket
< Accept-Encoding: gzip, deflate, br, peerdist
< Accept-Language: en-US,en;q=0.9
< Host: localhost:5005
< Max-Forwards: 10
< User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
< Origin: null
< Sec-WebSocket-Version: 13
< Sec-WebSocket-Key: /C9ah/z+wAo4mnoACSz2IA==
< Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
< X-Original-URL: /app
< X-Forwarded-For: [::1]:52798
< X-ARR-LOG-ID: 8c59749a-4e5d-43cf-8a5a-c4421cc4ecc8
< X-P2P-PeerDist: Version=1.1
< X-P2P-PeerDistEx: MinContentInformation=1.0, MaxContentInformation=2.0
> HTTP/1.1 101 Switching Protocols
> Upgrade: websocket
> Connection: Upgrade
> Sec-WebSocket-Accept: W9Sttf7fHX3aB9zd4b/PVGt0Ldg=
> Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=12; client_max_window_bits=12
> Date: Fri, 15 Jul 2022 19:14:32 GMT
> Server: Python/3.7 websockets/10.3
connection open
= connection is OPEN
! failing connection with code 1006
= connection is CLOSED
x half-closing TCP connection
connection handler failed
Traceback (most recent call last):
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\protocol.py", line 945, in transfer_data
    message = await self.read_message()
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\protocol.py", line 1015, in read_message
    frame = await self.read_data_frame(max_size=self.max_size)
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\protocol.py", line 1090, in read_data_frame
    frame = await self.read_frame(max_size)
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\protocol.py", line 1149, in read_frame
    extensions=self.extensions,
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\framing.py", line 70, in read
    data = await reader(2)
  File "C:\Program Files\Python37\lib\asyncio\streams.py", line 677, in readexactly
    raise IncompleteReadError(incomplete, n)
asyncio.streams.IncompleteReadError: 0 bytes read on a total of 2 expected bytes
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\server.py", line 232, in handler
    await self.ws_handler(self)
  File "D:/Robotic Framework/RoboticApps/UI_Framework/server.py", line 12, in echo
    async for message in websocket:
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\protocol.py", line 482, in __aiter__
    yield await self.recv()
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\protocol.py", line 553, in recv
    await self.ensure_open()
  File "C:\Users\amin.ramezanifar\AppData\Roaming\Python\Python37\site-packages\websockets\legacy\protocol.py", line 921, in ensure_open
    raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: no close frame received or sent
connection closed

为了确保 IIS 设置是否正确,我使用了来自 here 的另一个名为“simple-websocket-server”的 websocket 库它工作正常。我还尝试了来自 here 的简单 Node.js 服务器并且成功了。
有什么问题吗?

最佳答案

Amin(问题作者)和我发现您必须在 websockets 中禁用压缩,因为 IIS 不支持它。

与 websockets 不同,它与其他库一起工作,因为它们不实现压缩或默认情况下不启用它。

详情参见GitHub上的讨论:https://github.com/aaugustin/websockets/issues/1192

关于Python websockets 模块和 IIS 作为反向代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73008159/

相关文章:

python - 使用重复索引递增 Numpy 多维数组

python - Python 机器学习算法的扩展性如何?

c# - ASP.NET Web API 应用程序在启用 TransferRequestHandler 的情况下为不存在的路由返回 HTTP 500

javascript - 如果在 Chrome 上运行,createObjectURL 不起作用

python - os.system(旧Python)和带参数的参数

python - 导入 Keras 时出错

php - IIS php.ini display_errors = stderr 到文件?

asp.net - 确保 dot.net 站点始终运行

GWT和WebSocket/将数据从服务器推送到GWT客户端

php - 与 PHP 的 Websocket 安全 (wss) 连接