使用http方式访问n8n报错Could not connect to server. Refresh to try again

使用localhost去访问n8n是没问题,而使用http的ip形式去访问就报错。经过多次测试,不同版本的报错以及原因不尽相同。

1.109.1、1.109.2版本

运行n8n:

mkdir -p n8n_data && chown -R 1000:1000 n8n_data

docker run -itd \
  --name n8n \
  -p 5678:5678 \
  -e N8N_SECURE_COOKIE=false \
  -v ./n8n_data:/home/node/.n8n \
n8nio/n8n:1.109.2
# 这里换1.109.1也一样

访问页面,可以看到初始设置框/登录框,以及右下角的报错,但是报错归报错,初始设置/登录还是可以照常使用。

在 1.111.0 版本已解决。

1.120.3版本

运行n8n:

mkdir -p n8n_data && chown -R 1000:1000 n8n_data

docker run -itd \
  --name n8n \
  -p 5678:5678 \
  -e N8N_SECURE_COOKIE=false \
  -v ./n8n_data:/home/node/.n8n \
n8nio/n8n:1.120.3

访问页面,中间不出现初始设置框/登录框,只剩下右下角的报错。官方的issue里没告知原因和可用的解决方案,当然升级到 1.121.0 版本即可解决。

那么我非要使用1.120.3版本,有没有不升级就可以解决的法子呢?官方不给,我们就自己寻找。n8n是开源的,下载源码进行分析。在packages/frontend/@n8n/rest-api-client/src/utils.ts定位到:

const getBrowserId = () => {
	let browserId = localStorage.getItem(BROWSER_ID_STORAGE_KEY);
	if (!browserId) {
		browserId = crypto.randomUUID();
		localStorage.setItem(BROWSER_ID_STORAGE_KEY, browserId);
	}
	return browserId;
};

程序在初始化时会执行到getBrowserId函数,里面会先从浏览器的localStorage取一个BROWSER_ID_STORAGE_KEY值(这里经搜索源码得到赋值为n8n-browserId),如果取不到的话,就调用crypto.randomUUID()生成。

这里乍看上面这段代码没什么问题,但其实问题大的很,crypto.randomUUID()是Web Crypto API的一部分,浏览器对这个API里的某些功能(包括randomUUID)有secure context(安全上下文)要求:使用HTTPS协议,或者localhost、127.0.0.1等本地地址。

破案了,这也是为何使用http://IP:PORT/的形式访问n8n就会报错,使用http里就没法用到crypto.randomUUID(),而n8n的报错又不直接把捕捉到的错误给显示出来,让人难以定位。

解决法子:

// 在console里执行
localStorage.setItem('n8n-browserId', '18888888-8888-8888-8888-888888888888');

这样即可。另外如果登录后退出时会执行localStorage.removeItem(BROWSER_ID_STORAGE_KEY);,这会清理localStorage的n8n-browserId,若还要再使用,就还得执行上面的添加语句。

未来如果遇到其他版本的报错,pcat经分析后再作补充。