1#![allow(clippy::redundant_clone)]
2
3use proc_macro::TokenStream;
32use quote::quote;
33
34#[proc_macro_attribute]
36pub fn http_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
37 let func = syn::parse_macro_input!(item as syn::ItemFn);
38 let func_name = func.sig.ident.clone();
39
40 let wit_guest_rs = include_str!("./http_handler.rs").to_string();
41 let iface: TokenStream = wit_guest_rs.parse().expect("cannot parse http_handler.rs");
42
43 let iface_impl = quote!(
44
45 use exports::land::http::http_incoming;
46
47 struct HttpImpl;
48
49 impl TryFrom<http_incoming::Request> for Request {
50 type Error = anyhow::Error;
51
52 fn try_from(wasm_req: http_incoming::Request) -> Result<Self, Self::Error> {
53 use std::str::FromStr;
54
55 let mut http_req = http::Request::builder()
56 .method(http::Method::from_str(wasm_req.method.as_str())?)
57 .uri(&wasm_req.uri);
58
59 for (key, value) in wasm_req.headers {
60 http_req = http_req.header(key, value);
61 }
62 let body = Body::from_handle(wasm_req.body.unwrap_or(1));
64 Ok(http_req.body(body)?)
65 }
66 }
67
68 impl TryFrom<Response> for http_incoming::Response {
69 type Error = anyhow::Error;
70
71 fn try_from(http_res: Response) -> Result<Self, Self::Error> {
72 let status = http_res.status().as_u16();
73 let mut headers: Vec<(String, String)> = vec![];
74 for (key, value) in http_res.headers() {
75 headers.push((key.to_string(), value.to_str()?.to_string()));
76 }
77 let body = http_res.body();
78 Ok(http_incoming::Response {
79 status,
80 headers,
81 body: Some(body.body_handle()),
82 })
83 }
84 }
85
86 impl http_incoming::Guest for HttpImpl {
87 fn handle_request(req: http_incoming::Request) -> http_incoming::Response {
88 #func
89
90 let sdk_request: Request = req.try_into().unwrap();
92 let sdk_response = match #func_name(sdk_request){
93 Ok(r) => r,
94 Err(e) => {
95 land_sdk::http::error_response(
96 http::StatusCode::INTERNAL_SERVER_ERROR,
97 e.to_string(),
98 )
99 }
100 };
101
102 let sdk_response_body_handle = sdk_response.body().body_handle();
103 match sdk_response.try_into() {
105 Ok(r) => r,
106 Err(_e) => http_incoming::Response {
107 status: 500,
108 headers: vec![],
109 body: Some(sdk_response_body_handle),
110 },
111 }
112 }
113 }
114
115 );
116 let value = format!("{iface}\n{iface_impl}");
117 value.parse().unwrap()
118}