html: use api to fetch auth token

This commit is contained in:
Shuanglei Tao
2020-02-06 17:24:00 +08:00
parent 463da8352e
commit 6bbe4db775
9 changed files with 8564 additions and 8350 deletions

View File

@@ -65,6 +65,7 @@
"decko": "^1.2.0", "decko": "^1.2.0",
"file-saver": "^2.0.2", "file-saver": "^2.0.2",
"preact": "^10.0.5", "preact": "^10.0.5",
"whatwg-fetch": "^3.0.0",
"xterm": "^4.4.0", "xterm": "^4.4.0",
"xterm-addon-fit": "^0.3.0", "xterm-addon-fit": "^0.3.0",
"xterm-addon-web-links": "^0.2.1", "xterm-addon-web-links": "^0.2.1",

View File

@@ -8,9 +8,10 @@ if ((module as any).hot) {
require('preact/debug'); require('preact/debug');
} }
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'; const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsPath = window.location.pathname.endsWith('/') ? 'ws' : '/ws'; const path = window.location.pathname.replace(/[\/]+$/, '');
const url = [protocol, window.location.host, window.location.pathname, wsPath, window.location.search].join(''); const wsUrl = [protocol, '//', window.location.host, path, '/ws', window.location.search].join('');
const tokenUrl = [window.location.protocol, '//', window.location.host, path, '/token'].join('');
const termOptions = { const termOptions = {
fontSize: 13, fontSize: 13,
fontFamily: 'Menlo For Powerline,Consolas,Liberation Mono,Menlo,Courier,monospace', fontFamily: 'Menlo For Powerline,Consolas,Liberation Mono,Menlo,Courier,monospace',
@@ -39,6 +40,6 @@ const termOptions = {
export class App extends Component { export class App extends Component {
render() { render() {
return <Xterm id="terminal-container" url={url} options={termOptions} />; return <Xterm id="terminal-container" wsUrl={wsUrl} tokenUrl={tokenUrl} options={termOptions} />;
} }
} }

View File

@@ -17,7 +17,6 @@ export interface TerminalExtended extends Terminal {
export interface WindowExtended extends Window { export interface WindowExtended extends Window {
term: TerminalExtended; term: TerminalExtended;
tty_auth_token?: string;
} }
declare let window: WindowExtended; declare let window: WindowExtended;
@@ -34,7 +33,8 @@ const enum Command {
interface Props { interface Props {
id: string; id: string;
url: string; wsUrl: string;
tokenUrl: string;
options: ITerminalOptions; options: ITerminalOptions;
} }
@@ -47,6 +47,7 @@ export class Xterm extends Component<Props> {
private overlayAddon: OverlayAddon; private overlayAddon: OverlayAddon;
private zmodemAddon: ZmodemAddon; private zmodemAddon: ZmodemAddon;
private socket: WebSocket; private socket: WebSocket;
private token: string;
private title: string; private title: string;
private resizeTimeout: number; private resizeTimeout: number;
private backoff: backoff.Backoff; private backoff: backoff.Backoff;
@@ -65,7 +66,7 @@ export class Xterm extends Component<Props> {
}); });
this.backoff.on('ready', () => { this.backoff.on('ready', () => {
this.backoffLock = false; this.backoffLock = false;
this.openTerminal(); this.refreshToken().then(this.openTerminal);
}); });
this.backoff.on('backoff', (_, delay: number) => { this.backoff.on('backoff', (_, delay: number) => {
console.log(`[ttyd] will attempt to reconnect websocket in ${delay}ms`); console.log(`[ttyd] will attempt to reconnect websocket in ${delay}ms`);
@@ -73,7 +74,8 @@ export class Xterm extends Component<Props> {
}); });
} }
componentDidMount() { async componentDidMount() {
await this.refreshToken();
this.openTerminal(); this.openTerminal();
} }
@@ -102,6 +104,19 @@ export class Xterm extends Component<Props> {
socket.send(payload); socket.send(payload);
} }
@bind
private async refreshToken() {
try {
const resp = await fetch(this.props.tokenUrl);
if (resp.ok) {
const json = await resp.json();
this.token = json.token;
}
} catch (e) {
console.log(`[ttyd] fetch ${this.props.tokenUrl}: ${e.message}`);
}
}
@bind @bind
private onWindowResize() { private onWindowResize() {
const { fitAddon } = this; const { fitAddon } = this;
@@ -121,7 +136,7 @@ export class Xterm extends Component<Props> {
this.terminal.dispose(); this.terminal.dispose();
} }
this.socket = new WebSocket(this.props.url, ['tty']); this.socket = new WebSocket(this.props.wsUrl, ['tty']);
this.terminal = new Terminal(this.props.options); this.terminal = new Terminal(this.props.options);
const { socket, terminal, container, fitAddon, overlayAddon } = this; const { socket, terminal, container, fitAddon, overlayAddon } = this;
window.term = terminal as TerminalExtended; window.term = terminal as TerminalExtended;
@@ -174,9 +189,7 @@ export class Xterm extends Component<Props> {
this.backoff.reset(); this.backoff.reset();
const { socket, textEncoder, fitAddon } = this; const { socket, textEncoder, fitAddon } = this;
const authToken = window.tty_auth_token; socket.send(textEncoder.encode(JSON.stringify({ AuthToken: this.token })));
socket.send(textEncoder.encode(JSON.stringify({ AuthToken: authToken })));
fitAddon.fit(); fitAddon.fit();
} }
@@ -188,11 +201,6 @@ export class Xterm extends Component<Props> {
overlayAddon.showOverlay('Connection Closed', null); overlayAddon.showOverlay('Connection Closed', null);
window.removeEventListener('beforeunload', this.onWindowUnload); window.removeEventListener('beforeunload', this.onWindowUnload);
// 1008: POLICY_VIOLATION - Auth failure
if (event.code === 1008) {
window.location.reload();
}
// 1000: CLOSE_NORMAL // 1000: CLOSE_NORMAL
if (event.code !== 1000) { if (event.code !== 1000) {
this.reconnect(); this.reconnect();

View File

@@ -1,3 +1,4 @@
import 'whatwg-fetch';
import { h, render } from 'preact'; import { h, render } from 'preact';
import { App } from './components/app'; import { App } from './components/app';
import './style/index.scss'; import './style/index.scss';

View File

@@ -10,7 +10,6 @@
<% } %> <% } %>
</head> </head>
<body> <body>
<script src="auth_token.js"></script>
<% for (const js in htmlWebpackPlugin.files.js) { %> <% for (const js in htmlWebpackPlugin.files.js) { %>
<script inline type="text/javascript" src="<%= htmlWebpackPlugin.files.js[js] %>"></script> <script inline type="text/javascript" src="<%= htmlWebpackPlugin.files.js[js] %>"></script>
<% } %> <% } %>

View File

@@ -73,7 +73,7 @@ const devConfig = {
compress: true, compress: true,
port: 9000, port: 9000,
proxy: [{ proxy: [{
context: ['/auth_token.js', '/ws'], context: ['/token', '/ws'],
target: 'http://localhost:7681', target: 'http://localhost:7681',
ws: true ws: true
}] }]

View File

@@ -8477,6 +8477,11 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==
whatwg-fetch@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
which-module@^1.0.0: which-module@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"

16853
src/html.h

File diff suppressed because it is too large Load Diff

View File

@@ -149,15 +149,15 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
p = buffer + LWS_PRE; p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE; end = p + sizeof(buffer) - LWS_PRE;
if (strncmp(pss->path, "/auth_token.js", 14) == 0) { if (strncmp(pss->path, "/token", 6) == 0) {
const char *credential = server->credential != NULL ? server->credential : ""; const char *credential = server->credential != NULL ? server->credential : "";
size_t n = sprintf(buf, "var tty_auth_token = '%s';\n", credential); size_t n = sprintf(buf, "{\"token\": \"%s\"}", credential);
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
return 1; return 1;
if (lws_add_http_header_by_token(wsi, if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_CONTENT_TYPE, WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *) "application/javascript", (unsigned char *) "application/json;charset=utf-8",
22, &p, end)) 30, &p, end))
return 1; return 1;
if (lws_add_http_header_content_length(wsi, (unsigned long) n, &p, end)) if (lws_add_http_header_content_length(wsi, (unsigned long) n, &p, end))
return 1; return 1;