Skip to content

Commit

Permalink
Migrate to actix-web from rouille
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Mar 31, 2021
1 parent 0b7ae4d commit 7f4c396
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ assimp = ["assimp-crate", "assimp-sys"]

# Note: k, kiss3d, nalgebra, serde, and urdf-rs are public dependencies.
[dependencies]
actix-web = "3"
env_logger = "0.8"
k = "0.23"
kiss3d = "0.30"
log = "0.4"
nalgebra = "0.25"
rand = "0.8"
rouille = "3.0"
serde = { version = "1.0", features = ["derive"] }
structopt = "0.3"
thiserror = "1.0"
Expand Down
204 changes: 131 additions & 73 deletions src/web_server.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use rouille::*;
use actix_web::*;
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
use std::{
io,
sync::{Arc, Mutex},
};

#[derive(Deserialize, Serialize, Debug, Clone, Default)]
pub struct JointNamesAndPositions {
Expand Down Expand Up @@ -41,6 +44,14 @@ pub struct WebServer {
pub current_robot_origin: Arc<Mutex<RobotOrigin>>,
}

#[derive(Debug, Clone)]
struct Data {
target_joint_positions: Arc<Mutex<JointNamesAndPositionsRequest>>,
current_joint_positions: Arc<Mutex<JointNamesAndPositions>>,
target_robot_origin: Arc<Mutex<RobotOriginRequest>>,
current_robot_origin: Arc<Mutex<RobotOrigin>>,
}

impl WebServer {
pub fn new(port: u16) -> Self {
Self {
Expand Down Expand Up @@ -73,76 +84,123 @@ impl WebServer {
self.current_robot_origin.clone(),
)
}
pub fn start(self) {
rouille::start_server(("0.0.0.0", self.port), move |request| {
router!(request,
(POST) (/set_joint_positions) => {
let json: JointNamesAndPositions = try_or_400!(rouille::input::json_input(request));
let mut jp_request = try_or_404!(self.target_joint_positions.lock());
jp_request.joint_positions = json;
let jp = jp_request.joint_positions.clone();
if jp.names.len() != jp.positions.len() {
Response::json(
&ResultResponse {
is_ok: false,
reason: format!("names and positions size mismatch ({} != {})",
jp.names.len(), jp.positions.len()),
})
} else {
jp_request.requested = true;
Response::json(&ResultResponse { is_ok: true, reason: "".to_string() })
}
},
(POST) (/set_robot_origin) => {
let json: RobotOrigin = try_or_400!(rouille::input::json_input(request));
let mut pose_request = try_or_404!(self.target_robot_origin.lock());
pose_request.origin = json;
pose_request.requested = true;
Response::json(&ResultResponse { is_ok: true, reason: "".to_string() })
},
(OPTIONS) (/set_joint_positions) => {
Response::empty_204()
.with_additional_header("Allow", "OPTIONS, POST")
.with_additional_header("Access-Control-Allow-Methods", "POST")
.with_additional_header("Access-Control-Allow-Origin", "*")
.with_additional_header("Access-Control-Allow-Headers", "authorization,content-type")
.with_additional_header("Access-Control-Max-Age", "86400")
},
(OPTIONS) (/set_robot_origin) => {
Response::empty_204()
.with_additional_header("Allow", "OPTIONS, POST")
.with_additional_header("Access-Control-Allow-Methods", "POST")
.with_additional_header("Access-Control-Allow-Origin", "*")
.with_additional_header("Access-Control-Allow-Headers", "authorization,content-type")
.with_additional_header("Access-Control-Max-Age", "86400")
},
(GET) (/get_joint_positions) => {
let ja = try_or_404!(self.current_joint_positions.lock());
Response::json(&*ja)
},
(GET) (/get_robot_origin) => {
let origin = try_or_404!(self.current_robot_origin.lock());
Response::json(&*origin)
},
(OPTIONS) (/get_joint_positions) => {
Response::empty_204()
.with_additional_header("Allow", "OPTIONS, GET")
.with_additional_header("Access-Control-Allow-Methods", "GET")
.with_additional_header("Access-Control-Allow-Origin", "*")
.with_additional_header("Access-Control-Allow-Headers", "authorization")
.with_additional_header("Access-Control-Max-Age", "86400")
},
(OPTIONS) (/get_robot_origin) => {
Response::empty_204()
.with_additional_header("Allow", "OPTIONS, GET")
.with_additional_header("Access-Control-Allow-Methods", "GET")
.with_additional_header("Access-Control-Allow-Origin", "*")
.with_additional_header("Access-Control-Allow-Headers", "authorization")
.with_additional_header("Access-Control-Max-Age", "86400")
},

_ => Response::empty_404(),
)
});

#[actix_web::main]
pub async fn start(self) -> io::Result<()> {
let data = Data {
target_joint_positions: self.target_joint_positions,
current_joint_positions: self.current_joint_positions,
target_robot_origin: self.target_robot_origin,
current_robot_origin: self.current_robot_origin,
};

HttpServer::new(move || {
App::new()
.data(data.clone())
.service(set_joint_positions)
.service(set_robot_origin)
.service(options_set_joint_positions)
.service(options_set_robot_origin)
.service(get_joint_positions)
.service(get_robot_origin)
.service(options_get_joint_positions)
.service(options_get_robot_origin)
})
.bind(("0.0.0.0", self.port))?
.run()
.await
}
}

#[post("set_joint_positions")]
async fn set_joint_positions(
json: web::Json<JointNamesAndPositions>,
data: web::Data<Data>,
) -> HttpResponse {
let mut jp_request = data.target_joint_positions.lock().unwrap();
jp_request.joint_positions = json.into_inner();
let jp = jp_request.joint_positions.clone();
if jp.names.len() != jp.positions.len() {
HttpResponse::Ok().json(&ResultResponse {
is_ok: false,
reason: format!(
"names and positions size mismatch ({} != {})",
jp.names.len(),
jp.positions.len()
),
})
} else {
jp_request.requested = true;
HttpResponse::Ok().json(&ResultResponse {
is_ok: true,
reason: "".to_string(),
})
}
}

#[post("set_robot_origin")]
async fn set_robot_origin(json: web::Json<RobotOrigin>, data: web::Data<Data>) -> HttpResponse {
let mut pose_request = data.target_robot_origin.lock().unwrap();
pose_request.origin = json.into_inner();
pose_request.requested = true;
HttpResponse::Ok().json(&ResultResponse {
is_ok: true,
reason: "".to_string(),
})
}

#[options("set_joint_positions")]
async fn options_set_joint_positions() -> HttpResponse {
HttpResponse::NoContent()
.header("Allow", "OPTIONS, POST")
.header("Access-Control-Allow-Methods", "POST")
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "authorization,content-type")
.header("Access-Control-Max-Age", "86400")
.finish()
}

#[options("set_robot_origin")]
async fn options_set_robot_origin() -> HttpResponse {
HttpResponse::NoContent()
.header("Allow", "OPTIONS, POST")
.header("Access-Control-Allow-Methods", "POST")
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "authorization,content-type")
.header("Access-Control-Max-Age", "86400")
.finish()
}

#[get("get_joint_positions")]
async fn get_joint_positions(server: web::Data<Data>) -> HttpResponse {
let json = server.current_joint_positions.lock().unwrap();
HttpResponse::Ok().json(&*json)
}

#[get("get_robot_origin")]
async fn get_robot_origin(server: web::Data<Data>) -> HttpResponse {
let origin = server.current_robot_origin.lock().unwrap();
HttpResponse::Ok().json(&*origin)
}

#[options("get_joint_positions")]
async fn options_get_joint_positions() -> HttpResponse {
HttpResponse::NoContent()
.header("Allow", "OPTIONS, GET")
.header("Access-Control-Allow-Methods", "GET")
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "authorization")
.header("Access-Control-Max-Age", "86400")
.finish()
}

#[options("get_robot_origin")]
async fn options_get_robot_origin() -> HttpResponse {
HttpResponse::NoContent()
.header("Allow", "OPTIONS, GET")
.header("Access-Control-Allow-Methods", "GET")
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "authorization")
.header("Access-Control-Max-Age", "86400")
.finish()
}

0 comments on commit 7f4c396

Please sign in to comment.