From 8712d4cd8ba3f31998c18d1c0975c6cec21f0ba3 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 5 Apr 2022 18:16:04 +0900 Subject: [PATCH] frontend: WIP! request id in progress Frontend is able to successfully send a Request, but is failing to get/parse the Response. --- back_end/src/main.rs | 12 ++--- front_end/Cargo.lock | 2 + front_end/Cargo.toml | 6 ++- front_end/src/html_helper.rs | 27 +++++++++--- front_end/src/yew_components.rs | 78 +++++++++++++++++++++++++++------ 5 files changed, 99 insertions(+), 26 deletions(-) diff --git a/back_end/src/main.rs b/back_end/src/main.rs index 29fb1bd..04c86cf 100644 --- a/back_end/src/main.rs +++ b/back_end/src/main.rs @@ -43,19 +43,19 @@ async fn main() { let db_tx_clone = db_tx_clone.clone(); let s_helper_tx_clone = s_helper_tx.clone(); async move { - let body_str_result = std::str::from_utf8(bytes.as_ref()); + let body_str_result = dbg!(std::str::from_utf8(bytes.as_ref())); if let Ok(body_str) = body_str_result { let json_result = serde_json::from_str(body_str); if let Ok(json_value) = json_result { - Ok( - json_handlers::handle_json(json_value, db_tx_clone, s_helper_tx_clone) + Ok(warp::reply::json( + &json_handlers::handle_json(json_value, db_tx_clone, s_helper_tx_clone) .unwrap_or_else(|e| e), - ) + )) } else { - Ok(String::from("{\"type\": \"invalid_syntax\"}")) + Ok(warp::reply::json(&String::from("{\"type\": \"invalid_syntax\"}"))) } } else { - Ok::(String::from("{\"type\": \"invalid_syntax\"}")) + Ok::(warp::reply::json(&String::from("{\"type\": \"invalid_syntax\"}"))) } } }); diff --git a/front_end/Cargo.lock b/front_end/Cargo.lock index d625db5..166986a 100644 --- a/front_end/Cargo.lock +++ b/front_end/Cargo.lock @@ -43,6 +43,8 @@ dependencies = [ "js-sys", "log", "oorandom", + "serde", + "serde_derive", "serde_json", "wasm-bindgen", "wasm-bindgen-futures", diff --git a/front_end/Cargo.toml b/front_end/Cargo.toml index cff3e69..0166b84 100644 --- a/front_end/Cargo.toml +++ b/front_end/Cargo.toml @@ -9,9 +9,11 @@ edition = "2021" yew = "0.19" log = "0.4.6" wasm-logger = "0.2.0" -web-sys = { version = "0.3.56", features = ["Window", "Document", "Element", "Request", "RequestInit"] } +web-sys = { version = "0.3.56", features = ["Window", "Document", "Element", "Request", "RequestInit", "Headers", "RequestMode", "Response", "ReadableStream"] } js-sys = "0.3.56" oorandom = "11.1.3" -wasm-bindgen = "0.2.79" +wasm-bindgen = { version = "0.2.79", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.29" +serde = { version = "1.0", features = ["derive"] } +serde_derive = "1.0" serde_json = "1.0" diff --git a/front_end/src/html_helper.rs b/front_end/src/html_helper.rs index 4bb3368..3d76d3d 100644 --- a/front_end/src/html_helper.rs +++ b/front_end/src/html_helper.rs @@ -82,10 +82,27 @@ pub fn element_remove_class(document: &Document, id: &str, class: &str) -> Resul pub fn create_json_request(target_url: &str, json_body: &str) -> Result { let mut req_init: RequestInit = RequestInit::new(); req_init.body(Some(&JsValue::from_str(json_body))); - req_init.headers( - &JsValue::from_serde("'headers': { 'Content-Type': 'application/json' }") - .map_err(|e| format!("{}", e))?, - ); + req_init.method("POST"); + // TODO omit the NoCors when hosted on website + req_init.mode(web_sys::RequestMode::NoCors); + // req_init.headers( + // &JsValue::from_str("{'Content-Type': 'application/json'}"), + // &JsValue::from_serde("{'Content-Type': 'application/json'}") + // .map_err(|e| format!("{}", e))?, + // &JsValue::from_serde("'headers': { 'Content-Type': 'application/json' }") + // .map_err(|e| format!("{}", e))?, + // ); - Ok(Request::new_with_str_and_init(target_url, &req_init).map_err(|e| format!("{:?}", e))?) + let request: Request = + Request::new_with_str_and_init(target_url, &req_init).map_err(|e| format!("{:?}", e))?; + request + .headers() + .set("Content-Type", "application/json") + .map_err(|e| format!("{:?}", e))?; + request + .headers() + .set("Accept", "application/json") + .map_err(|e| format!("{:?}", e))?; + + Ok(request) } diff --git a/front_end/src/yew_components.rs b/front_end/src/yew_components.rs index cf22d4e..7c03453 100644 --- a/front_end/src/yew_components.rs +++ b/front_end/src/yew_components.rs @@ -14,11 +14,12 @@ use crate::state::{BoardState, GameState, MainMenuMessage, SharedState, Turn}; use std::cell::Cell; use std::rc::Rc; -use js_sys::{JsString, Promise}; +use js_sys::{Function, Promise}; +use wasm_bindgen::JsCast; +use web_sys::Response; use serde_json::Value as SerdeJSONValue; -use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen_futures::JsFuture; use yew::prelude::*; @@ -287,25 +288,53 @@ impl Wrapper { // get window let window = web_sys::window().expect("Should be able to get Window"); // get request - let request = create_json_request(BACKEND_URL, "'type': 'pairing_request'") + let request = create_json_request(BACKEND_URL, "{\"type\": \"pairing_request\"}") .expect("Should be able to create the JSON request for player_id"); // send request let promise = window.fetch_with_request(&request); // get request result - let response_result = JsFuture::from(promise) + let jsvalue_result = JsFuture::from(promise) .await .map_err(|e| format!("{:?}", e)); - if let Err(e) = response_result { - return WrapperMsg::BackendResponse(BREnum::Error(format!("ERROR: {:?}", e))); + if let Err(e) = jsvalue_result { + return WrapperMsg::BackendResponse(BREnum::Error(format!( + "ERROR jsvalue_result: {:?}", + e + ))); } + log::warn!("{:?}", jsvalue_result.as_ref().unwrap()); // get response from request result - let response = response_result.unwrap(); - let json_value_result: Result = response.into_serde(); - if let Err(e) = json_value_result { - return WrapperMsg::BackendResponse(BREnum::Error(format!("ERROR: {:?}", e))); + let response_result: Result = jsvalue_result.unwrap().dyn_into(); + if let Err(e) = response_result { + return WrapperMsg::BackendResponse(BREnum::Error(format!( + "ERROR response_result: {:?}", + e + ))); + } + let json_jsvalue_promise_result = response_result.unwrap().json(); + if let Err(e) = json_jsvalue_promise_result { + return WrapperMsg::BackendResponse(BREnum::Error(format!( + "ERROR json_jsvalue_promise_result: {:?}", + e + ))); + } + let json_jsvalue_result = JsFuture::from(json_jsvalue_promise_result.unwrap()).await; + if let Err(e) = json_jsvalue_result { + return WrapperMsg::BackendResponse(BREnum::Error(format!( + "ERROR json_jsvalue_result: {:?}", + e + ))); + } + let json_result = json_jsvalue_result.unwrap().into_serde(); + if let Err(e) = json_result { + return WrapperMsg::BackendResponse(BREnum::Error(format!( + "ERROR json_result: {:?}", + e + ))); } // get serde json Value from result - let json_value = json_value_result.unwrap(); + let json_value: SerdeJSONValue = json_result.unwrap(); + log::warn!("{:?}", json_value); // get and check "type" in JSON let type_opt = json_value.get("type"); @@ -378,8 +407,24 @@ impl Wrapper { )); } - // TODO set "disconnect" callback here so that the client sends + // set "disconnect" callback here so that the client sends // disconnect message when the page is closed + let function = Function::new_no_args(&format!( + " + window.onunload = function(event) {{ + let request_conf = {{}}; + request_conf.method = 'POST'; + request_conf.headers = \"'Content-Type': 'application/json'\"; + request_conf.body = \"{{ \"type\": \"disconnect\", \"id\": {} }}\"; + + const request = new Request('{}', request_conf); + + fetch(request); + }}; + ", + player_id, BACKEND_URL + )); + function.call0(&function).ok(); if status == Status::Paired { // Get which side current player is on if paired @@ -1006,7 +1051,14 @@ impl Component for Wrapper { WrapperMsg::BackendRequest { place } => { self.place_request = Some(place); } - WrapperMsg::BackendResponse(string) => {} + WrapperMsg::BackendResponse(br_enum) => match br_enum { + BREnum::Error(string) => { + log::warn!("{}", string); + } + BREnum::GotID(id, turn_opt) => { + self.player_id = Some(id); + } + }, } // match (msg) true