1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use TokenStream;
/// Integrate the struct with the Workers Runtime as Durable Object.\
/// Requires the `DurableObject` trait with the durable_object attribute macro on the struct.
///
/// ## Example
///
/// ```rust
/// #[durable_object]
/// pub struct Chatroom {
/// users: Vec<User>,
/// messages: Vec<Message>,
/// state: State,
/// env: Env, // access `Env` across requests, use inside `fetch`
/// }
///
/// impl DurableObject for Chatroom {
/// fn new(state: State, env: Env) -> Self {
/// Self {
/// users: vec![],
/// messages: vec![],
/// state,
/// env,
/// }
/// }
///
/// async fn fetch(&self, _req: Request) -> Result<Response> {
/// // do some work when a worker makes a request to this DO
/// Response::ok(&format!("{} active users.", self.users.len()))
/// }
/// }
/// ```
///
/// ## Note
///
/// By default all durable object events are enabled.
/// Arguments may be provided to the macro to only generate the desired events, and reduce the generated JS & Wasm output:
///
/// * `fetch`: simple `fetch` target
/// * `alarm`: with [Alarms API](https://developers.cloudflare.com/durable-objects/examples/alarms-api/)
/// * `websocket`: [WebSocket server](https://developers.cloudflare.com/durable-objects/examples/websocket-hibernation-server/)
///
/// ```rust
/// #[durable_object(fetch)]
/// pub struct Chatroom {
/// users: Vec<User>,
/// messages: Vec<Message>,
/// state: State,
/// env: Env, // access `Env` across requests, use inside `fetch`
/// }
/// ```
/// The `event` macro is used to denote a [Worker handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/), essentially binding from
/// the JS runtime to a Rust function.
///
/// As of right now, the following attributes are supported:
/// * `fetch`: [Fetch Handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/)
/// * `scheduled`: [Scheduled Handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/scheduled/)
/// * `queue`: [Queue Handler](https://developers.cloudflare.com/queues/reference/javascript-apis/#consumer)
/// * This attribute is only available when the `queue` feature is enabled.
/// * `start`: merely creates a [wasm-bindgen start function](https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-rust-exports/start.html)
/// * `respond_with_errors`: if this attribute is present, the function will return a `Response` object with a 500 status code and the status text of the error message, if an error occurs
///
/// The macro is expanded into a different function signature, depending on the attributes used
///
/// # Fetch
///
/// At a high-level, the `fetch` handler is used to handle incoming HTTP requests. The function signature for a `fetch` handler is conceptually something like:
///
/// ```rust
/// async fn fetch(req: impl From<web_sys::Request>, env: Env, ctx: Context) -> Result<impl Into<web_sys::Response>, impl Into<Box<dyn Error>>>
/// ```
///
/// In other words, it takes some "request" object that can be derived *from* a `web_sys::Request` (into whatever concrete Request type you like),
/// and returns some "response" object that can be converted *into* a `web_sys::Response` (from whatever concrete Response type you like).
/// Error types can be any type that implements [`std::error::Error`].
///
/// In practice, the "request" and "response" objects are usually one of these concrete types, supported out of the box:
///
/// ### worker::{Request, Response}
///
/// ```rust
/// #[event(fetch, respond_with_errors)]
/// async fn main(req: worker::Request, env: Env, ctx: Context) -> Result<worker::Response> {
/// worker::Response::ok("Hello World (worker type)")
/// }
/// ```
///
/// ### web_sys::{Request, Response}
///
/// ```rust
/// #[event(fetch, respond_with_errors)]
/// async fn main(req: web_sys::Request, env: Env, ctx: Context) -> Result<web_sys::Response> {
/// Ok(web_sys::Response::new_with_opt_str(Some("Hello World (native type)".into())).unwrap())
/// }
/// ```
///
/// ### axum (with `http` feature)
///
/// ```rust
/// #[event(fetch)]
/// async fn fetch(req: HttpRequest, env: Env, ctx: Context) -> Result<http::Response<axum::body::Body>> {
/// Ok(router().call(req).await?)
/// }
/// ```
/// Convert an async function which is `!Send` to be `Send`.
///
/// This is useful for implementing async handlers in frameworks which
/// expect the handler to be `Send`, such as `axum`.
///
/// ```rust
/// #[worker::send]
/// async fn foo() {
/// // JsFuture is !Send
/// let fut = JsFuture::from(promise);
/// fut.await
/// }
/// ```