@@ -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+
1260impl 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