受祝福的服务器(Node.js)通过 websocket 到浏览器中的 Xterm.js 客户端
Posted
技术标签:
【中文标题】受祝福的服务器(Node.js)通过 websocket 到浏览器中的 Xterm.js 客户端【英文标题】:Blessed server (Node.js) over websocket to Xterm.js client in Browser 【发布时间】:2018-10-16 20:52:57 【问题描述】:我有什么:
Node.js 脚本运行 Blessed 和 http/websocket 服务器。 浏览器运行 Xterm.js 和 websocket 客户端。我想做什么:
通过 websockets 为 xterm 窗口渲染祝福。服务器代码:
"use strict";
process.title = 'neosim-server';
var blessed = require('neo-blessed');
var contrib = require('blessed-contrib');
var webSocketServer = require('websocket').server;
var http = require('http');
const webSocketsServerPort = 8080;
var clients = [ ];
/**
* HTTP server
*/
var server = http.createServer(function(request, response)
// Not important for us. We're writing WebSocket server,
// not HTTP server
);
server.listen(webSocketsServerPort, function()
console.log((new Date()) + " Server is listening on port "
+ webSocketsServerPort + ".");
);
/**
* WebSocket server
*/
var wsServer = new webSocketServer(
// WebSocket server is tied to a HTTP server. WebSocket
// request is just an enhanced HTTP request. For more info
// http://tools.ietf.org/html/rfc6455#page-6
httpServer: server,
autoAcceptConnections: false
);
function originIsAllowed(origin)
// put logic here to detect whether the specified origin is allowed.
return true;
// This callback function is called every time someone
// tries to connect to the WebSocket server
wsServer.on('request', function(request)
if (!originIsAllowed(request.origin))
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
console.log((new Date()) + ' Connection from origin '
+ request.origin + '.');
// accept connection - you should check 'request.origin' to
// make sure that client is connecting from your website
// (http://en.wikipedia.org/wiki/Same_origin_policy)
var connection = request.accept(null, request.origin);
// we need to know client index to remove them on 'close' event
connection.write = connection.send;
connection.read = connection.socket.read;
connection.program = blessed.program(
tput: true,
input: connection,
output: connection
);
connection.program.tput = blessed.tput(
term: 'xterm-256color',
extended: true,
);
connection.screen = blessed.screen(
program: connection.program,
tput: connection.program.tput,
input: connection,
output: connection,
//smartCSR: true,
terminal: 'xterm-256color',
fullUnicode: true
);
var index = clients.push(connection) - 1;
var userName = false;
console.log((new Date()) + ' Connection accepted.');
connection.program.write("test");
// send back chat history
/*if (history.length > 0)
connection.sendUTF(
JSON.stringify( type: 'history', data: history ));
*/
// terminal type message
connection.on('term', function(terminal)
console.log("Term");
connection.screen.terminal = terminal;
connection.screen.render();
);
connection.on('resize', function(width, height)
console.log("Resize");
connection.columns = width;
connection.rows = height;
connection.emit('resize');
);
// user sent some message
connection.on('message', function(message)
if (message.type === 'utf8') // accept only text
console.log((new Date()) + ' Received Message: ' + message.utf8Data);
);
// user disconnected
connection.on('close', function(connection)
if (connection.screen && !connection.screen.destroyed)
connection.screen.destroy();
);
connection.screen.key(['C-c', 'q'], function(ch, key)
connection.screen.destroy();
);
connection.screen.on('destroy', function()
if (connection.writable)
connection.destroy();
);
connection.screen.data.main = blessed.box(
parent: connection.screen,
left: 'center',
top: 'center',
width: '80%',
height: '90%',
border: 'line',
content: 'Welcome to my server. Here is your own private session.'
);
connection.screen.render();
);
客户页面:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
<script src="node_modules/xterm/dist/xterm.js"></script>
<script src="node_modules/xterm/dist/addons/attach/attach.js"></script>
<script src="node_modules/xterm/dist/addons/fit/fit.js"></script>
<script src="node_modules/xterm/dist/addons/winptyCompat/winptyCompat.js"></script>
</head>
<body>
<div id="terminal"></div>
<script>
Terminal.applyAddon(attach);
Terminal.applyAddon(fit);
Terminal.applyAddon(winptyCompat);
var term = new Terminal();
var socket = new WebSocket('ws://localhost:8080', null);
term.open(document.getElementById('terminal'));
term.winptyCompatInit();
term.fit();
term.focus();
term.write('Terminal ('+term.cols+'x'+term.rows+')\n\r');
// term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
// window.addEventListener('resize', resizeScreen, false)
function resizeScreen ()
term.fit();
socket.emit('resize', cols: term.cols, rows: term.rows );
;
socket.onopen = function (connection)
term.attach(socket, true, false);
//term.emit('term');
//term.emit('resize');
;
socket.onmessage = function (message)
term.write(message);
;
</script>
</body>
</html>
我遇到的问题是调用 screen.render() 时,客户端上没有显示任何内容。创建我的blessed.screen 时,我尝试使用:
connection.screen = blessed.screen(input: connection.socket, output: connection.socket);
但这也不起作用。在我当前的服务器代码中,我试图欺骗祝福使用connection.send而不是connect.socket.write,因为我认为浏览器websockets只接受'onmessage'事件。像这样:
connection.write = connection.send;
connection.read = connection.socket.read;
connection.screen = blessed.screen(input: connection, output: connection);
到目前为止,我尝试过的任何方法都没有奏效。我在这里做错了什么?或者仅仅是祝福不会与浏览器websockets一起使用。另外,我知道连接正常,因为我可以在两端发送/接收消息。
【问题讨论】:
【参考方案1】:我让它工作了。我将 http 响应添加到您的服务器以提供 html/js 文件 - 只是为了将所有内容集中在一个地方。主要问题是客户端中 websocket 连接的第二个参数为空。我刚刚删除它,然后它正在播放。
还添加了按 CR 时输入的回声,以便您从服务器获得响应。
查看下面的修改来源
服务器代码:
process.title = 'neosim-server';
var blessed = require('neo-blessed');
var contrib = require('blessed-contrib');
var webSocketServer = require('websocket').server;
var http = require('http');
var fs = require('fs');
const webSocketsServerPort = 8080;
var clients = [ ];
/**
* HTTP server
*/
var server = http.createServer(function(request, response)
// Not important for us. We're writing WebSocket server,
// not HTTP server
let path = request.url.substring(1);
if(path === '')
path = 'index.html';
if(fs.existsSync(path))
if(path.indexOf('.js') === path.length-3)
response.setHeader('Content-Type', 'application/javascript');
response.end(fs.readFileSync(path));
else
response.statusCode = 404;
response.end('');
);
server.listen(webSocketsServerPort, function()
console.log((new Date()) + " Server is listening on port "
+ webSocketsServerPort + ".");
);
/**
* WebSocket server
*/
var wsServer = new webSocketServer(
// WebSocket server is tied to a HTTP server. WebSocket
// request is just an enhanced HTTP request. For more info
// http://tools.ietf.org/html/rfc6455#page-6
httpServer: server,
autoAcceptConnections: false
);
function originIsAllowed(origin)
// put logic here to detect whether the specified origin is allowed.
return true;
// This callback function is called every time someone
// tries to connect to the WebSocket server
wsServer.on('request', function(request)
if (!originIsAllowed(request.origin))
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
console.log((new Date()) + ' Connection from origin '
+ request.origin + '.');
// accept connection - you should check 'request.origin' to
// make sure that client is connecting from your website
// (http://en.wikipedia.org/wiki/Same_origin_policy)
var connection = request.accept(null, request.origin);
// we need to know client index to remove them on 'close' event
connection.write = connection.send;
connection.read = connection.socket.read;
connection.program = blessed.program(
tput: true,
input: connection,
output: connection
);
connection.program.tput = blessed.tput(
term: 'xterm-256color',
extended: true,
);
connection.screen = blessed.screen(
program: connection.program,
tput: connection.program.tput,
input: connection,
output: connection,
//smartCSR: true,
terminal: 'xterm-256color',
fullUnicode: true
);
var index = clients.push(connection) - 1;
var userName = false;
console.log((new Date()) + ' Connection accepted.');
connection.program.write("test");
// send back chat history
/*if (history.length > 0)
connection.sendUTF(
JSON.stringify( type: 'history', data: history ));
*/
// terminal type message
connection.on('term', function(terminal)
console.log("Term");
connection.screen.terminal = terminal;
connection.screen.render();
);
connection.on('resize', function(width, height)
console.log("Resize");
connection.columns = width;
connection.rows = height;
connection.emit('resize');
);
let buf = '';
// user sent some message
connection.on('message', function(message)
if (message.type === 'utf8') // accept only text
console.log((new Date()) + ' Received Message: ' + message.utf8Data);
buf += message.utf8Data;
if(message.utf8Data === '\r')
console.log('You wrote:', buf);
connection.sendUTF(buf +'\r\n');
buf = '';
);
// user disconnected
connection.on('close', function(connection)
if (connection.screen && !connection.screen.destroyed)
connection.screen.destroy();
);
connection.screen.key(['C-c', 'q'], function(ch, key)
connection.screen.destroy();
);
connection.screen.on('destroy', function()
if (connection.writable)
connection.destroy();
);
connection.screen.data.main = blessed.box(
parent: connection.screen,
left: 'center',
top: 'center',
width: '80%',
height: '90%',
border: 'line',
content: 'Welcome to my server. Here is your own private session.'
);
connection.screen.render();
);
客户端代码:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
<script src="node_modules/xterm/dist/xterm.js"></script>
<script src="node_modules/xterm/dist/addons/attach/attach.js"></script>
<script src="node_modules/xterm/dist/addons/fit/fit.js"></script>
<script src="node_modules/xterm/dist/addons/winptyCompat/winptyCompat.js"></script>
</head>
<body>
<div id="terminal"></div>
<script>
Terminal.applyAddon(attach);
Terminal.applyAddon(fit);
Terminal.applyAddon(winptyCompat);
var term = new Terminal();
var socket = new WebSocket('ws://localhost:8080');
term.open(document.getElementById('terminal'));
term.winptyCompatInit();
term.fit();
term.focus();
term.write('Terminal ('+term.cols+'x'+term.rows+')\n\r');
// term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
// window.addEventListener('resize', resizeScreen, false)
function resizeScreen ()
term.fit();
socket.emit('resize', cols: term.cols, rows: term.rows );
;
socket.onopen = function (connection)
console.log('connection opened');
term.attach(socket, true, false);
//term.emit('term');
//term.emit('resize');
;
socket.onmessage = function (message)
term.write(message);
;
</script>
</body>
</html>
【讨论】:
您将如何销毁您创建的外壳并重新生成一个新外壳?以上是关于受祝福的服务器(Node.js)通过 websocket 到浏览器中的 Xterm.js 客户端的主要内容,如果未能解决你的问题,请参考以下文章
httpOnly cookie 中的 JWT - AuthGuard 和受保护的路由(Node.js、Angular)