mirror of
https://github.com/whyour/qinglong.git
synced 2025-07-29 07:56:06 +08:00
抽取到service层
This commit is contained in:
parent
f9ea960758
commit
74cad45856
|
@ -1,113 +1,29 @@
|
|||
import { Router } from 'express';
|
||||
import * as pty from 'node-pty';
|
||||
import os from 'os';
|
||||
import Container from 'typedi';
|
||||
import { Logger } from 'winston';
|
||||
import TerminalService from '../services/terminal';
|
||||
// Whether to use binary transport.
|
||||
const USE_BINARY = os.platform() !== 'win32';
|
||||
const route = Router();
|
||||
|
||||
export default (app: Router) => {
|
||||
const terminals = {};
|
||||
const logs = {};
|
||||
const logger: Logger = Container.get('logger');
|
||||
|
||||
app.use('/', route);
|
||||
route.post('/terminals', (req, res) => {
|
||||
const env = Object.assign({}, process.env);
|
||||
env['COLORTERM'] = 'truecolor';
|
||||
var cols = parseInt(req.query.cols),
|
||||
rows = parseInt(req.query.rows),
|
||||
term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
|
||||
name: 'xterm-256color',
|
||||
cols: cols || 80,
|
||||
rows: rows || 24,
|
||||
cwd: process.platform === 'win32' ? undefined : env.PWD,
|
||||
env: env,
|
||||
encoding: USE_BINARY ? null : 'utf8',
|
||||
});
|
||||
|
||||
console.log('Created terminal with PID: ' + term.pid);
|
||||
terminals[term.pid] = term;
|
||||
logs[term.pid] = '';
|
||||
term.on('data', function (data) {
|
||||
logs[term.pid] += data;
|
||||
});
|
||||
const terminalService = Container.get(TerminalService);
|
||||
const term = terminalService.createTerminal(req);
|
||||
res.send(term.pid.toString());
|
||||
res.end();
|
||||
});
|
||||
|
||||
route.post('/terminals/:pid/size', (req, res) => {
|
||||
var pid = parseInt(req.params.pid),
|
||||
cols = parseInt(req.query.cols),
|
||||
rows = parseInt(req.query.rows),
|
||||
term = terminals[pid];
|
||||
|
||||
term.resize(cols, rows);
|
||||
console.log(
|
||||
'Resized terminal ' +
|
||||
pid +
|
||||
' to ' +
|
||||
cols +
|
||||
' cols and ' +
|
||||
rows +
|
||||
' rows.',
|
||||
);
|
||||
const terminalService = Container.get(TerminalService);
|
||||
terminalService.resizeTerminal(req);
|
||||
res.end();
|
||||
});
|
||||
|
||||
route.ws('/terminals/:pid', function (ws, req) {
|
||||
var term = terminals[parseInt(req.params.pid)];
|
||||
console.log('Connected to terminal ' + term.pid);
|
||||
ws.send(logs[term.pid]);
|
||||
|
||||
// string message buffering
|
||||
function buffer(socket, timeout) {
|
||||
let s = '';
|
||||
let sender = null;
|
||||
return (data) => {
|
||||
s += data;
|
||||
if (!sender) {
|
||||
sender = setTimeout(() => {
|
||||
socket.send(s);
|
||||
s = '';
|
||||
sender = null;
|
||||
}, timeout);
|
||||
}
|
||||
};
|
||||
}
|
||||
// binary message buffering
|
||||
function bufferUtf8(socket, timeout) {
|
||||
let buffer = [];
|
||||
let sender = null;
|
||||
let length = 0;
|
||||
return (data) => {
|
||||
buffer.push(data);
|
||||
length += data.length;
|
||||
if (!sender) {
|
||||
sender = setTimeout(() => {
|
||||
socket.send(Buffer.concat(buffer, length));
|
||||
buffer = [];
|
||||
sender = null;
|
||||
length = 0;
|
||||
}, timeout);
|
||||
}
|
||||
};
|
||||
}
|
||||
const send = USE_BINARY ? bufferUtf8(ws, 5) : buffer(ws, 5);
|
||||
|
||||
term.on('data', function (data) {
|
||||
try {
|
||||
send(data);
|
||||
} catch (ex) {
|
||||
// The WebSocket is not open, ignore
|
||||
}
|
||||
});
|
||||
ws.on('message', function (msg) {
|
||||
term.write(msg);
|
||||
});
|
||||
ws.on('close', function () {
|
||||
term.kill();
|
||||
console.log('Closed terminal ' + term.pid);
|
||||
// Clean things up
|
||||
delete terminals[term.pid];
|
||||
delete logs[term.pid];
|
||||
});
|
||||
const terminalService = Container.get(TerminalService);
|
||||
terminalService.listenTerminal(ws, req);
|
||||
});
|
||||
};
|
||||
|
|
123
back/services/terminal.ts
Normal file
123
back/services/terminal.ts
Normal file
|
@ -0,0 +1,123 @@
|
|||
import { Inject, Service } from 'typedi';
|
||||
import os from 'os';
|
||||
import * as pty from 'node-pty';
|
||||
import winston from 'winston';
|
||||
|
||||
const USE_BINARY = os.platform() !== 'win32';
|
||||
|
||||
@Service()
|
||||
export default class TerminalService {
|
||||
private terminals: Record<string, any>;
|
||||
private logs: Record<string, string>;
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {
|
||||
this.terminals = {};
|
||||
this.logs = {};
|
||||
}
|
||||
|
||||
createTerminal(req) {
|
||||
const that = this;
|
||||
const env = Object.assign({}, process.env);
|
||||
env['COLORTERM'] = 'truecolor';
|
||||
const cols = parseInt(req.query.cols);
|
||||
const rows = parseInt(req.query.rows);
|
||||
const term = pty.spawn(
|
||||
process.platform === 'win32' ? 'cmd.exe' : 'bash',
|
||||
[],
|
||||
{
|
||||
name: 'xterm-256color',
|
||||
cols: cols || 80,
|
||||
rows: rows || 24,
|
||||
cwd: process.platform === 'win32' ? undefined : env.PWD,
|
||||
env: env,
|
||||
encoding: USE_BINARY ? null : 'utf8',
|
||||
},
|
||||
);
|
||||
|
||||
that.logger.silly('Created terminal with PID: ' + term.pid);
|
||||
that.terminals[term.pid] = term;
|
||||
that.logs[term.pid] = '';
|
||||
term.on('data', function (data) {
|
||||
that.logs[term.pid] += data;
|
||||
});
|
||||
return term;
|
||||
}
|
||||
|
||||
resizeTerminal(req) {
|
||||
const that = this;
|
||||
const pid = parseInt(req.params.pid);
|
||||
const cols = parseInt(req.query.cols);
|
||||
const rows = parseInt(req.query.rows);
|
||||
const term = that.terminals[pid];
|
||||
|
||||
term.resize(cols, rows);
|
||||
that.logger.silly(
|
||||
'Resized terminal ' +
|
||||
pid +
|
||||
' to ' +
|
||||
cols +
|
||||
' cols and ' +
|
||||
rows +
|
||||
' rows.',
|
||||
);
|
||||
}
|
||||
|
||||
listenTerminal(ws, req) {
|
||||
const that = this;
|
||||
var term = that.terminals[parseInt(req.params.pid)];
|
||||
that.logger.silly('Connected to terminal ' + term.pid);
|
||||
ws.send(that.logs[term.pid]);
|
||||
|
||||
// string message buffering
|
||||
function buffer(socket, timeout) {
|
||||
let s = '';
|
||||
let sender = null;
|
||||
return (data) => {
|
||||
s += data;
|
||||
if (!sender) {
|
||||
sender = setTimeout(() => {
|
||||
socket.send(s);
|
||||
s = '';
|
||||
sender = null;
|
||||
}, timeout);
|
||||
}
|
||||
};
|
||||
}
|
||||
// binary message buffering
|
||||
function bufferUtf8(socket, timeout) {
|
||||
let buffer = [];
|
||||
let sender = null;
|
||||
let length = 0;
|
||||
return (data) => {
|
||||
buffer.push(data);
|
||||
length += data.length;
|
||||
if (!sender) {
|
||||
sender = setTimeout(() => {
|
||||
socket.send(Buffer.concat(buffer, length));
|
||||
buffer = [];
|
||||
sender = null;
|
||||
length = 0;
|
||||
}, timeout);
|
||||
}
|
||||
};
|
||||
}
|
||||
const send = USE_BINARY ? bufferUtf8(ws, 5) : buffer(ws, 5);
|
||||
|
||||
term.on('data', function (data) {
|
||||
try {
|
||||
send(data);
|
||||
} catch (ex) {
|
||||
// The WebSocket is not open, ignore
|
||||
}
|
||||
});
|
||||
ws.on('message', function (msg) {
|
||||
term.write(msg);
|
||||
});
|
||||
ws.on('close', function () {
|
||||
term.kill();
|
||||
that.logger.silly('Closed terminal ' + term.pid);
|
||||
// Clean things up
|
||||
delete that.terminals[term.pid];
|
||||
delete that.logs[term.pid];
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user