From d90b1e69ea2778181661a1fa3e6620afe9018f74 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Fri, 22 Jul 2022 23:54:20 +0800 Subject: [PATCH] feat: update fetch --- .../wit-bindgen-sample/container/src/main.rs | 111 ++++++++++++------ __wasm/wit-bindgen-sample/engine/src/lib.rs | 19 ++- 2 files changed, 82 insertions(+), 48 deletions(-) diff --git a/__wasm/wit-bindgen-sample/container/src/main.rs b/__wasm/wit-bindgen-sample/container/src/main.rs index e651239..05f88ca 100644 --- a/__wasm/wit-bindgen-sample/container/src/main.rs +++ b/__wasm/wit-bindgen-sample/container/src/main.rs @@ -1,9 +1,13 @@ +extern crate core; + use std::collections::BTreeMap; +use std::io::{ErrorKind, Read, Write}; use std::time::Duration; use anyhow::Result; use reqwest::Method; use serde::{Deserialize, Serialize}; +use serde_json::{Map, Number, Value}; use wasmtime::{Config, Engine, Instance, Linker, Module, Store}; wit_bindgen_wasmtime::export!("../container.wit"); @@ -22,6 +26,13 @@ impl FetchResult { } } + fn success(result: String) -> Self { + FetchResult { + result: Some(result), + error: None, + } + } + fn to_json(&self) -> String { serde_json::to_string(&self).expect("JSResult to json error") } @@ -34,14 +45,9 @@ impl Into for FetchResult { } #[derive(Clone, Debug, Serialize, Deserialize)] -struct JsResult { - message: String, -} - -impl JsResult { - fn to_json(&self) -> String { - serde_json::to_string(&self).expect("JSResult to json error") - } +struct FetchParams { + url: String, + options: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -51,12 +57,6 @@ struct FetchOptions { body: Option, } -#[derive(Clone, Debug, Serialize, Deserialize)] -struct FetchParams { - url: String, - options: Option, -} - #[derive(Default)] pub struct MyContainer; @@ -107,22 +107,49 @@ impl container::Container for MyContainer { } } - let fetch_response = match request_builder.send() { + let mut fetch_response = match request_builder.send() { Err(e) => return FetchResult::fail(format!("Send request failed: {}", e)).to_json(), Ok(fetch_response) => fetch_response, }; let status = fetch_response.status().as_u16(); - let headers = fetch_response.headers(); - let body = fetch_response.bytes(); + let headers = fetch_response.headers().clone(); - // FetchResult { - // error: None, - // result: Some(JsResult { - // message: format!("fetched: {:?}", r.text()), - // }.to_json()), - // }.to_json() - "".to_string() + let mut body_buff = Vec::new(); + let mut buff = [0_u8; 1024]; + loop { + match fetch_response.read(&mut buff) { + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return FetchResult::fail(format!("Fetch response failed: {}", e)).to_json(), + Ok(len) => if len == 0 { + break; + } else { + if let Err(e) = body_buff.write_all(&buff[0..len]) { + return FetchResult::fail(format!("Fetch response failed: {}", e)).to_json(); + } + if body_buff.len() > 1024 * 1024 { + return FetchResult::fail(format!("Fetch response too large, {} more than 1MB", body_buff.len())).to_json(); + } + } + } + } + + let mut result_map = Map::new(); + result_map.insert("status".to_string(), Value::Number(Number::from(status))); + let mut header_map = Map::new(); + for (k, v) in headers { + let header_key = k.map(|n| n.as_str().to_string()).unwrap_or_else(|| "".to_string()); + let header_value = match v.to_str() { + Err(_) => continue, + Ok(v) => v.to_string(), + }; + header_map.insert(header_key, Value::String(header_value)); + } + result_map.insert("headers".to_string(), Value::Object(header_map)); + result_map.insert("body".to_string(), Value::String(String::from_utf8_lossy(&body_buff).to_string())); + + + FetchResult::success(format!("{}", Value::Object(result_map))).to_json() } } @@ -138,22 +165,30 @@ fn main() -> Result<()> { )?; let a = exports.eval_javascript(&mut store, r##" function hi(name) { return "hi: " + name; } - let a = []; - a.push(fetch('https://hatter.ink/util/print_request.action')); - for (let i = 0; i < 3; i++) { a.push(i); } - a.push({ - id: 1, name: 'hatter' - }); - a.push(hi('001')); - a.push(hi('002')); - // JSON.stringify(a) - a + // let a = []; + // a.push(fetch('https://hatter.ink/util/print_request.action')); + // for (let i = 0; i < 3; i++) { a.push(i); } + // a.push({ + // id: 1, name: 'hatter' + // }); + // a.push(hi('001')); + // a.push(hi('002')); + let a = fetch('https://hatter.ink/util/print_request.action'); + JSON.stringify(a) + // a "##); + let a = a.expect("error"); + let a: Value = serde_json::from_str(&a).expect("error"); + let a = match a { + Value::String(a) => a, + _ => panic!("error"), + }; - match a { - Ok(a) => println!("Hello, world! {:?}", a), - Err(e) => println!("ERROR: {}", e), - } + // println!(">>>>>>> {}", a); + let v: Value = serde_json::from_str(&a).expect("errorr"); + let p = serde_json::to_string_pretty(&v).expect("error"); + // println!("------- {}", v); + println!("{}", p); Ok(()) } diff --git a/__wasm/wit-bindgen-sample/engine/src/lib.rs b/__wasm/wit-bindgen-sample/engine/src/lib.rs index af5001e..cc0b421 100644 --- a/__wasm/wit-bindgen-sample/engine/src/lib.rs +++ b/__wasm/wit-bindgen-sample/engine/src/lib.rs @@ -1,6 +1,6 @@ use boa_engine::{Context, JsResult, JsString, JsValue}; use serde::{Deserialize, Serialize}; -use serde_json::Value; +use serde_json::{Map, Value}; wit_bindgen_rust::export!("../exports.wit"); wit_bindgen_rust::import!("../container.wit"); @@ -28,15 +28,14 @@ struct FetchResult { } fn fetch_fn(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult { - let mut options = String::new(); - options.push('['); - args.iter().enumerate().for_each(|(i, arg)| { - if i > 0 { options.push(','); } - options.push_str(arg.to_json(ctx).expect("to json error").as_str().expect("as str error")) - }); - options.push(']'); - // let r = serde_json::to_string(args).unwrap(); - let fetch_result_string = container::fetch(&options); + let mut fetch_params_map = Map::new(); + fetch_params_map.insert("url".to_string(), args[0].to_json(ctx).expect("error")); + if args.len() > 1 { + fetch_params_map.insert("params".to_string(), args[1].to_json(ctx).expect("error")); + } + let fetch_params = format!("{}", Value::Object(fetch_params_map)); + + let fetch_result_string = container::fetch(&fetch_params); let fetch_result: FetchResult = serde_json::from_str(&fetch_result_string).expect("from str error"); if let Some(result) = fetch_result.result { let r: Value = serde_json::from_str(&result).expect("result from str error");