Skip to content

Commit 19fb41f

Browse files
Extract standard library HTTP registry exports
Introduces an `execute_request!` macro in `stdlib/src/http.rs` to abstract the capability checking, error handling, and response processing for HTTP requests. This heavily reduces duplicated logic across the `get` and `post` handlers. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com>
1 parent 5afb72b commit 19fb41f

1 file changed

Lines changed: 50 additions & 84 deletions

File tree

‎stdlib/src/http.rs‎

Lines changed: 50 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,54 @@ use techscript_runtime::{
99
value::RuntimeValue,
1010
};
1111

12+
macro_rules! execute_request {
13+
($ctx:expr, $req_name:expr, $req:expr) => {{
14+
if !$ctx.config.capabilities.contains(&Capability::Network) {
15+
return Err(RuntimeError::new(
16+
RuntimeErrorKind::InvalidOperation(
17+
"Security policy violation: Network capability is denied".to_string(),
18+
),
19+
None,
20+
None,
21+
));
22+
}
23+
24+
let response = $req.map_err(|e| {
25+
RuntimeError::new(
26+
RuntimeErrorKind::InvalidOperation(format!(
27+
"HTTP {} request failed: {}",
28+
$req_name, e
29+
)),
30+
None,
31+
None,
32+
)
33+
})?;
34+
35+
let status = response.status();
36+
let body = response.into_string().map_err(|e| {
37+
RuntimeError::new(
38+
RuntimeErrorKind::InvalidOperation(format!(
39+
"Failed to read HTTP response body: {}",
40+
e
41+
)),
42+
None,
43+
None,
44+
)
45+
})?;
46+
47+
// ⚡ Bolt Performance Optimization:
48+
// Pre-allocating the IndexMap capacity matching the expected number of keys
49+
// avoids intermediate allocations and re-hashing during insertion.
50+
let mut res_map = IndexMap::with_capacity(2);
51+
res_map.insert("status".to_string(), RuntimeValue::Int(status as i64));
52+
res_map.insert("body".to_string(), RuntimeValue::Str(body));
53+
Ok(RuntimeValue::Map {
54+
entries: Rc::new(RefCell::new(res_map)),
55+
is_const: false,
56+
})
57+
}};
58+
}
59+
1260
impl StdlibRegistry {
1361
pub fn register_http(&mut self) {
1462
let mut exports: HashMap<String, Rc<dyn techscript_runtime::function::Callable>> =
@@ -20,49 +68,8 @@ impl StdlibRegistry {
2068
name: "get".to_string(),
2169
arity: 1,
2270
callback: |ctx, args| {
23-
if !ctx.config.capabilities.contains(&Capability::Network) {
24-
return Err(RuntimeError::new(
25-
RuntimeErrorKind::InvalidOperation(
26-
"Security policy violation: Network capability is denied"
27-
.to_string(),
28-
),
29-
None,
30-
None,
31-
));
32-
}
3371
let url = args[0].try_into_string()?;
34-
let response = ureq::get(&url).call().map_err(|e| {
35-
RuntimeError::new(
36-
RuntimeErrorKind::InvalidOperation(format!(
37-
"HTTP GET request failed: {}",
38-
e
39-
)),
40-
None,
41-
None,
42-
)
43-
})?;
44-
let status = response.status();
45-
let body = response.into_string().map_err(|e| {
46-
RuntimeError::new(
47-
RuntimeErrorKind::InvalidOperation(format!(
48-
"Failed to read HTTP response body: {}",
49-
e
50-
)),
51-
None,
52-
None,
53-
)
54-
})?;
55-
56-
// ⚡ Bolt Performance Optimization:
57-
// Pre-allocating the IndexMap capacity matching the expected number of keys
58-
// avoids intermediate allocations and re-hashing during insertion.
59-
let mut res_map = IndexMap::with_capacity(2);
60-
res_map.insert("status".to_string(), RuntimeValue::Int(status as i64));
61-
res_map.insert("body".to_string(), RuntimeValue::Str(body));
62-
Ok(RuntimeValue::Map {
63-
entries: Rc::new(RefCell::new(res_map)),
64-
is_const: false,
65-
})
72+
execute_request!(ctx, "GET", ureq::get(&url).call())
6673
},
6774
}),
6875
);
@@ -73,50 +80,9 @@ impl StdlibRegistry {
7380
name: "post".to_string(),
7481
arity: 2,
7582
callback: |ctx, args| {
76-
if !ctx.config.capabilities.contains(&Capability::Network) {
77-
return Err(RuntimeError::new(
78-
RuntimeErrorKind::InvalidOperation(
79-
"Security policy violation: Network capability is denied"
80-
.to_string(),
81-
),
82-
None,
83-
None,
84-
));
85-
}
8683
let url = args[0].try_into_string()?;
8784
let body = args[1].try_into_string()?;
88-
let response = ureq::post(&url).send_string(&body).map_err(|e| {
89-
RuntimeError::new(
90-
RuntimeErrorKind::InvalidOperation(format!(
91-
"HTTP POST request failed: {}",
92-
e
93-
)),
94-
None,
95-
None,
96-
)
97-
})?;
98-
let status = response.status();
99-
let res_body = response.into_string().map_err(|e| {
100-
RuntimeError::new(
101-
RuntimeErrorKind::InvalidOperation(format!(
102-
"Failed to read HTTP response body: {}",
103-
e
104-
)),
105-
None,
106-
None,
107-
)
108-
})?;
109-
110-
// ⚡ Bolt Performance Optimization:
111-
// Pre-allocating the IndexMap capacity matching the expected number of keys
112-
// avoids intermediate allocations and re-hashing during insertion.
113-
let mut res_map = IndexMap::with_capacity(2);
114-
res_map.insert("status".to_string(), RuntimeValue::Int(status as i64));
115-
res_map.insert("body".to_string(), RuntimeValue::Str(res_body));
116-
Ok(RuntimeValue::Map {
117-
entries: Rc::new(RefCell::new(res_map)),
118-
is_const: false,
119-
})
85+
execute_request!(ctx, "POST", ureq::post(&url).send_string(&body))
12086
},
12187
}),
12288
);

0 commit comments

Comments
 (0)