Update to actix-web 1.0 and use handlebars
This commit is contained in:
parent
d71b42665f
commit
e74a974d51
1260
Cargo.lock
generated
1260
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -16,10 +16,13 @@ travis-ci = { repository = "fubarnetes/webterm", branch = "master" }
|
|||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
actix-files = "0.1.4"
|
||||||
|
actix-service = "0.4.2"
|
||||||
|
actix-web-actors = "1.0.2"
|
||||||
actix-web= "1.0.8"
|
actix-web= "1.0.8"
|
||||||
actix= "0.8.3"
|
actix= "0.8.3"
|
||||||
askama = { version = "0.8.0", features= ["with-actix-web"] }
|
|
||||||
futures = "0.1.29"
|
futures = "0.1.29"
|
||||||
|
handlebars = "2.0.2"
|
||||||
lazy_static = "1.3.0"
|
lazy_static = "1.3.0"
|
||||||
libc = "0.2.62"
|
libc = "0.2.62"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
use actix::Message;
|
use actix::Message;
|
||||||
use actix_web::Binary;
|
|
||||||
use futures::{Future, Poll};
|
use futures::{Future, Poll};
|
||||||
use libc::c_ushort;
|
use libc::c_ushort;
|
||||||
use tokio_pty_process::PtyMaster;
|
use tokio_pty_process::PtyMaster;
|
||||||
@ -37,8 +36,8 @@ impl Message for IO {
|
|||||||
type Result = ();
|
type Result = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<Binary> for IO {
|
impl Into<actix_web::web::Bytes> for IO {
|
||||||
fn into(self) -> Binary {
|
fn into(self) -> actix_web::web::Bytes {
|
||||||
self.0.into()
|
self.0.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,8 +48,8 @@ impl AsRef<[u8]> for IO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Binary> for IO {
|
impl From<actix_web::web::Bytes> for IO {
|
||||||
fn from(b: Binary) -> Self {
|
fn from(b: actix_web::web::Bytes) -> Self {
|
||||||
Self(b.as_ref().into())
|
Self(b.as_ref().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/lib.rs
63
src/lib.rs
@ -29,10 +29,11 @@
|
|||||||
|
|
||||||
extern crate actix;
|
extern crate actix;
|
||||||
extern crate actix_web;
|
extern crate actix_web;
|
||||||
extern crate askama;
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
|
extern crate handlebars;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate tokio;
|
extern crate tokio;
|
||||||
extern crate tokio_codec;
|
extern crate tokio_codec;
|
||||||
@ -41,12 +42,11 @@ extern crate tokio_pty_process;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate pretty_env_logger;
|
extern crate pretty_env_logger;
|
||||||
use askama::actix_web::TemplateIntoResponse;
|
|
||||||
|
|
||||||
use actix::*;
|
use actix::prelude::*;
|
||||||
use actix_web::{ws, App};
|
use actix::{Actor, StreamHandler};
|
||||||
|
use actix_web::{web, App, HttpRequest, HttpResponse};
|
||||||
use futures::prelude::*;
|
use actix_web_actors::ws;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
@ -55,11 +55,12 @@ use std::time::{Duration, Instant};
|
|||||||
use tokio_codec::{BytesCodec, Decoder, FramedRead};
|
use tokio_codec::{BytesCodec, Decoder, FramedRead};
|
||||||
use tokio_pty_process::{AsyncPtyMaster, AsyncPtyMasterWriteHalf, Child, CommandExt};
|
use tokio_pty_process::{AsyncPtyMaster, AsyncPtyMasterWriteHalf, Child, CommandExt};
|
||||||
|
|
||||||
|
use handlebars::Handlebars;
|
||||||
|
|
||||||
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
|
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
|
const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||||
|
|
||||||
mod event;
|
mod event;
|
||||||
pub mod templates;
|
|
||||||
mod terminado;
|
mod terminado;
|
||||||
|
|
||||||
/// Actix WebSocket actor
|
/// Actix WebSocket actor
|
||||||
@ -175,6 +176,7 @@ impl StreamHandler<ws::Message, ws::ProtocolError> for Websocket {
|
|||||||
}
|
}
|
||||||
ws::Message::Binary(b) => cons.do_send(event::IO::from(b)),
|
ws::Message::Binary(b) => cons.do_send(event::IO::from(b)),
|
||||||
ws::Message::Close(_) => ctx.stop(),
|
ws::Message::Close(_) => ctx.stop(),
|
||||||
|
ws::Message::Nop => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,7 +343,7 @@ pub trait WebTermExt {
|
|||||||
/// Serve the websocket for the webterm
|
/// Serve the websocket for the webterm
|
||||||
fn webterm_socket<F>(self: Self, endpoint: &str, handler: F) -> Self
|
fn webterm_socket<F>(self: Self, endpoint: &str, handler: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&actix_web::Request) -> Command + 'static;
|
F: Clone + Fn(&actix_web::HttpRequest) -> Command + 'static;
|
||||||
|
|
||||||
fn webterm_ui(
|
fn webterm_ui(
|
||||||
self: Self,
|
self: Self,
|
||||||
@ -351,14 +353,27 @@ pub trait WebTermExt {
|
|||||||
) -> Self;
|
) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebTermExt for App<()> {
|
impl<T, B> WebTermExt for App<T, B>
|
||||||
|
where
|
||||||
|
B: actix_web::body::MessageBody,
|
||||||
|
T: actix_service::NewService<
|
||||||
|
Config = (),
|
||||||
|
Request = actix_web::dev::ServiceRequest,
|
||||||
|
Response = actix_web::dev::ServiceResponse<B>,
|
||||||
|
Error = actix_web::Error,
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
{
|
||||||
fn webterm_socket<F>(self: Self, endpoint: &str, handler: F) -> Self
|
fn webterm_socket<F>(self: Self, endpoint: &str, handler: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&actix_web::Request) -> Command + 'static,
|
F: Clone + Fn(&actix_web::HttpRequest) -> Command + 'static,
|
||||||
{
|
{
|
||||||
self.resource(endpoint, move |r| {
|
self.route(
|
||||||
r.f(move |req| ws::start(req, Websocket::new(handler(req))))
|
endpoint,
|
||||||
})
|
web::get().to(move |req: HttpRequest, stream: web::Payload| {
|
||||||
|
ws::start(Websocket::new(handler(&req)), &req, stream)
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn webterm_ui(
|
fn webterm_ui(
|
||||||
@ -367,9 +382,23 @@ impl WebTermExt for App<()> {
|
|||||||
webterm_socket_endpoint: &str,
|
webterm_socket_endpoint: &str,
|
||||||
static_path: &str,
|
static_path: &str,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let template = templates::WebTerm::new(webterm_socket_endpoint, static_path);
|
let mut handlebars = Handlebars::new();
|
||||||
self.resource(endpoint, move |r| {
|
handlebars
|
||||||
r.get().f(move |_| template.into_response())
|
.register_templates_directory(".html", "./templates")
|
||||||
})
|
.unwrap();
|
||||||
|
let handlebars_ref = web::Data::new(handlebars);
|
||||||
|
let static_path = static_path.to_owned();
|
||||||
|
let webterm_socket_endpoint = webterm_socket_endpoint.to_owned();
|
||||||
|
self.register_data(handlebars_ref.clone()).route(
|
||||||
|
endpoint,
|
||||||
|
web::get().to(move |hb: web::Data<Handlebars>| {
|
||||||
|
let data = json!({
|
||||||
|
"websocket_path": webterm_socket_endpoint,
|
||||||
|
"static_path": static_path,
|
||||||
|
});
|
||||||
|
let body = hb.render("term", &data).unwrap();
|
||||||
|
HttpResponse::Ok().body(body)
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
extern crate actix;
|
extern crate actix;
|
||||||
extern crate actix_web;
|
extern crate actix_web;
|
||||||
extern crate webterm;
|
|
||||||
extern crate structopt;
|
extern crate structopt;
|
||||||
|
extern crate webterm;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
use actix_web::{fs::StaticFiles, server, App};
|
use actix_web::{App, HttpServer};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use webterm::WebTermExt;
|
use webterm::WebTermExt;
|
||||||
|
|
||||||
@ -31,18 +31,12 @@ lazy_static! {
|
|||||||
static ref OPT: Opt = Opt::from_args();
|
static ref OPT: Opt = Opt::from_args();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
server::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.handler(
|
.service(actix_files::Files::new("/static", "./node_modules"))
|
||||||
"/static",
|
|
||||||
StaticFiles::new("node_modules")
|
|
||||||
.unwrap()
|
|
||||||
.show_files_listing(),
|
|
||||||
)
|
|
||||||
.webterm_socket("/websocket", |_req| {
|
.webterm_socket("/websocket", |_req| {
|
||||||
let mut cmd = Command::new(OPT.command.clone());
|
let mut cmd = Command::new(OPT.command.clone());
|
||||||
cmd.env("TERM", "xterm");
|
cmd.env("TERM", "xterm");
|
||||||
@ -52,5 +46,6 @@ fn main() {
|
|||||||
})
|
})
|
||||||
.bind(format!("{}:{}", OPT.host, OPT.port))
|
.bind(format!("{}:{}", OPT.host, OPT.port))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.run();
|
.run()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
use askama::Template;
|
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "term.html")]
|
|
||||||
pub struct WebTerm {
|
|
||||||
websocket_path: String,
|
|
||||||
static_path: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WebTerm {
|
|
||||||
pub fn new<S>(websocket_path: S, static_path: S) -> Self
|
|
||||||
where
|
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
Self {
|
|
||||||
websocket_path: websocket_path.into(),
|
|
||||||
static_path: static_path.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -7,12 +7,12 @@ SPDX-License-Identifier: BSD-3-Clause
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="stylesheet" href="{{ static_path|safe }}/xterm/dist/xterm.css" />
|
<link rel="stylesheet" href="{{ static_path }}/xterm/dist/xterm.css" />
|
||||||
<script src="{{ static_path|safe }}/xterm/dist/xterm.js"></script>
|
<script src="{{ static_path }}/xterm/dist/xterm.js"></script>
|
||||||
<script src="{{ static_path|safe }}/xterm/dist/addons/attach/attach.js"></script>
|
<script src="{{ static_path }}/xterm/dist/addons/attach/attach.js"></script>
|
||||||
<script src="{{ static_path|safe }}/xterm/dist/addons/terminado/terminado.js"></script>
|
<script src="{{ static_path }}/xterm/dist/addons/terminado/terminado.js"></script>
|
||||||
<script src="{{ static_path|safe }}/xterm/dist/addons/fit/fit.js"></script>
|
<script src="{{ static_path }}/xterm/dist/addons/fit/fit.js"></script>
|
||||||
<script src="{{ static_path|safe }}/xterm/dist/addons/search/search.js"></script>
|
<script src="{{ static_path }}/xterm/dist/addons/search/search.js"></script>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -32,7 +32,7 @@ SPDX-License-Identifier: BSD-3-Clause
|
|||||||
|
|
||||||
var term = new Terminal();
|
var term = new Terminal();
|
||||||
var protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
var protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
|
||||||
var socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + "{{ websocket_path|safe }}";
|
var socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + "{{ websocket_path }}";
|
||||||
var sock = new WebSocket(socketURL);
|
var sock = new WebSocket(socketURL);
|
||||||
|
|
||||||
sock.addEventListener('open', function() {
|
sock.addEventListener('open', function() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user