diff --git a/macros/cf/src/lib.rs b/macros/cf/src/lib.rs index d11facf8..4a7457f3 100644 --- a/macros/cf/src/lib.rs +++ b/macros/cf/src/lib.rs @@ -2,21 +2,42 @@ extern crate wasm_bindgen_macro_support; use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, Ident, ItemFn}; +use syn::{Ident, ItemFn, parse_macro_input, punctuated::Punctuated, token::Comma}; #[proc_macro_attribute] pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream { - let exit_missing_attr = - || panic!("must have either 'fetch' or 'scheduled' attribute, e.g. #[cf::worker(fetch)]"); - if attr.is_empty() { - exit_missing_attr(); + let attrs: Punctuated = parse_macro_input!(attr with Punctuated::parse_terminated); + + enum HandlerType { + Fetch, + Scheduled + } + use HandlerType::*; + + let mut handler_type = None; + let mut respond_with_errors = false; + + for attr in attrs { + match attr.to_string().as_str() { + "fetch" => { + handler_type = Some(Fetch) + } + "scheduled" => { + handler_type = Some(Scheduled) + } + "respond_with_errors" => { + respond_with_errors = true; + }, + _ => panic!("Invalid attribute: {}", attr.to_string()) + } } + let handler_type = handler_type.expect("must have either 'fetch' or 'scheduled' attribute, e.g. #[cf::worker(fetch)]"); // create new var using syn item of the attributed fn let mut input_fn = parse_macro_input!(item as ItemFn); - match attr.to_string().as_str() { - "fetch" => { + match handler_type { + Fetch => { // TODO: validate the inputs / signature // let input_arg = input_fn.sig.inputs.first().expect("#[cf::worker(fetch)] attribute requires exactly one input, of type `worker::Request`"); @@ -26,13 +47,29 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream { // rename the original attributed fn input_fn.sig.ident = input_fn_ident.clone(); + let error_handling = match respond_with_errors { + true => { + quote! { + Response::error(e.to_string(), 500).unwrap().into() + } + }, + false => { + quote! { panic!("{}", e) } + } + }; + // create a new "main" function that takes the edgeworker_sys::Request, and calls the // original attributed function, passing in a converted worker::Request let wrapper_fn = quote! { - pub async fn #wrapper_fn_ident(req: ::edgeworker_sys::Request, env: ::worker::Env) -> ::worker::Result<::edgeworker_sys::Response> { + pub async fn #wrapper_fn_ident(req: ::edgeworker_sys::Request, env: ::worker::Env) -> ::edgeworker_sys::Response { // get the worker::Result by calling the original fn - #input_fn_ident(worker::Request::from(req), env).await - .map(edgeworker_sys::Response::from) + match #input_fn_ident(worker::Request::from(req), env).await.map(edgeworker_sys::Response::from) { + Ok(res) => res, + Err(e) => { + ::worker::prelude::console_log!("{}", &e); + #error_handling + } + } } }; let wasm_bindgen_code = @@ -47,7 +84,7 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream { TokenStream::from(output) } - "scheduled" => { + Scheduled => { // save original fn name for re-use in the wrapper fn let original_input_fn_ident = input_fn.sig.ident.clone(); let output_fn_ident = Ident::new("glue_cron", input_fn.sig.ident.span()); @@ -72,7 +109,6 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream { TokenStream::from(output) } - _ => exit_missing_attr(), } } diff --git a/rust-sandbox/src/lib.rs b/rust-sandbox/src/lib.rs index 4b382e97..db7f4e70 100644 --- a/rust-sandbox/src/lib.rs +++ b/rust-sandbox/src/lib.rs @@ -34,7 +34,7 @@ fn handle_a_request(_req: Request, _env: Env, _params: Params) -> Result Result { utils::set_panic_hook(); @@ -111,13 +111,13 @@ pub async fn main(req: Request, env: Env) -> Result { )) })?; - router.on_async("/proxy_request/:url", |_req, _env, params| { + router.on_async("/proxy_request/*url", |_req, _env, params| { // Must copy the parameters into the heap here for lifetime purposes - let url = params.get("url").unwrap().to_string(); + let url = params.get("url").unwrap().strip_prefix('/').unwrap().to_string(); async move { Fetch::Url(&url).send().await } })?; - router.on_async("durable", |_req, e, _params| async move { + router.on_async("/durable", |_req, e, _params| async move { let namespace = e.get_binding::("COUNTER")?; let stub = namespace.id_from_name("A")?.get_stub()?; stub.fetch_with_str("/").await diff --git a/worker/src/lib.rs b/worker/src/lib.rs index b0eda5c0..f64883de 100644 --- a/worker/src/lib.rs +++ b/worker/src/lib.rs @@ -37,6 +37,7 @@ pub mod prelude { pub use crate::{Date, DateInit}; pub use matchit::Params; pub use web_sys::RequestInit; + pub use edgeworker_sys::console_log; } #[derive(Debug)]