From 7f4c396e4dac78ff9dfd07879173b52ada93864a Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 31 Mar 2021 15:18:55 +0900 Subject: [PATCH] Migrate to actix-web from rouille --- Cargo.toml | 2 +- src/web_server.rs | 204 +++++++++++++++++++++++++++++----------------- 2 files changed, 132 insertions(+), 74 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 627d7c6..aee23b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/web_server.rs b/src/web_server.rs index 6c3162d..5e7bf8f 100644 --- a/src/web_server.rs +++ b/src/web_server.rs @@ -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 { @@ -41,6 +44,14 @@ pub struct WebServer { pub current_robot_origin: Arc>, } +#[derive(Debug, Clone)] +struct Data { + target_joint_positions: Arc>, + current_joint_positions: Arc>, + target_robot_origin: Arc>, + current_robot_origin: Arc>, +} + impl WebServer { pub fn new(port: u16) -> Self { Self { @@ -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, + data: web::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, data: web::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) -> 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) -> 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() +}