From ca32d8701cca4939f08a1d7eaf764a2dc0a60a09 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Thu, 21 Jul 2022 01:18:42 +0800 Subject: [PATCH] feat: udpate container --- .../wit-bindgen-sample/container/src/main.rs | 113 +++++++++++++----- 1 file changed, 86 insertions(+), 27 deletions(-) diff --git a/__wasm/wit-bindgen-sample/container/src/main.rs b/__wasm/wit-bindgen-sample/container/src/main.rs index 029bad9..e651239 100644 --- a/__wasm/wit-bindgen-sample/container/src/main.rs +++ b/__wasm/wit-bindgen-sample/container/src/main.rs @@ -1,6 +1,8 @@ +use std::collections::BTreeMap; use std::time::Duration; use anyhow::Result; +use reqwest::Method; use serde::{Deserialize, Serialize}; use wasmtime::{Config, Engine, Instance, Linker, Module, Store}; @@ -13,11 +15,24 @@ struct FetchResult { } impl FetchResult { + fn fail(message: impl Into) -> Self { + FetchResult { + result: None, + error: Some(message.into()), + } + } + fn to_json(&self) -> String { serde_json::to_string(&self).expect("JSResult to json error") } } +impl Into for FetchResult { + fn into(self) -> String { + self.to_json() + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] struct JsResult { message: String, @@ -29,41 +44,85 @@ impl JsResult { } } -pub fn get(url: &str) -> reqwest::Result { - let client = reqwest::blocking::Client::builder() - .timeout(Duration::from_secs(8)) - .connect_timeout(Duration::from_secs(3)) - // .proxy(reqwest::Proxy::all("http://127.0.0.1:1086").expect("to proxy failed")) - .build()?; - let request_builder = client.get(url); - let request_builder = request_builder.header("X-Custom-Header", "Value"); - request_builder.send() +#[derive(Clone, Debug, Serialize, Deserialize)] +struct FetchOptions { + method: Option, + headers: Option>, + body: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct FetchParams { + url: String, + options: Option, } #[derive(Default)] pub struct MyContainer; impl container::Container for MyContainer { - fn fetch(&mut self, s: &str) -> String { - println!("fetch arguments: {}", s); - let url: String = s.chars().skip(1).take(s.len() - 2).collect(); - println!("fetch arguments URL: {}", url); - let r = match get(&url) { - Err(e) => return FetchResult { - error: Some(JsResult { - message: format!("failed: {}", e) - }.to_json()), - result: None, - }.to_json(), - Ok(r) => r, + fn fetch(&mut self, params: &str) -> String { + let fetch_params: FetchParams = match serde_json::from_str(params) { + Err(e) => return FetchResult::fail(format!("Fetch param parse error: {}, raw params: {}", e, params)).to_json(), + Ok(params) => params, + }; + if fetch_params.url.is_empty() { + return FetchResult::fail("Param url cannot be empty").to_json(); + } + let client = match reqwest::blocking::Client::builder() + .timeout(Duration::from_secs(8)) + .connect_timeout(Duration::from_secs(3)) + // .proxy(reqwest::Proxy::all("http://127.0.0.1:1086").expect("to proxy failed")) + .build() { + Err(e) => return FetchResult::fail(format!("Create client failed: {}", e)).to_json(), + Ok(client) => client, + }; + let method = fetch_params.options.as_ref().map(|options| options.method.as_ref().map(|m| m.to_uppercase())).flatten(); + let method_str = method.as_ref().map(|m| m.as_str()).unwrap_or_else(|| "GET"); + let request_method = match method_str { + "GET" => Method::GET, + "POST" => Method::POST, + m => return FetchResult::fail(format!("Unsupported method: {}", m)).to_json(), + }; + let mut request_builder = client.request(request_method.clone(), &fetch_params.url); + if let Some(options) = &fetch_params.options { + let mut has_user_agent = false; + if let Some(headers) = &options.headers { + for (k, v) in headers { + if k.to_lowercase() == "user-agent" { + has_user_agent = true; + } + request_builder = request_builder.header(k.to_string(), v.to_string()); + } + } + if !has_user_agent { + request_builder = request_builder.header("User-Agent", "JavaScriptSandboxContainer/0.1"); + } + + if let Some(body) = &options.body { + if Method::POST == request_method { + let body = reqwest::blocking::Body::from(body.to_string()); + request_builder = request_builder.body(body); + } + } + } + + let fetch_response = match request_builder.send() { + Err(e) => return FetchResult::fail(format!("Send request failed: {}", e)).to_json(), + Ok(fetch_response) => fetch_response, }; - FetchResult { - error: None, - result: Some(JsResult { - message: format!("fetched: {:?}", r.text()), - }.to_json()), - }.to_json() + let status = fetch_response.status().as_u16(); + let headers = fetch_response.headers(); + let body = fetch_response.bytes(); + + // FetchResult { + // error: None, + // result: Some(JsResult { + // message: format!("fetched: {:?}", r.text()), + // }.to_json()), + // }.to_json() + "".to_string() } }