feat: update container

This commit is contained in:
2022-07-23 00:21:43 +08:00
parent 0415152500
commit a116b1c2e6
2 changed files with 139 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FnResult {
error: Option<String>,
result: Option<String>,
}
impl FnResult {
pub fn fail(message: impl Into<String>) -> Self {
FnResult {
result: None,
error: Some(message.into()),
}
}
pub fn success(result: String) -> Self {
FnResult {
result: Some(result),
error: None,
}
}
pub fn to_json(&self) -> String {
serde_json::to_string(&self).expect("JSResult to json error")
}
}

View File

@@ -0,0 +1,112 @@
use std::collections::BTreeMap;
use std::io::{ErrorKind, Read, Write};
use std::time::Duration;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Number, Value};
use crate::fn_common::FnResult;
#[derive(Clone, Debug, Serialize, Deserialize)]
struct FetchParams {
url: String,
options: Option<FetchOptions>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct FetchOptions {
method: Option<String>,
headers: Option<BTreeMap<String, String>>,
body: Option<String>,
}
pub fn do_fetch(params: &str) -> FnResult {
let fetch_params: FetchParams = match serde_json::from_str(params) {
Err(e) => return FnResult::fail(format!("Fetch param parse error: {}, raw params: {}", e, params)),
Ok(params) => params,
};
if fetch_params.url.is_empty() {
return FnResult::fail("Param url cannot be empty");
}
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 FnResult::fail(format!("Create client failed: {}", e)),
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 FnResult::fail(format!("Unsupported method: {}", m)),
};
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 mut fetch_response = match request_builder.send() {
Err(e) => return FnResult::fail(format!("Send request failed: {}", e)),
Ok(fetch_response) => fetch_response,
};
let status = fetch_response.status().as_u16();
let headers = fetch_response.headers().clone();
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 FnResult::fail(format!("Fetch response failed: {}", e)),
Ok(len) => if len == 0 {
break;
} else {
if let Err(e) = body_buff.write_all(&buff[0..len]) {
return FnResult::fail(format!("Fetch response failed: {}", e));
}
if body_buff.len() > 1024 * 1024 {
return FnResult::fail(format!("Fetch response too large, {} more than 1MB", body_buff.len()));
}
}
}
}
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()));
FnResult::success(format!("{}", Value::Object(result_map)))
}