Skip to content

Commit

Permalink
Feat: Add 'log_error' attribute to allow errors to pass through inste…
Browse files Browse the repository at this point in the history
…ad of triggering Worker Threw Exception (cloudflare#13)

* add log_error attribute

* added console logging and renamed attribute

Co-authored-by: Leo Orshansky <[email protected]>
  • Loading branch information
leoorshansky and Leo Orshansky authored Aug 6, 2021
1 parent 7034fa4 commit b5adcca
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 16 deletions.
60 changes: 48 additions & 12 deletions macros/cf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Ident, Comma> = 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`");

Expand All @@ -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<worker::Response> 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 =
Expand All @@ -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());
Expand All @@ -72,7 +109,6 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream {

TokenStream::from(output)
}
_ => exit_missing_attr(),
}
}

Expand Down
8 changes: 4 additions & 4 deletions rust-sandbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn handle_a_request(_req: Request, _env: Env, _params: Params) -> Result<Respons
Response::ok("weeee")
}

#[cf::worker(fetch)]
#[cf::worker(fetch, respond_with_errors)]
pub async fn main(req: Request, env: Env) -> Result<Response> {
utils::set_panic_hook();

Expand Down Expand Up @@ -111,13 +111,13 @@ pub async fn main(req: Request, env: Env) -> Result<Response> {
))
})?;

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::<ObjectNamespace>("COUNTER")?;
let stub = namespace.id_from_name("A")?.get_stub()?;
stub.fetch_with_str("/").await
Expand Down
1 change: 1 addition & 0 deletions worker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down

0 comments on commit b5adcca

Please sign in to comment.