workerman创建wss客户端无法调用通义千问的实时语音合成模型, 推荐写法似乎有bug!

askuiop

问题描述

在使用workerman 创建 wss 客户端调用通义千问的实时语音合成模型时, 使用官方示例写法设置hearder后, 千问服务端却返回 401 。 但是使用官方的python 示例脚本没有问题。 还有如果使用原始拼接发送hearder 也没有问题。 是不是Bug呢 ?

程序代码或配置

1.有问题的: workerman手册示例写法:

    $worker = new Worker();
        $worker->onWorkerStart = function() use ($API_KEY) {

            $ws = new AsyncTcpConnection("ws://dashscope.aliyuncs.com:443/api-ws/v1/realtime?model=qwen-tts-realtime");
            $ws->transport = 'ssl';

            $ws->headers = [
                "Host: dashscope.aliyuncs.com",
                "Authorization: Bearer $API_KEY",
                "User-Agent: Workerman-WebSocket-Client",
                "Upgrade: websocket",
                "Connection: Upgrade",
                "Sec-WebSocket-Key: " . base64_encode(random_bytes(16)),
                "Sec-WebSocket-Version: 13"
            ];

            // 握手成功
            $ws->onConnect = function($connection) {
                echo "握手成功,可以通信了...\n";
            };

            // 接收服务端返回消息
            $ws->onMessage = function($connection, $data) {
                echo "收到消息: $data\n";
            };

            $ws->onError = function($connection, $code, $msg) {
                echo "出错 [$code] $msg\n";
            };

            $ws->onClose = function($connection) {
                echo "连接已关闭\n";
            };

            $ws->connect();
        }

输出信息:

握手成功,可以通信了...
Sec-WebSocket-Accept not found. Header:
HTTP/1.1 401 Unauthorized
x-request-id: 7a696c29-a890-443f-a49a-58e182721f93
content-type: application/json
content-length: 109
x-envoy-upstream-service-time: 4
date: Tue, 16 Sep 2025 09:09:01 GMT
server: istio-envoy
req-cost-time: 4
req-arrive-time: 1758013741363
resp-start-time: 1758013741367
vary: Accept-Encoding
connection: close
连接已关闭

2. 可以正常运行的: workerman 比较原始的拼接发送hearder:

    $worker = new Worker();
        $worker->onWorkerStart = function() {
            $API_KEY = 'sk-xxxx';
            $path = "/api-ws/v1/realtime?model=qwen-tts-realtime";
            $secKey = base64_encode(random_bytes(16));
            $raw = "GET $path HTTP/1.1\r\n";
            $raw .= "Host: dashscope.aliyuncs.com\r\n";
            $raw .= "Upgrade: websocket\r\n";
            $raw .= "Connection: Upgrade\r\n";
            $raw .= "Sec-WebSocket-Key: $secKey\r\n";
            $raw .= "Sec-WebSocket-Version: 13\r\n";
            $raw .= "User-Agent: Workerman-WebSocket-Client\r\n";
            $raw .= "Authorization: Bearer " . $API_KEY . "\r\n";
            $raw .= "\r\n";

            // 建立一个 SSL/TCP 连接到 443(ssl://)
            $conn = new AsyncTcpConnection('ssl://dashscope.aliyuncs.com:443');
            $conn->onConnect = function($c) use ($raw) {
                echo "已连接,发送原始握手请求...\n";
                $c->send($raw);
            };

            $conn->onMessage = function($c, $rawData) {
                echo "=== 服务器响应开始 ===\n";
                echo $rawData . "\n";
                echo "=== 服务器响应结束 ===\n";
                // 打后直接关连接
                $c->close();
            };

            $conn->onError = function($c, $code, $msg) {
                echo "连接/发送错误: [$code] $msg\n";
            };

            $conn->connect();
        };

输出信息:

已连接,发送原始握手请求...
=== 服务器响应开始 ===
HTTP/1.1 101 Switching Protocols
upgrade: websocket
connection: upgrade
sec-websocket-accept: 0eO4LqIZ6T9E0u+vqpcjmd6DGGU=
date: Wed, 17 Sep 2025 01:31:47 GMT
server: istio-envoy

=== 服务器响应结束 ===
=== 服务器响应开始 ===
~{"event_id":"event_DnN9IwmPCLLyQigDxLvoY","type":"session.created","session":{"object":"realtime.session","mode":"server_commit","model":"qwen-tts-realtime","voice":"Cherry","response_format":"pcm","sample_rate":24000,"id":"sess_I
uMmaLRz7ri1FtkC5j28K"}}
=== 服务器响应结束 ===

第二种写法就是没有问题的。 为什么第一种推荐写法会不行呢, 这是什么原因, 是bug吗?

操作系统环境及workerman/webman等具体版本

windows 10 系统, php7.4 , workerman V4.1.17

116 1 1
1个回答

walkor 打赏

除了
"Authorization: Bearer $API_KEY"
其它头没必要写,其它头都是自动的

  • askuiop 20小时前

    都尝试过了,就是因为单独写Authorization 不行, 才补上其他的头信息的, 也是不行

  • askuiop 19小时前

    使用 ratchet/pawl 库也是没有问题的

  • morris 17小时前

    tcpdump 抓包看看 数据流 。 具体哪里不一样

🔝