You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mojo示例WebSocket在HTTPS环境下无法运行,报不安全操作异常

Firefox中运行Mojo示例代码出现"Uncaught DOMException: The operation is insecure"错误的解决方法

在Firefox中运行示例代码时触发以下错误:

Uncaught DOMException: The operation is insecure.

示例代码

启动命令

$ MOJO_LISTEN=http://*:5000 morbo index.pl

Perl应用代码(index.pl)

use Mojolicious::Lite -signatures;

# 渲染DATA段中的index.html.ep模板
get '/' => sub ($c) {
  $c->render(template => 'index');
};

# 模板调用的WebSocket服务,用于提取网站标题
websocket '/title' => sub ($c) {
  $c->on(message => sub ($c, $msg) {
    my $title = $c->ua->get($msg)->result->dom->at('title')->text;
    $c->send($title);
  });
};

app->start;
__DATA__

@@ index.html.ep
% my $url = url_for 'title';
<script>
  const ws = new WebSocket('<%= $url->to_abs %>');
  ws.onmessage = function (event) { document.body.innerHTML += event.data };
  ws.onopen    = function (event) { ws.send('https://mojolicious.org') };
</script>

问题原因

当前使用Nginx作为Mojo的反向代理,浏览器的混合内容安全策略规定:当页面通过HTTPS协议加载时,所有子资源(包括WebSocket连接)必须使用加密协议。示例代码中url_for->to_abs生成的是未加密的ws://地址,违反了安全策略,导致Firefox抛出该错误。

解决方案

1. 配置Nginx支持WSS反向代理

在Nginx的站点配置中添加WebSocket代理规则,确保将wss://请求转发到Mojo的ws://服务:

location /title {
    proxy_pass http://127.0.0.1:5000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    # 传递协议头给后端应用
    proxy_set_header X-Forwarded-Proto $scheme;
}

2. 修改WebSocket地址生成逻辑

确保生成的WebSocket地址与当前页面协议匹配(HTTP对应ws,HTTPS对应wss),有两种实现方式:

方式一:前端自动适配协议

修改index.html.ep中的JavaScript代码,动态切换协议:

% my $url = url_for 'title';
<script>
  // 根据页面协议自动选择ws或wss
  const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
  const wsUrl = new URL('<%= $url->to_abs %>');
  wsUrl.protocol = wsProtocol;
  const ws = new WebSocket(wsUrl);
  
  ws.onmessage = function (event) { document.body.innerHTML += event.data };
  ws.onopen    = function (event) { ws.send('https://mojolicious.org') };
</script>

方式二:后端根据代理头设置协议

在Mojo应用中添加钩子,根据Nginx传递的X-Forwarded-Proto头生成正确的绝对URL:

use Mojolicious::Lite -signatures;

# 根据反向代理头修正协议
app->hook(before_render => sub ($c) {
  if (my $proto = $c->req->headers->header('X-Forwarded-Proto')) {
    $c->req->url->base->scheme($proto);
  }
});

# 原有路由逻辑不变
get '/' => sub ($c) {
  $c->render(template => 'index');
};

websocket '/title' => sub ($c) {
  $c->on(message => sub ($c, $msg) {
    my $title = $c->ua->get($msg)->result->dom->at('title')->text;
    $c->send($title);
  });
};

app->start;
__DATA__

@@ index.html.ep
% my $url = url_for 'title';
<script>
  const ws = new WebSocket('<%= $url->to_abs %>');
  ws.onmessage = function (event) { document.body.innerHTML += event.data };
  ws.onopen    = function (event) { ws.send('https://mojolicious.org') };
</script>

3. 重启服务

  • 重启Nginx使配置生效:sudo systemctl restart nginx
  • 重启Mojo应用(morbo开发服务器直接重启即可)

内容的提问来源于stack exchange,提问作者chovy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:16:38