hyperlane_macros/lib.rs
1//! hyperlane-macros
2//!
3//! A comprehensive collection of procedural macros for building
4//! HTTP servers with enhanced functionality. This crate provides
5//! attribute macros that simplify HTTP request handling, protocol
6//! validation, response management, and request data extraction.
7
8mod aborted;
9mod closed;
10mod common;
11mod filter;
12mod flush;
13mod from_stream;
14mod hook;
15mod host;
16mod http;
17mod hyperlane;
18mod inject;
19mod protocol;
20mod referer;
21mod reject;
22mod request;
23mod request_middleware;
24mod response;
25mod response_middleware;
26mod route;
27mod send;
28mod stream;
29
30pub(crate) use aborted::*;
31pub(crate) use closed::*;
32pub(crate) use common::*;
33pub(crate) use filter::*;
34pub(crate) use flush::*;
35pub(crate) use from_stream::*;
36pub(crate) use hook::*;
37pub(crate) use host::*;
38pub(crate) use http::*;
39pub(crate) use hyperlane::*;
40pub(crate) use inject::*;
41pub(crate) use protocol::*;
42pub(crate) use referer::*;
43pub(crate) use reject::*;
44pub(crate) use request::*;
45pub(crate) use request_middleware::*;
46pub(crate) use response::*;
47pub(crate) use response_middleware::*;
48pub(crate) use route::*;
49pub(crate) use send::*;
50pub(crate) use stream::*;
51
52pub(crate) use proc_macro::TokenStream;
53pub(crate) use proc_macro2::TokenStream as TokenStream2;
54pub(crate) use quote::quote;
55pub(crate) use syn::{
56 Ident, Token,
57 parse::{Parse, ParseStream, Parser, Result},
58 punctuated::Punctuated,
59 token::Comma,
60 *,
61};
62
63inventory::collect!(InjectableMacro);
64
65/// Restricts function execution to HTTP GET requests only.
66///
67/// This attribute macro ensures the decorated function only executes when the incoming request
68/// uses the GET HTTP method. Requests with other methods will be filtered out.
69///
70/// # Usage
71///
72/// ```rust
73/// use hyperlane::*;
74/// use hyperlane_macros::*;
75///
76/// #[route("/get")]
77/// struct Get;
78///
79/// impl ServerHook for Get {
80/// async fn new(_ctx: &Context) -> Self {
81/// Self
82/// }
83///
84/// #[prologue_macros(get, response_body("get"))]
85/// async fn handle(self, ctx: &Context) {}
86/// }
87/// ```
88///
89/// The macro takes no parameters and should be applied directly to async functions
90/// that accept a `&Context` parameter.
91#[proc_macro_attribute]
92pub fn get(_attr: TokenStream, item: TokenStream) -> TokenStream {
93 get_handler(item, Position::Prologue)
94}
95
96/// Restricts function execution to HTTP POST requests only.
97///
98/// This attribute macro ensures the decorated function only executes when the incoming request
99/// uses the POST HTTP method. Requests with other methods will be filtered out.
100///
101/// # Usage
102///
103/// ```rust
104/// use hyperlane::*;
105/// use hyperlane_macros::*;
106///
107/// #[route("/post")]
108/// struct Post;
109///
110/// impl ServerHook for Post {
111/// async fn new(_ctx: &Context) -> Self {
112/// Self
113/// }
114///
115/// #[prologue_macros(post, response_body("post"))]
116/// async fn handle(self, ctx: &Context) {}
117/// }
118/// ```
119///
120/// The macro takes no parameters and should be applied directly to async functions
121/// that accept a `&Context` parameter.
122#[proc_macro_attribute]
123pub fn post(_attr: TokenStream, item: TokenStream) -> TokenStream {
124 epilogue_handler(item, Position::Prologue)
125}
126
127/// Restricts function execution to HTTP PUT requests only.
128///
129/// This attribute macro ensures the decorated function only executes when the incoming request
130/// uses the PUT HTTP method. Requests with other methods will be filtered out.
131///
132/// # Usage
133///
134/// ```rust
135/// use hyperlane::*;
136/// use hyperlane_macros::*;
137///
138/// #[route("/put")]
139/// struct Put;
140///
141/// impl ServerHook for Put {
142/// async fn new(_ctx: &Context) -> Self {
143/// Self
144/// }
145///
146/// #[prologue_macros(put, response_body("put"))]
147/// async fn handle(self, ctx: &Context) {}
148/// }
149/// ```
150///
151/// The macro takes no parameters and should be applied directly to async functions
152/// that accept a `&Context` parameter.
153#[proc_macro_attribute]
154pub fn put(_attr: TokenStream, item: TokenStream) -> TokenStream {
155 put_handler(item, Position::Prologue)
156}
157
158/// Restricts function execution to HTTP DELETE requests only.
159///
160/// This attribute macro ensures the decorated function only executes when the incoming request
161/// uses the DELETE HTTP method. Requests with other methods will be filtered out.
162///
163/// # Usage
164///
165/// ```rust
166/// use hyperlane::*;
167/// use hyperlane_macros::*;
168///
169/// #[route("/delete")]
170/// struct Delete;
171///
172/// impl ServerHook for Delete {
173/// async fn new(_ctx: &Context) -> Self {
174/// Self
175/// }
176///
177/// #[prologue_macros(delete, response_body("delete"))]
178/// async fn handle(self, ctx: &Context) {}
179/// }
180/// ```
181///
182/// The macro takes no parameters and should be applied directly to async functions
183/// that accept a `&Context` parameter.
184#[proc_macro_attribute]
185pub fn delete(_attr: TokenStream, item: TokenStream) -> TokenStream {
186 delete_handler(item, Position::Prologue)
187}
188
189/// Restricts function execution to HTTP PATCH requests only.
190///
191/// This attribute macro ensures the decorated function only executes when the incoming request
192/// uses the PATCH HTTP method. Requests with other methods will be filtered out.
193///
194/// # Usage
195///
196/// ```rust
197/// use hyperlane::*;
198/// use hyperlane_macros::*;
199///
200/// #[route("/patch")]
201/// struct Patch;
202///
203/// impl ServerHook for Patch {
204/// async fn new(_ctx: &Context) -> Self {
205/// Self
206/// }
207///
208/// #[prologue_macros(patch, response_body("patch"))]
209/// async fn handle(self, ctx: &Context) {}
210/// }
211/// ```
212///
213/// The macro takes no parameters and should be applied directly to async functions
214/// that accept a `&Context` parameter.
215#[proc_macro_attribute]
216pub fn patch(_attr: TokenStream, item: TokenStream) -> TokenStream {
217 patch_handler(item, Position::Prologue)
218}
219
220/// Restricts function execution to HTTP HEAD requests only.
221///
222/// This attribute macro ensures the decorated function only executes when the incoming request
223/// uses the HEAD HTTP method. Requests with other methods will be filtered out.
224///
225/// # Usage
226///
227/// ```rust
228/// use hyperlane::*;
229/// use hyperlane_macros::*;
230///
231/// #[route("/head")]
232/// struct Head;
233///
234/// impl ServerHook for Head {
235/// async fn new(_ctx: &Context) -> Self {
236/// Self
237/// }
238///
239/// #[prologue_macros(head, response_body("head"))]
240/// async fn handle(self, ctx: &Context) {}
241/// }
242/// ```
243///
244/// The macro takes no parameters and should be applied directly to async functions
245/// that accept a `&Context` parameter.
246#[proc_macro_attribute]
247pub fn head(_attr: TokenStream, item: TokenStream) -> TokenStream {
248 head_handler(item, Position::Prologue)
249}
250
251/// Restricts function execution to HTTP OPTIONS requests only.
252///
253/// This attribute macro ensures the decorated function only executes when the incoming request
254/// uses the OPTIONS HTTP method. Requests with other methods will be filtered out.
255///
256/// # Usage
257///
258/// ```rust
259/// use hyperlane::*;
260/// use hyperlane_macros::*;
261///
262/// #[route("/options")]
263/// struct Options;
264///
265/// impl ServerHook for Options {
266/// async fn new(_ctx: &Context) -> Self {
267/// Self
268/// }
269///
270/// #[prologue_macros(options, response_body("options"))]
271/// async fn handle(self, ctx: &Context) {}
272/// }
273/// ```
274///
275/// The macro takes no parameters and should be applied directly to async functions
276/// that accept a `&Context` parameter.
277#[proc_macro_attribute]
278pub fn options(_attr: TokenStream, item: TokenStream) -> TokenStream {
279 options_handler(item, Position::Prologue)
280}
281
282/// Restricts function execution to HTTP CONNECT requests only.
283///
284/// This attribute macro ensures the decorated function only executes when the incoming request
285/// uses the CONNECT HTTP method. Requests with other methods will be filtered out.
286///
287/// # Usage
288///
289/// ```rust
290/// use hyperlane::*;
291/// use hyperlane_macros::*;
292///
293/// #[route("/connect")]
294/// struct Connect;
295///
296/// impl ServerHook for Connect {
297/// async fn new(_ctx: &Context) -> Self {
298/// Self
299/// }
300///
301/// #[prologue_macros(connect, response_body("connect"))]
302/// async fn handle(self, ctx: &Context) {}
303/// }
304/// ```
305///
306/// The macro takes no parameters and should be applied directly to async functions
307/// that accept a `&Context` parameter.
308#[proc_macro_attribute]
309pub fn connect(_attr: TokenStream, item: TokenStream) -> TokenStream {
310 connect_handler(item, Position::Prologue)
311}
312
313/// Restricts function execution to HTTP TRACE requests only.
314///
315/// This attribute macro ensures the decorated function only executes when the incoming request
316/// uses the TRACE HTTP method. Requests with other methods will be filtered out.
317///
318/// # Usage
319///
320/// ```rust
321/// use hyperlane::*;
322/// use hyperlane_macros::*;
323///
324/// #[route("/trace")]
325/// struct Trace;
326///
327/// impl ServerHook for Trace {
328/// async fn new(_ctx: &Context) -> Self {
329/// Self
330/// }
331///
332/// #[prologue_macros(trace, response_body("trace"))]
333/// async fn handle(self, ctx: &Context) {}
334/// }
335/// ```
336///
337/// The macro takes no parameters and should be applied directly to async functions
338/// that accept a `&Context` parameter.
339#[proc_macro_attribute]
340pub fn trace(_attr: TokenStream, item: TokenStream) -> TokenStream {
341 trace_handler(item, Position::Prologue)
342}
343
344/// Allows function to handle multiple HTTP methods.
345///
346/// This attribute macro configures the decorated function to execute for any of the specified
347/// HTTP methods. Methods should be provided as a comma-separated list.
348///
349/// # Usage
350///
351/// ```rust
352/// use hyperlane::*;
353/// use hyperlane_macros::*;
354///
355/// #[route("/get_post")]
356/// struct GetPost;
357///
358/// impl ServerHook for GetPost {
359/// async fn new(_ctx: &Context) -> Self {
360/// Self
361/// }
362///
363/// #[prologue_macros(
364/// http,
365/// methods(get, post),
366/// response_body("get_post")
367/// )]
368/// async fn handle(self, ctx: &Context) {}
369/// }
370/// ```
371///
372/// The macro accepts a comma-separated list of HTTP method names (lowercase) and should be
373/// applied to async functions that accept a `&Context` parameter.
374#[proc_macro_attribute]
375pub fn methods(attr: TokenStream, item: TokenStream) -> TokenStream {
376 methods_macro(attr, item, Position::Prologue)
377}
378
379/// Restricts function execution to WebSocket upgrade requests only.
380///
381/// This attribute macro ensures the decorated function only executes when the incoming request
382/// is a valid WebSocket upgrade request with proper request headers and protocol negotiation.
383///
384/// # Usage
385///
386/// ```rust
387/// use hyperlane::*;
388/// use hyperlane_macros::*;
389///
390/// #[route("/ws")]
391/// struct Websocket;
392///
393/// impl ServerHook for Websocket {
394/// async fn new(_ctx: &Context) -> Self {
395/// Self
396/// }
397///
398/// #[ws]
399/// #[ws_from_stream]
400/// async fn handle(self, ctx: &Context) {
401/// let body: RequestBody = ctx.get_request_body().await;
402/// let body_list: Vec<ResponseBody> = WebSocketFrame::create_frame_list(&body);
403/// ctx.send_body_list_with_data(&body_list).await.unwrap();
404/// }
405/// }
406/// ```
407///
408/// The macro takes no parameters and should be applied directly to async functions
409/// that accept a `&Context` parameter.
410#[proc_macro_attribute]
411pub fn ws(_attr: TokenStream, item: TokenStream) -> TokenStream {
412 ws_macro(item, Position::Prologue)
413}
414
415/// Restricts function execution to standard HTTP requests only.
416///
417/// This attribute macro ensures the decorated function only executes for standard HTTP requests,
418/// excluding WebSocket upgrades and other protocol upgrade requests.
419///
420/// # Usage
421///
422/// ```rust
423/// use hyperlane::*;
424/// use hyperlane_macros::*;
425///
426/// #[route("/http")]
427/// struct HttpOnly;
428///
429/// impl ServerHook for HttpOnly {
430/// async fn new(_ctx: &Context) -> Self {
431/// Self
432/// }
433///
434/// #[prologue_macros(http, response_body("http"))]
435/// async fn handle(self, ctx: &Context) {}
436/// }
437/// ```
438///
439/// The macro takes no parameters and should be applied directly to async functions
440/// that accept a `&Context` parameter.
441#[proc_macro_attribute]
442pub fn http(_attr: TokenStream, item: TokenStream) -> TokenStream {
443 http_macro(item, Position::Prologue)
444}
445
446/// Sets the HTTP status code for the response.
447///
448/// This attribute macro configures the HTTP status code that will be sent with the response.
449/// The status code can be provided as a numeric literal or a global constant.
450///
451/// # Usage
452///
453/// ```rust
454/// use hyperlane::*;
455/// use hyperlane_macros::*;
456///
457/// const CUSTOM_STATUS_CODE: i32 = 200;
458///
459/// #[route("/response")]
460/// struct Response;
461///
462/// impl ServerHook for Response {
463/// async fn new(_ctx: &Context) -> Self {
464/// Self
465/// }
466///
467/// #[response_status_code(CUSTOM_STATUS_CODE)]
468/// async fn handle(self, ctx: &Context) {}
469/// }
470/// ```
471///
472/// The macro accepts a numeric HTTP status code or a global constant
473/// and should be applied to async functions that accept a `&Context` parameter.
474#[proc_macro_attribute]
475pub fn response_status_code(attr: TokenStream, item: TokenStream) -> TokenStream {
476 response_status_code_macro(attr, item, Position::Prologue)
477}
478
479/// Sets the HTTP reason phrase for the response.
480///
481/// This attribute macro configures the HTTP reason phrase that accompanies the status code.
482/// The reason phrase can be provided as a string literal or a global constant.
483///
484/// # Usage
485///
486/// ```rust
487/// use hyperlane::*;
488/// use hyperlane_macros::*;
489///
490/// const CUSTOM_REASON: &str = "Accepted";
491///
492/// #[route("/response")]
493/// struct Response;
494///
495/// impl ServerHook for Response {
496/// async fn new(_ctx: &Context) -> Self {
497/// Self
498/// }
499///
500/// #[response_reason_phrase(CUSTOM_REASON)]
501/// async fn handle(self, ctx: &Context) {}
502/// }
503/// ```
504///
505/// The macro accepts a string literal or global constant for the reason phrase and should be
506/// applied to async functions that accept a `&Context` parameter.
507#[proc_macro_attribute]
508pub fn response_reason_phrase(attr: TokenStream, item: TokenStream) -> TokenStream {
509 response_reason_phrase_macro(attr, item, Position::Prologue)
510}
511
512/// Sets or replaces a specific HTTP response header.
513///
514/// This attribute macro configures a specific HTTP response header that will be sent with the response.
515/// Both the header name and value can be provided as string literals or global constants.
516/// Use `"key", "value"` to set a header (add to existing headers) or `"key" => "value"` to replace a header (overwrite existing).
517///
518/// # Usage
519///
520/// ```rust
521/// use hyperlane::*;
522/// use hyperlane_macros::*;
523///
524/// const CUSTOM_HEADER_NAME: &str = "X-Custom-Header";
525/// const CUSTOM_HEADER_VALUE: &str = "custom-value";
526///
527/// #[route("/response")]
528/// struct Response;
529///
530/// impl ServerHook for Response {
531/// async fn new(_ctx: &Context) -> Self {
532/// Self
533/// }
534///
535/// #[response_header(CUSTOM_HEADER_NAME => CUSTOM_HEADER_VALUE)]
536/// async fn handle(self, ctx: &Context) {}
537/// }
538///
539/// #[route("/response_header")]
540/// struct ResponseHeaderTest;
541///
542/// impl ServerHook for ResponseHeaderTest {
543/// async fn new(_ctx: &Context) -> Self {
544/// Self
545/// }
546///
547/// #[response_body("Testing header set and replace operations")]
548/// #[response_header("X-Add-Header", "add-value")]
549/// #[response_header("X-Set-Header" => "set-value")]
550/// async fn handle(self, ctx: &Context) {}
551/// }
552/// ```
553///
554/// The macro accepts header name and header value, both can be string literals or global constants.
555/// Use `"key", "value"` for setting headers and `"key" => "value"` for replacing headers.
556/// Should be applied to async functions that accept a `&Context` parameter.
557#[proc_macro_attribute]
558pub fn response_header(attr: TokenStream, item: TokenStream) -> TokenStream {
559 response_header_macro(attr, item, Position::Prologue)
560}
561
562/// Sets the HTTP response body.
563///
564/// This attribute macro configures the HTTP response body that will be sent with the response.
565/// The body content can be provided as a string literal or a global constant.
566///
567/// # Usage
568///
569/// ```rust
570/// use hyperlane::*;
571/// use hyperlane_macros::*;
572///
573/// const RESPONSE_DATA: &str = "{\"status\": \"success\"}";
574///
575/// #[route("/response")]
576/// struct Response;
577///
578/// impl ServerHook for Response {
579/// async fn new(_ctx: &Context) -> Self {
580/// Self
581/// }
582///
583/// #[response_body(&RESPONSE_DATA)]
584/// async fn handle(self, ctx: &Context) {}
585/// }
586/// ```
587///
588/// The macro accepts a string literal or global constant for the response body and should be
589/// applied to async functions that accept a `&Context` parameter.
590#[proc_macro_attribute]
591pub fn response_body(attr: TokenStream, item: TokenStream) -> TokenStream {
592 response_body_macro(attr, item, Position::Prologue)
593}
594
595/// Clears all response headers.
596///
597/// This attribute macro clears all response headers from the response.
598///
599/// # Usage
600///
601/// ```rust
602/// use hyperlane::*;
603/// use hyperlane_macros::*;
604///
605/// #[route("/unknown_method")]
606/// struct UnknownMethod;
607///
608/// impl ServerHook for UnknownMethod {
609/// async fn new(_ctx: &Context) -> Self {
610/// Self
611/// }
612///
613/// #[prologue_macros(
614/// clear_response_headers,
615/// filter(ctx.get_request().await.is_unknown_method()),
616/// response_body("unknown_method")
617/// )]
618/// async fn handle(self, ctx: &Context) {}
619/// }
620/// ```
621///
622/// The macro should be applied to async functions that accept a `&Context` parameter.
623#[proc_macro_attribute]
624pub fn clear_response_headers(_attr: TokenStream, item: TokenStream) -> TokenStream {
625 clear_response_headers_macro(item, Position::Prologue)
626}
627
628/// Sets the HTTP response version.
629///
630/// This attribute macro configures the HTTP response version that will be sent with the response.
631/// The version can be provided as a variable or code block.
632///
633/// # Usage
634///
635/// ```rust
636/// use hyperlane::*;
637/// use hyperlane_macros::*;
638///
639/// #[request_middleware]
640/// struct RequestMiddleware;
641///
642/// impl ServerHook for RequestMiddleware {
643/// async fn new(_ctx: &Context) -> Self {
644/// Self
645/// }
646///
647/// #[epilogue_macros(
648/// response_status_code(200),
649/// response_version(HttpVersion::HTTP1_1),
650/// response_header(SERVER => HYPERLANE)
651/// )]
652/// async fn handle(self, ctx: &Context) {}
653/// }
654/// ```
655///
656/// The macro accepts a variable or code block for the response version and should be
657/// applied to async functions that accept a `&Context` parameter.
658#[proc_macro_attribute]
659pub fn response_version(attr: TokenStream, item: TokenStream) -> TokenStream {
660 response_version_macro(attr, item, Position::Prologue)
661}
662
663/// Automatically sends the complete response after function execution.
664///
665/// This attribute macro ensures that the response (request headers and body) is automatically sent
666/// to the client after the function completes execution.
667///
668/// # Usage
669///
670/// ```rust
671/// use hyperlane::*;
672/// use hyperlane_macros::*;
673///
674/// #[response_middleware(2)]
675/// struct ResponseMiddleware2;
676///
677/// impl ServerHook for ResponseMiddleware2 {
678/// async fn new(_ctx: &Context) -> Self {
679/// Self
680/// }
681///
682/// #[epilogue_macros(send, flush)]
683/// async fn handle(self, ctx: &Context) {}
684/// }
685/// ```
686///
687/// The macro takes no parameters and should be applied directly to async functions
688/// that accept a `&Context` parameter.
689#[proc_macro_attribute]
690pub fn send(_attr: TokenStream, item: TokenStream) -> TokenStream {
691 send_macro(item, Position::Epilogue)
692}
693
694/// Automatically sends only the response body after function execution.
695///
696/// This attribute macro ensures that only the response body is automatically sent
697/// to the client after the function completes, handling request headers separately.
698///
699/// # Usage
700///
701/// ```rust
702/// use hyperlane::*;
703/// use hyperlane_macros::*;
704///
705/// #[response_middleware("3")]
706/// struct ResponseMiddleware3;
707///
708/// impl ServerHook for ResponseMiddleware3 {
709/// async fn new(_ctx: &Context) -> Self {
710/// Self
711/// }
712///
713/// #[epilogue_macros(send_body, flush)]
714/// async fn handle(self, ctx: &Context) {}
715/// }
716/// ```
717///
718/// The macro takes no parameters and should be applied directly to async functions
719/// that accept a `&Context` parameter.
720#[proc_macro_attribute]
721pub fn send_body(_attr: TokenStream, item: TokenStream) -> TokenStream {
722 send_body_macro(item, Position::Epilogue)
723}
724
725/// Sends the complete response with data after function execution.
726///
727/// This attribute macro ensures that the response (request headers and body) is automatically sent
728/// to the client after the function completes execution, with the specified data.
729///
730/// # Usage
731///
732/// ```rust
733/// use hyperlane::*;
734/// use hyperlane_macros::*;
735///
736/// #[route("/send_with_data")]
737/// struct SendWithData;
738///
739/// impl ServerHook for SendWithData {
740/// async fn new(_ctx: &Context) -> Self {
741/// Self
742/// }
743///
744/// #[epilogue_macros(send_with_data("Hello, World!"))]
745/// async fn handle(self, ctx: &Context) {}
746/// }
747/// ```
748///
749/// The macro accepts data to send and should be applied to async functions
750/// that accept a `&Context` parameter.
751#[proc_macro_attribute]
752pub fn send_with_data(attr: TokenStream, item: TokenStream) -> TokenStream {
753 send_with_data_macro(attr, item, Position::Epilogue)
754}
755
756/// Sends the complete response exactly once after function execution.
757///
758/// This attribute macro ensures that the response is sent exactly once to the client,
759/// preventing multiple response transmissions for single-use scenarios.
760///
761/// # Usage
762///
763/// ```rust
764/// use hyperlane::*;
765/// use hyperlane_macros::*;
766///
767/// #[route("/post")]
768/// struct Post;
769///
770/// impl ServerHook for Post {
771/// async fn new(_ctx: &Context) -> Self {
772/// Self
773/// }
774///
775/// #[prologue_macros(post, response_body("post"), send_once)]
776/// async fn handle(self, ctx: &Context) {}
777/// }
778/// ```
779///
780/// The macro takes no parameters and should be applied directly to async functions
781/// that accept a `&Context` parameter.
782#[proc_macro_attribute]
783pub fn send_once(_attr: TokenStream, item: TokenStream) -> TokenStream {
784 send_once_macro(item, Position::Epilogue)
785}
786
787/// Sends only the response body exactly once after function execution.
788///
789/// This attribute macro ensures that the response body is sent exactly once to the client,
790/// preventing multiple body transmissions for single-use scenarios.
791///
792/// # Usage
793///
794/// ```rust
795/// use hyperlane::*;
796/// use hyperlane_macros::*;
797///
798/// #[route("/get")]
799/// struct Get;
800///
801/// impl ServerHook for Get {
802/// async fn new(_ctx: &Context) -> Self {
803/// Self
804/// }
805///
806/// #[prologue_macros(get, response_body("get"), send_body_once)]
807/// async fn handle(self, ctx: &Context) {}
808/// }
809/// ```
810///
811/// The macro takes no parameters and should be applied directly to async functions
812/// that accept a `&Context` parameter.
813#[proc_macro_attribute]
814pub fn send_body_once(_attr: TokenStream, item: TokenStream) -> TokenStream {
815 send_body_once_macro(item, Position::Epilogue)
816}
817
818/// Sends the complete response exactly once with data after function execution.
819///
820/// This attribute macro ensures that the response is sent exactly once to the client,
821/// preventing multiple response transmissions for single-use scenarios, with the specified data.
822///
823/// # Usage
824///
825/// ```rust
826/// use hyperlane::*;
827/// use hyperlane_macros::*;
828///
829/// #[route("/send_once_with_data")]
830/// struct SendOnceWithData;
831///
832/// impl ServerHook for SendOnceWithData {
833/// async fn new(_ctx: &Context) -> Self {
834/// Self
835/// }
836///
837/// #[epilogue_macros(send_once_with_data("One-time response"))]
838/// async fn handle(self, ctx: &Context) {}
839/// }
840/// ```
841///
842/// The macro accepts data to send and should be applied to async functions
843/// that accept a `&Context` parameter.
844#[proc_macro_attribute]
845pub fn send_once_with_data(attr: TokenStream, item: TokenStream) -> TokenStream {
846 send_once_with_data_macro(attr, item, Position::Epilogue)
847}
848
849/// Flushes the response stream after function execution.
850///
851/// This attribute macro ensures that the response stream is flushed to guarantee immediate
852/// data transmission, forcing any buffered response data to be sent to the client.
853///
854/// # Usage
855///
856/// ```rust
857/// use hyperlane::*;
858/// use hyperlane_macros::*;
859///
860/// #[response_middleware(2)]
861/// struct ResponseMiddleware2;
862///
863/// impl ServerHook for ResponseMiddleware2 {
864/// async fn new(_ctx: &Context) -> Self {
865/// Self
866/// }
867///
868/// #[epilogue_macros(send, flush)]
869/// async fn handle(self, ctx: &Context) {}
870/// }
871/// ```
872///
873/// The macro takes no parameters and should be applied directly to async functions
874/// that accept a `&Context` parameter.
875#[proc_macro_attribute]
876pub fn flush(_attr: TokenStream, item: TokenStream) -> TokenStream {
877 flush_macro(item, Position::Prologue)
878}
879
880/// Handles aborted request scenarios.
881///
882/// This attribute macro configures the function to handle cases where the client has
883/// aborted the request, providing appropriate handling for interrupted or cancelled requests.
884///
885/// # Usage
886///
887/// ```rust
888/// use hyperlane::*;
889/// use hyperlane_macros::*;
890///
891/// #[route("/aborted")]
892/// struct Aborted;
893///
894/// impl ServerHook for Aborted {
895/// async fn new(_ctx: &Context) -> Self {
896/// Self
897/// }
898///
899/// #[aborted]
900/// async fn handle(self, ctx: &Context) {}
901/// }
902/// ```
903///
904/// The macro takes no parameters and should be applied directly to async functions
905/// that accept a `&Context` parameter.
906#[proc_macro_attribute]
907pub fn aborted(_attr: TokenStream, item: TokenStream) -> TokenStream {
908 aborted_macro(item, Position::Prologue)
909}
910
911/// Handles closed connection scenarios.
912///
913/// This attribute macro configures the function to handle cases where the connection
914/// has been closed, providing appropriate handling for terminated or disconnected connections.
915///
916/// # Usage
917///
918/// ```rust
919/// use hyperlane::*;
920/// use hyperlane_macros::*;
921///
922/// #[route("/get_post")]
923/// struct GetPost;
924///
925/// impl ServerHook for GetPost {
926/// async fn new(_ctx: &Context) -> Self {
927/// Self
928/// }
929///
930/// #[closed]
931/// #[prologue_macros(
932/// http,
933/// methods(get, post),
934/// response_body("get_post")
935/// )]
936/// async fn handle(self, ctx: &Context) {}
937/// }
938/// ```
939///
940/// The macro takes no parameters and should be applied directly to async functions
941/// that accept a `&Context` parameter.
942#[proc_macro_attribute]
943pub fn closed(_attr: TokenStream, item: TokenStream) -> TokenStream {
944 closed_macro(item, Position::Prologue)
945}
946
947/// Restricts function execution to HTTP/2 Cleartext (h2c) requests only.
948///
949/// This attribute macro ensures the decorated function only executes for HTTP/2 cleartext
950/// requests that use the h2c upgrade mechanism.
951///
952/// # Usage
953///
954/// ```rust
955/// use hyperlane::*;
956/// use hyperlane_macros::*;
957///
958/// #[route("/h2c")]
959/// struct H2c;
960///
961/// impl ServerHook for H2c {
962/// async fn new(_ctx: &Context) -> Self {
963/// Self
964/// }
965///
966/// #[prologue_macros(h2c, response_body("h2c"))]
967/// async fn handle(self, ctx: &Context) {}
968/// }
969/// ```
970///
971/// The macro takes no parameters and should be applied directly to async functions
972/// that accept a `&Context` parameter.
973#[proc_macro_attribute]
974pub fn h2c(_attr: TokenStream, item: TokenStream) -> TokenStream {
975 h2c_macro(item, Position::Prologue)
976}
977
978/// Restricts function execution to HTTP/0.9 requests only.
979///
980/// This attribute macro ensures the decorated function only executes for HTTP/0.9
981/// protocol requests, the earliest version of the HTTP protocol.
982///
983/// # Usage
984///
985/// ```rust
986/// use hyperlane::*;
987/// use hyperlane_macros::*;
988///
989/// #[route("/http0_9")]
990/// struct Http09;
991///
992/// impl ServerHook for Http09 {
993/// async fn new(_ctx: &Context) -> Self {
994/// Self
995/// }
996///
997/// #[prologue_macros(http0_9, response_body("http0_9"))]
998/// async fn handle(self, ctx: &Context) {}
999/// }
1000/// ```
1001///
1002/// The macro takes no parameters and should be applied directly to async functions
1003/// that accept a `&Context` parameter.
1004#[proc_macro_attribute]
1005pub fn http0_9(_attr: TokenStream, item: TokenStream) -> TokenStream {
1006 http0_9_macro(item, Position::Prologue)
1007}
1008
1009/// Restricts function execution to HTTP/1.0 requests only.
1010///
1011/// This attribute macro ensures the decorated function only executes for HTTP/1.0
1012/// protocol requests.
1013///
1014/// # Usage
1015///
1016/// ```rust
1017/// use hyperlane::*;
1018/// use hyperlane_macros::*;
1019///
1020/// #[route("/http1_0")]
1021/// struct Http10;
1022///
1023/// impl ServerHook for Http10 {
1024/// async fn new(_ctx: &Context) -> Self {
1025/// Self
1026/// }
1027///
1028/// #[prologue_macros(http1_0, response_body("http1_0"))]
1029/// async fn handle(self, ctx: &Context) {}
1030/// }
1031/// ```
1032///
1033/// The macro takes no parameters and should be applied directly to async functions
1034/// that accept a `&Context` parameter.
1035#[proc_macro_attribute]
1036pub fn http1_0(_attr: TokenStream, item: TokenStream) -> TokenStream {
1037 http1_0_macro(item, Position::Prologue)
1038}
1039
1040/// Restricts function execution to HTTP/1.1 requests only.
1041///
1042/// This attribute macro ensures the decorated function only executes for HTTP/1.1
1043/// protocol requests.
1044///
1045/// # Usage
1046///
1047/// ```rust
1048/// use hyperlane::*;
1049/// use hyperlane_macros::*;
1050///
1051/// #[route("/http1_1")]
1052/// struct Http11;
1053///
1054/// impl ServerHook for Http11 {
1055/// async fn new(_ctx: &Context) -> Self {
1056/// Self
1057/// }
1058///
1059/// #[prologue_macros(http1_1, response_body("http1_1"))]
1060/// async fn handle(self, ctx: &Context) {}
1061/// }
1062/// ```
1063///
1064/// The macro takes no parameters and should be applied directly to async functions
1065/// that accept a `&Context` parameter.
1066#[proc_macro_attribute]
1067pub fn http1_1(_attr: TokenStream, item: TokenStream) -> TokenStream {
1068 http1_1_macro(item, Position::Prologue)
1069}
1070
1071/// Restricts function execution to HTTP/1.1 or higher protocol versions.
1072///
1073/// This attribute macro ensures the decorated function only executes for HTTP/1.1
1074/// or newer protocol versions, including HTTP/2, HTTP/3, and future versions.
1075///
1076/// # Usage
1077///
1078/// ```rust
1079/// use hyperlane::*;
1080/// use hyperlane_macros::*;
1081///
1082/// #[route("/http1_1_or_higher")]
1083/// struct Http11OrHigher;
1084///
1085/// impl ServerHook for Http11OrHigher {
1086/// async fn new(_ctx: &Context) -> Self {
1087/// Self
1088/// }
1089///
1090/// #[prologue_macros(http1_1_or_higher, response_body("http1_1_or_higher"))]
1091/// async fn handle(self, ctx: &Context) {}
1092/// }
1093/// ```
1094///
1095/// The macro takes no parameters and should be applied directly to async functions
1096/// that accept a `&Context` parameter.
1097#[proc_macro_attribute]
1098pub fn http1_1_or_higher(_attr: TokenStream, item: TokenStream) -> TokenStream {
1099 http1_1_or_higher_macro(item, Position::Prologue)
1100}
1101
1102/// Restricts function execution to HTTP/2 requests only.
1103///
1104/// This attribute macro ensures the decorated function only executes for HTTP/2
1105/// protocol requests.
1106///
1107/// # Usage
1108///
1109/// ```rust
1110/// use hyperlane::*;
1111/// use hyperlane_macros::*;
1112///
1113/// #[route("/http2")]
1114/// struct Http2;
1115///
1116/// impl ServerHook for Http2 {
1117/// async fn new(_ctx: &Context) -> Self {
1118/// Self
1119/// }
1120///
1121/// #[prologue_macros(http2, response_body("http2"))]
1122/// async fn handle(self, ctx: &Context) {}
1123/// }
1124/// ```
1125///
1126/// The macro takes no parameters and should be applied directly to async functions
1127/// that accept a `&Context` parameter.
1128#[proc_macro_attribute]
1129pub fn http2(_attr: TokenStream, item: TokenStream) -> TokenStream {
1130 http2_macro(item, Position::Prologue)
1131}
1132
1133/// Restricts function execution to HTTP/3 requests only.
1134///
1135/// This attribute macro ensures the decorated function only executes for HTTP/3
1136/// protocol requests, the latest version of the HTTP protocol.
1137///
1138/// # Usage
1139///
1140/// ```rust
1141/// use hyperlane::*;
1142/// use hyperlane_macros::*;
1143///
1144/// #[route("/http3")]
1145/// struct Http3;
1146///
1147/// impl ServerHook for Http3 {
1148/// async fn new(_ctx: &Context) -> Self {
1149/// Self
1150/// }
1151///
1152/// #[prologue_macros(http3, response_body("http3"))]
1153/// async fn handle(self, ctx: &Context) {}
1154/// }
1155/// ```
1156///
1157/// The macro takes no parameters and should be applied directly to async functions
1158/// that accept a `&Context` parameter.
1159#[proc_macro_attribute]
1160pub fn http3(_attr: TokenStream, item: TokenStream) -> TokenStream {
1161 http3_macro(item, Position::Prologue)
1162}
1163
1164/// Restricts function execution to TLS-encrypted requests only.
1165///
1166/// This attribute macro ensures the decorated function only executes for requests
1167/// that use TLS/SSL encryption on the connection.
1168///
1169/// # Usage
1170///
1171/// ```rust
1172/// use hyperlane::*;
1173/// use hyperlane_macros::*;
1174///
1175/// #[route("/tls")]
1176/// struct Tls;
1177///
1178/// impl ServerHook for Tls {
1179/// async fn new(_ctx: &Context) -> Self {
1180/// Self
1181/// }
1182///
1183/// #[prologue_macros(tls, response_body("tls"))]
1184/// async fn handle(self, ctx: &Context) {}
1185/// }
1186/// ```
1187///
1188/// The macro takes no parameters and should be applied directly to async functions
1189/// that accept a `&Context` parameter.
1190#[proc_macro_attribute]
1191pub fn tls(_attr: TokenStream, item: TokenStream) -> TokenStream {
1192 tls_macro(item, Position::Prologue)
1193}
1194
1195/// Filters requests based on a boolean condition.
1196///
1197/// The function continues execution only if the provided code block returns `true`.
1198///
1199/// # Usage
1200///
1201/// ```rust
1202/// use hyperlane::*;
1203/// use hyperlane_macros::*;
1204///
1205/// #[route("/unknown_method")]
1206/// struct UnknownMethod;
1207///
1208/// impl ServerHook for UnknownMethod {
1209/// async fn new(_ctx: &Context) -> Self {
1210/// Self
1211/// }
1212///
1213/// #[prologue_macros(
1214/// filter(ctx.get_request().await.is_unknown_method()),
1215/// response_body("unknown_method")
1216/// )]
1217/// async fn handle(self, ctx: &Context) {}
1218/// }
1219/// ```
1220#[proc_macro_attribute]
1221pub fn filter(attr: TokenStream, item: TokenStream) -> TokenStream {
1222 filter_macro(attr, item, Position::Prologue)
1223}
1224
1225/// Rejects requests based on a boolean condition.
1226///
1227/// The function continues execution only if the provided code block returns `false`.
1228///
1229/// # Usage
1230///
1231/// ```rust
1232/// use hyperlane::*;
1233/// use hyperlane_macros::*;
1234///
1235/// #[response_middleware(2)]
1236/// struct ResponseMiddleware2;
1237///
1238/// impl ServerHook for ResponseMiddleware2 {
1239/// async fn new(_ctx: &Context) -> Self {
1240/// Self
1241/// }
1242///
1243/// #[prologue_macros(
1244/// reject(ctx.get_request().await.is_ws())
1245/// )]
1246/// async fn handle(self, ctx: &Context) {}
1247/// }
1248/// ```
1249#[proc_macro_attribute]
1250pub fn reject(attr: TokenStream, item: TokenStream) -> TokenStream {
1251 reject_macro(attr, item, Position::Prologue)
1252}
1253
1254/// Restricts function execution to requests with a specific host.
1255///
1256/// This attribute macro ensures the decorated function only executes when the incoming request
1257/// has a host header that matches the specified value. Requests with different or missing host headers will be filtered out.
1258///
1259/// # Usage
1260///
1261/// ```rust
1262/// use hyperlane::*;
1263/// use hyperlane_macros::*;
1264///
1265/// #[route("/host")]
1266/// struct Host;
1267///
1268/// impl ServerHook for Host {
1269/// async fn new(_ctx: &Context) -> Self {
1270/// Self
1271/// }
1272///
1273/// #[host("localhost")]
1274/// #[prologue_macros(response_body("host string literal: localhost"), send)]
1275/// async fn handle(self, ctx: &Context) {}
1276/// }
1277/// ```
1278///
1279/// The macro accepts a string literal specifying the expected host value and should be
1280/// applied to async functions that accept a `&Context` parameter.
1281#[proc_macro_attribute]
1282pub fn host(attr: TokenStream, item: TokenStream) -> TokenStream {
1283 host_macro(attr, item, Position::Prologue)
1284}
1285
1286/// Reject requests that have no host header.
1287///
1288/// This attribute macro ensures the decorated function only executes when the incoming request
1289/// has a host header present. Requests without a host header will be filtered out.
1290///
1291/// # Usage
1292///
1293/// ```rust
1294/// use hyperlane::*;
1295/// use hyperlane_macros::*;
1296///
1297/// #[route("/reject_host")]
1298/// struct RejectHost;
1299///
1300/// impl ServerHook for RejectHost {
1301/// async fn new(_ctx: &Context) -> Self {
1302/// Self
1303/// }
1304///
1305/// #[prologue_macros(
1306/// reject_host("filter.localhost"),
1307/// response_body("host filter string literal")
1308/// )]
1309/// async fn handle(self, ctx: &Context) {}
1310/// }
1311/// ```
1312///
1313/// The macro takes no parameters and should be applied directly to async functions
1314/// that accept a `&Context` parameter.
1315#[proc_macro_attribute]
1316pub fn reject_host(attr: TokenStream, item: TokenStream) -> TokenStream {
1317 reject_host_macro(attr, item, Position::Prologue)
1318}
1319
1320/// Restricts function execution to requests with a specific referer.
1321///
1322/// This attribute macro ensures the decorated function only executes when the incoming request
1323/// has a referer header that matches the specified value. Requests with different or missing referer headers will be filtered out.
1324///
1325/// # Usage
1326///
1327/// ```rust
1328/// use hyperlane::*;
1329/// use hyperlane_macros::*;
1330///
1331/// #[route("/referer")]
1332/// struct Referer;
1333///
1334/// impl ServerHook for Referer {
1335/// async fn new(_ctx: &Context) -> Self {
1336/// Self
1337/// }
1338///
1339/// #[prologue_macros(
1340/// referer("http://localhost"),
1341/// response_body("referer string literal: http://localhost")
1342/// )]
1343/// async fn handle(self, ctx: &Context) {}
1344/// }
1345/// ```
1346///
1347/// The macro accepts a string literal specifying the expected referer value and should be
1348/// applied to async functions that accept a `&Context` parameter.
1349#[proc_macro_attribute]
1350pub fn referer(attr: TokenStream, item: TokenStream) -> TokenStream {
1351 referer_macro(attr, item, Position::Prologue)
1352}
1353
1354/// Reject requests that have a specific referer header.
1355///
1356/// This attribute macro ensures the decorated function only executes when the incoming request
1357/// does not have a referer header that matches the specified value. Requests with the matching referer header will be filtered out.
1358///
1359/// # Usage
1360///
1361/// ```rust
1362/// use hyperlane::*;
1363/// use hyperlane_macros::*;
1364///
1365/// #[route("/reject_referer")]
1366/// struct RejectReferer;
1367///
1368/// impl ServerHook for RejectReferer {
1369/// async fn new(_ctx: &Context) -> Self {
1370/// Self
1371/// }
1372///
1373/// #[prologue_macros(
1374/// reject_referer("http://localhost"),
1375/// response_body("referer filter string literal")
1376/// )]
1377/// async fn handle(self, ctx: &Context) {}
1378/// }
1379/// ```
1380///
1381/// The macro accepts a string literal specifying the referer value to filter out and should be
1382/// applied to async functions that accept a `&Context` parameter.
1383#[proc_macro_attribute]
1384pub fn reject_referer(attr: TokenStream, item: TokenStream) -> TokenStream {
1385 reject_referer_macro(attr, item, Position::Prologue)
1386}
1387
1388/// Executes multiple specified functions before the main handler function.
1389///
1390/// This attribute macro configures multiple pre-execution hooks that run before the main function logic.
1391/// The specified hook functions will be called in the order provided, followed by the main function execution.
1392///
1393/// # Usage
1394///
1395/// ```rust
1396/// use hyperlane::*;
1397/// use hyperlane_macros::*;
1398///
1399/// struct PrologueHooks;
1400///
1401/// impl ServerHook for PrologueHooks {
1402/// async fn new(_ctx: &Context) -> Self {
1403/// Self
1404/// }
1405///
1406/// #[get]
1407/// #[http]
1408/// async fn handle(self, _ctx: &Context) {}
1409/// }
1410///
1411/// async fn prologue_hooks_fn(ctx: Context) {
1412/// let hook = PrologueHooks::new(&ctx).await;
1413/// hook.handle(&ctx).await;
1414/// }
1415///
1416/// #[route("/hook")]
1417/// struct Hook;
1418///
1419/// impl ServerHook for Hook {
1420/// async fn new(_ctx: &Context) -> Self {
1421/// Self
1422/// }
1423///
1424/// #[prologue_hooks(prologue_hooks_fn)]
1425/// #[response_body("Testing hook macro")]
1426/// async fn handle(self, ctx: &Context) {}
1427/// }
1428/// ```
1429///
1430/// The macro accepts a comma-separated list of function names as parameters. All hook functions
1431/// and the main function must accept a `Context` parameter. Avoid combining this macro with other
1432/// macros on the same function to prevent macro expansion conflicts.
1433#[proc_macro_attribute]
1434pub fn prologue_hooks(attr: TokenStream, item: TokenStream) -> TokenStream {
1435 prologue_hooks_macro(attr, item, Position::Prologue)
1436}
1437
1438/// Executes multiple specified functions after the main handler function.
1439///
1440/// This attribute macro configures multiple post-execution hooks that run after the main function logic.
1441/// The main function will execute first, followed by the specified hook functions in the order provided.
1442///
1443/// # Usage
1444///
1445/// ```rust
1446/// use hyperlane::*;
1447/// use hyperlane_macros::*;
1448///
1449/// struct EpilogueHooks;
1450///
1451/// impl ServerHook for EpilogueHooks {
1452/// async fn new(_ctx: &Context) -> Self {
1453/// Self
1454/// }
1455///
1456/// #[response_status_code(200)]
1457/// async fn handle(self, ctx: &Context) {}
1458/// }
1459///
1460/// async fn epilogue_hooks_fn(ctx: Context) {
1461/// let hook = EpilogueHooks::new(&ctx).await;
1462/// hook.handle(&ctx).await;
1463/// }
1464///
1465/// #[route("/hook")]
1466/// struct Hook;
1467///
1468/// impl ServerHook for Hook {
1469/// async fn new(_ctx: &Context) -> Self {
1470/// Self
1471/// }
1472///
1473/// #[epilogue_hooks(epilogue_hooks_fn)]
1474/// #[response_body("Testing hook macro")]
1475/// async fn handle(self, ctx: &Context) {}
1476/// }
1477/// ```
1478///
1479/// The macro accepts a comma-separated list of function names as parameters. All hook functions
1480/// and the main function must accept a `Context` parameter. Avoid combining this macro with other
1481/// macros on the same function to prevent macro expansion conflicts.
1482#[proc_macro_attribute]
1483pub fn epilogue_hooks(attr: TokenStream, item: TokenStream) -> TokenStream {
1484 epilogue_hooks_macro(attr, item, Position::Epilogue)
1485}
1486
1487/// Extracts the raw request body into a specified variable.
1488///
1489/// This attribute macro extracts the raw request body content into a variable
1490/// with the fixed type `RequestBody`. The body content is not parsed or deserialized.
1491///
1492/// # Usage
1493///
1494/// ```rust
1495/// use hyperlane::*;
1496/// use hyperlane_macros::*;
1497///
1498/// #[route("/request_body")]
1499/// struct RequestBodyRoute;
1500///
1501/// impl ServerHook for RequestBodyRoute {
1502/// async fn new(_ctx: &Context) -> Self {
1503/// Self
1504/// }
1505///
1506/// #[response_body(&format!("raw body: {raw_body:?}"))]
1507/// #[request_body(raw_body)]
1508/// async fn handle(self, ctx: &Context) {}
1509/// }
1510/// ```
1511///
1512/// The macro accepts only a variable name. The variable will be available
1513/// in the function scope as a `RequestBody` type.
1514#[proc_macro_attribute]
1515pub fn request_body(attr: TokenStream, item: TokenStream) -> TokenStream {
1516 request_body_macro(attr, item, Position::Prologue)
1517}
1518
1519/// Parses the request body as JSON into a specified variable and type.
1520///
1521/// This attribute macro extracts and deserializes the request body content as JSON into a variable
1522/// with the specified type. The body content is parsed as JSON using serde.
1523///
1524/// # Usage
1525///
1526/// ```rust
1527/// use hyperlane::*;
1528/// use hyperlane_macros::*;
1529/// use serde::{Deserialize, Serialize};
1530///
1531/// #[derive(Debug, Serialize, Deserialize, Clone)]
1532/// struct TestData {
1533/// name: String,
1534/// age: u32,
1535/// }
1536///
1537/// #[route("/request_body_json")]
1538/// struct RequestBodyJson;
1539///
1540/// impl ServerHook for RequestBodyJson {
1541/// async fn new(_ctx: &Context) -> Self {
1542/// Self
1543/// }
1544///
1545/// #[response_body(&format!("request data: {request_data_result:?}"))]
1546/// #[request_body_json(request_data_result: TestData)]
1547/// async fn handle(self, ctx: &Context) {}
1548/// }
1549/// ```
1550///
1551/// The macro accepts a variable name and type in the format `variable_name: Type`.
1552/// The variable will be available in the function scope as a `Result<Type, JsonError>`.
1553#[proc_macro_attribute]
1554pub fn request_body_json(attr: TokenStream, item: TokenStream) -> TokenStream {
1555 request_body_json_macro(attr, item, Position::Prologue)
1556}
1557
1558/// Extracts a specific attribute value into a variable.
1559///
1560/// This attribute macro retrieves a specific attribute by key and makes it available
1561/// as a typed variable from the request context.
1562///
1563/// # Usage
1564///
1565/// ```rust
1566/// use hyperlane::*;
1567/// use hyperlane_macros::*;
1568/// use serde::{Deserialize, Serialize};
1569///
1570/// const TEST_ATTRIBUTE_KEY: &str = "test_attribute_key";
1571///
1572/// #[derive(Debug, Serialize, Deserialize, Clone)]
1573/// struct TestData {
1574/// name: String,
1575/// age: u32,
1576/// }
1577///
1578/// #[route("/attribute")]
1579/// struct Attribute;
1580///
1581/// impl ServerHook for Attribute {
1582/// async fn new(_ctx: &Context) -> Self {
1583/// Self
1584/// }
1585///
1586/// #[response_body(&format!("request attribute: {request_attribute_option:?}"))]
1587/// #[attribute(TEST_ATTRIBUTE_KEY => request_attribute_option: TestData)]
1588/// async fn handle(self, ctx: &Context) {}
1589/// }
1590/// ```
1591///
1592/// The macro accepts a key-to-variable mapping in the format `key => variable_name: Type`.
1593/// The variable will be available as an `Option<Type>` in the function scope.
1594#[proc_macro_attribute]
1595pub fn attribute(attr: TokenStream, item: TokenStream) -> TokenStream {
1596 attribute_macro(attr, item, Position::Prologue)
1597}
1598
1599/// Extracts all attributes into a HashMap variable.
1600///
1601/// This attribute macro retrieves all available attributes from the request context
1602/// and makes them available as a HashMap for comprehensive attribute access.
1603///
1604/// # Usage
1605///
1606/// ```rust
1607/// use hyperlane::*;
1608/// use hyperlane_macros::*;
1609///
1610/// #[route("/attributes")]
1611/// struct Attributes;
1612///
1613/// impl ServerHook for Attributes {
1614/// async fn new(_ctx: &Context) -> Self {
1615/// Self
1616/// }
1617///
1618/// #[response_body(&format!("request attributes: {request_attributes:?}"))]
1619/// #[attributes(request_attributes)]
1620/// async fn handle(self, ctx: &Context) {}
1621/// }
1622/// ```
1623///
1624/// The macro accepts a variable name that will contain a HashMap of all attributes.
1625/// The variable will be available as a HashMap in the function scope.
1626#[proc_macro_attribute]
1627pub fn attributes(attr: TokenStream, item: TokenStream) -> TokenStream {
1628 attributes_macro(attr, item, Position::Prologue)
1629}
1630
1631/// Extracts a specific route parameter into a variable.
1632///
1633/// This attribute macro retrieves a specific route parameter by key and makes it
1634/// available as a variable. Route parameters are extracted from the URL path segments.
1635///
1636/// # Usage
1637///
1638/// ```rust
1639/// use hyperlane::*;
1640/// use hyperlane_macros::*;
1641///
1642/// #[route("/route_param/:test")]
1643/// struct RouteParam;
1644///
1645/// impl ServerHook for RouteParam {
1646/// async fn new(_ctx: &Context) -> Self {
1647/// Self
1648/// }
1649///
1650/// #[response_body(&format!("route param: {request_route_param:?}"))]
1651/// #[route_param("test" => request_route_param)]
1652/// async fn handle(self, ctx: &Context) {}
1653/// }
1654/// ```
1655///
1656/// The macro accepts a key-to-variable mapping in the format `"key" => variable_name`.
1657/// The variable will be available as an `Option<String>` in the function scope.
1658#[proc_macro_attribute]
1659pub fn route_param(attr: TokenStream, item: TokenStream) -> TokenStream {
1660 route_param_macro(attr, item, Position::Prologue)
1661}
1662
1663/// Extracts all route parameters into a collection variable.
1664///
1665/// This attribute macro retrieves all available route parameters from the URL path
1666/// and makes them available as a collection for comprehensive route parameter access.
1667///
1668/// # Usage
1669///
1670/// ```rust
1671/// use hyperlane::*;
1672/// use hyperlane_macros::*;
1673///
1674/// #[route("/route_params/:test")]
1675/// struct RouteParams;
1676///
1677/// impl ServerHook for RouteParams {
1678/// async fn new(_ctx: &Context) -> Self {
1679/// Self
1680/// }
1681///
1682/// #[response_body(&format!("request route params: {request_route_params:?}"))]
1683/// #[route_params(request_route_params)]
1684/// async fn handle(self, ctx: &Context) {}
1685/// }
1686/// ```
1687///
1688/// The macro accepts a variable name that will contain all route parameters.
1689/// The variable will be available as a collection in the function scope.
1690#[proc_macro_attribute]
1691pub fn route_params(attr: TokenStream, item: TokenStream) -> TokenStream {
1692 route_params_macro(attr, item, Position::Prologue)
1693}
1694
1695/// Extracts a specific request query parameter into a variable.
1696///
1697/// This attribute macro retrieves a specific request query parameter by key and makes it
1698/// available as a variable. Query parameters are extracted from the URL request query string.
1699///
1700/// # Usage
1701///
1702/// ```rust
1703/// use hyperlane::*;
1704/// use hyperlane_macros::*;
1705///
1706/// #[route("/request_query")]
1707/// struct RequestQuery;
1708///
1709/// impl ServerHook for RequestQuery {
1710/// async fn new(_ctx: &Context) -> Self {
1711/// Self
1712/// }
1713///
1714/// #[prologue_macros(
1715/// request_query("test" => request_query_option),
1716/// response_body(&format!("request query: {request_query_option:?}")),
1717/// send
1718/// )]
1719/// async fn handle(self, ctx: &Context) {}
1720/// }
1721/// ```
1722///
1723/// The macro accepts a key-to-variable mapping in the format `"key" => variable_name`.
1724/// The variable will be available as an `Option<String>` in the function scope.
1725#[proc_macro_attribute]
1726pub fn request_query(attr: TokenStream, item: TokenStream) -> TokenStream {
1727 request_query_macro(attr, item, Position::Prologue)
1728}
1729
1730/// Extracts all request query parameters into a collection variable.
1731///
1732/// This attribute macro retrieves all available request query parameters from the URL request query string
1733/// and makes them available as a collection for comprehensive request query parameter access.
1734///
1735/// # Usage
1736///
1737/// ```rust
1738/// use hyperlane::*;
1739/// use hyperlane_macros::*;
1740///
1741/// #[route("/request_querys")]
1742/// struct RequestQuerys;
1743///
1744/// impl ServerHook for RequestQuerys {
1745/// async fn new(_ctx: &Context) -> Self {
1746/// Self
1747/// }
1748///
1749/// #[prologue_macros(
1750/// request_querys(request_querys),
1751/// response_body(&format!("request querys: {request_querys:?}")),
1752/// send
1753/// )]
1754/// async fn handle(self, ctx: &Context) {}
1755/// }
1756/// ```
1757///
1758/// The macro accepts a variable name that will contain all request query parameters.
1759/// The variable will be available as a collection in the function scope.
1760#[proc_macro_attribute]
1761pub fn request_querys(attr: TokenStream, item: TokenStream) -> TokenStream {
1762 request_querys_macro(attr, item, Position::Prologue)
1763}
1764
1765/// Extracts a specific HTTP request header into a variable.
1766///
1767/// This attribute macro retrieves a specific HTTP request header by name and makes it
1768/// available as a variable. Header values are extracted from the request request headers collection.
1769///
1770/// # Usage
1771///
1772/// ```rust
1773/// use hyperlane::*;
1774/// use hyperlane_macros::*;
1775///
1776/// #[route("/request_header")]
1777/// struct RequestHeader;
1778///
1779/// impl ServerHook for RequestHeader {
1780/// async fn new(_ctx: &Context) -> Self {
1781/// Self
1782/// }
1783///
1784/// #[prologue_macros(
1785/// request_header(HOST => request_header_option),
1786/// response_body(&format!("request header: {request_header_option:?}")),
1787/// send
1788/// )]
1789/// async fn handle(self, ctx: &Context) {}
1790/// }
1791/// ```
1792///
1793/// The macro accepts a request header name-to-variable mapping in the format `HEADER_NAME => variable_name`
1794/// or `"Header-Name" => variable_name`. The variable will be available as an `Option<String>`.
1795#[proc_macro_attribute]
1796pub fn request_header(attr: TokenStream, item: TokenStream) -> TokenStream {
1797 request_header_macro(attr, item, Position::Prologue)
1798}
1799
1800/// Extracts all HTTP request headers into a collection variable.
1801///
1802/// This attribute macro retrieves all available HTTP request headers from the request
1803/// and makes them available as a collection for comprehensive request header access.
1804///
1805/// # Usage
1806///
1807/// ```rust
1808/// use hyperlane::*;
1809/// use hyperlane_macros::*;
1810///
1811/// #[route("/request_headers")]
1812/// struct RequestHeaders;
1813///
1814/// impl ServerHook for RequestHeaders {
1815/// async fn new(_ctx: &Context) -> Self {
1816/// Self
1817/// }
1818///
1819/// #[prologue_macros(
1820/// request_headers(request_headers),
1821/// response_body(&format!("request headers: {request_headers:?}")),
1822/// send
1823/// )]
1824/// async fn handle(self, ctx: &Context) {}
1825/// }
1826/// ```
1827///
1828/// The macro accepts a variable name that will contain all HTTP request headers.
1829/// The variable will be available as a collection in the function scope.
1830#[proc_macro_attribute]
1831pub fn request_headers(attr: TokenStream, item: TokenStream) -> TokenStream {
1832 request_headers_macro(attr, item, Position::Prologue)
1833}
1834
1835/// Extracts a specific cookie value or all cookies into a variable.
1836///
1837/// This attribute macro supports two syntaxes:
1838/// 1. `cookie(key => variable_name)` - Extract a specific cookie value by key
1839/// 2. `cookie(variable_name)` - Extract all cookies as a raw string
1840///
1841/// # Usage
1842///
1843/// ```rust
1844/// use hyperlane::*;
1845/// use hyperlane_macros::*;
1846///
1847/// #[route("/cookie")]
1848/// struct Cookie;
1849///
1850/// impl ServerHook for Cookie {
1851/// async fn new(_ctx: &Context) -> Self {
1852/// Self
1853/// }
1854///
1855/// #[response_body(&format!("Session cookie: {session_cookie_opt:?}"))]
1856/// #[request_cookie("test" => session_cookie_opt)]
1857/// async fn handle(self, ctx: &Context) {}
1858/// }
1859/// ```
1860///
1861/// For specific cookie extraction, the variable will be available as `Option<String>`.
1862/// For all cookies extraction, the variable will be available as `String`.
1863#[proc_macro_attribute]
1864pub fn request_cookie(attr: TokenStream, item: TokenStream) -> TokenStream {
1865 request_cookie_macro(attr, item, Position::Prologue)
1866}
1867
1868/// Extracts all cookies as a raw string into a variable.
1869///
1870/// This attribute macro retrieves the entire Cookie header from the request and makes it
1871/// available as a String variable. If no Cookie header is present, an empty string is used.
1872///
1873/// # Usage
1874///
1875/// ```rust
1876/// use hyperlane::*;
1877/// use hyperlane_macros::*;
1878///
1879/// #[route("/cookies")]
1880/// struct Cookies;
1881///
1882/// impl ServerHook for Cookies {
1883/// async fn new(_ctx: &Context) -> Self {
1884/// Self
1885/// }
1886///
1887/// #[response_body(&format!("All cookies: {cookie_value:?}"))]
1888/// #[request_cookies(cookie_value)]
1889/// async fn handle(self, ctx: &Context) {}
1890/// }
1891/// ```
1892///
1893/// The macro accepts a variable name that will contain the Cookie header value.
1894/// The variable will be available as a String in the function scope.
1895#[proc_macro_attribute]
1896pub fn request_cookies(attr: TokenStream, item: TokenStream) -> TokenStream {
1897 request_cookies_macro(attr, item, Position::Prologue)
1898}
1899
1900/// Extracts the HTTP request version into a variable.
1901///
1902/// This attribute macro retrieves the HTTP version from the request and makes it
1903/// available as a variable. The version represents the HTTP protocol version used.
1904///
1905/// # Usage
1906///
1907/// ```rust
1908/// use hyperlane::*;
1909/// use hyperlane_macros::*;
1910///
1911/// #[route("/request_version")]
1912/// struct RequestVersionTest;
1913///
1914/// impl ServerHook for RequestVersionTest {
1915/// async fn new(_ctx: &Context) -> Self {
1916/// Self
1917/// }
1918///
1919/// #[response_body(&format!("HTTP Version: {http_version}"))]
1920/// #[request_version(http_version)]
1921/// async fn handle(self, ctx: &Context) {}
1922/// }
1923/// ```
1924///
1925/// The macro accepts a variable name that will contain the HTTP request version.
1926/// The variable will be available as a RequestVersion type in the function scope.
1927#[proc_macro_attribute]
1928pub fn request_version(attr: TokenStream, item: TokenStream) -> TokenStream {
1929 request_version_macro(attr, item, Position::Prologue)
1930}
1931
1932/// Extracts the HTTP request path into a variable.
1933///
1934/// This attribute macro retrieves the request path from the HTTP request and makes it
1935/// available as a variable. The path represents the URL path portion of the request.
1936///
1937/// # Usage
1938///
1939/// ```rust
1940/// use hyperlane::*;
1941/// use hyperlane_macros::*;
1942///
1943/// #[route("/request_path")]
1944/// struct RequestPathTest;
1945///
1946/// impl ServerHook for RequestPathTest {
1947/// async fn new(_ctx: &Context) -> Self {
1948/// Self
1949/// }
1950///
1951/// #[response_body(&format!("Request Path: {request_path}"))]
1952/// #[request_path(request_path)]
1953/// async fn handle(self, ctx: &Context) {}
1954/// }
1955/// ```
1956///
1957/// The macro accepts a variable name that will contain the HTTP request path.
1958/// The variable will be available as a RequestPath type in the function scope.
1959#[proc_macro_attribute]
1960pub fn request_path(attr: TokenStream, item: TokenStream) -> TokenStream {
1961 request_path_macro(attr, item, Position::Prologue)
1962}
1963
1964/// Creates a new instance of a specified type with a given variable name.
1965///
1966/// This attribute macro generates an instance initialization at the beginning of the function.
1967///
1968/// # Usage
1969///
1970/// ```rust,no_run
1971/// use hyperlane::*;
1972/// use hyperlane_macros::*;
1973///
1974/// #[hyperlane(server: Server)]
1975/// #[hyperlane(config: ServerConfig)]
1976/// #[tokio::main]
1977/// async fn main() {
1978/// config.disable_nodelay().await;
1979/// server.config(config).await;
1980/// let server_hook: ServerControlHook = server.run().await.unwrap_or_default();
1981/// server_hook.wait().await;
1982/// }
1983/// ```
1984///
1985/// The macro accepts a `variable_name: Type` pair.
1986/// The variable will be available as an instance of the specified type in the function scope.
1987#[proc_macro_attribute]
1988pub fn hyperlane(attr: TokenStream, item: TokenStream) -> TokenStream {
1989 hyperlane_macro(attr, item)
1990}
1991
1992/// Registers a function as a route handler.
1993///
1994/// This attribute macro registers the decorated function as a route handler for a given path.
1995/// This macro requires the `#[hyperlane(server: Server)]` macro to be used to define the server instance.
1996///
1997/// # Usage
1998///
1999/// ```rust
2000/// use hyperlane::*;
2001/// use hyperlane_macros::*;
2002///
2003/// #[route("/response")]
2004/// struct Response;
2005///
2006/// impl ServerHook for Response {
2007/// async fn new(_ctx: &Context) -> Self {
2008/// Self
2009/// }
2010///
2011/// #[response_body("response")]
2012/// async fn handle(self, ctx: &Context) {}
2013/// }
2014/// ```
2015///
2016/// # Parameters
2017///
2018/// - `path`: String literal defining the route path
2019///
2020/// # Dependencies
2021///
2022/// This macro depends on the `#[hyperlane(server: Server)]` macro to define the server instance.
2023#[proc_macro_attribute]
2024pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
2025 route_macro(attr, item)
2026}
2027
2028/// Registers a function as a request middleware.
2029///
2030/// This attribute macro registers the decorated function to be executed as a middleware
2031/// for incoming requests. This macro requires the `#[hyperlane(server: Server)]` macro to be used to define the server instance.
2032///
2033/// # Note
2034///
2035/// If an order parameter is not specified, the hook will have a higher priority than hooks with a specified order.
2036///
2037/// # Usage
2038///
2039/// ```rust
2040/// use hyperlane::*;
2041/// use hyperlane_macros::*;
2042///
2043/// #[request_middleware]
2044/// struct RequestMiddleware;
2045///
2046/// impl ServerHook for RequestMiddleware {
2047/// async fn new(_ctx: &Context) -> Self {
2048/// Self
2049/// }
2050///
2051/// #[epilogue_macros(
2052/// response_status_code(200),
2053/// response_version(HttpVersion::HTTP1_1),
2054/// response_header(SERVER => HYPERLANE)
2055/// )]
2056/// async fn handle(self, ctx: &Context) {}
2057/// }
2058/// ```
2059///
2060/// # Dependencies
2061///
2062/// This macro depends on the `#[hyperlane(server: Server)]` macro to define the server instance.
2063#[proc_macro_attribute]
2064pub fn request_middleware(attr: TokenStream, item: TokenStream) -> TokenStream {
2065 request_middleware_macro(attr, item)
2066}
2067
2068/// Registers a function as a response middleware.
2069///
2070/// This attribute macro registers the decorated function to be executed as a middleware
2071/// for outgoing responses. This macro requires the `#[hyperlane(server: Server)]` macro to be used to define the server instance.
2072///
2073/// # Note
2074///
2075/// If an order parameter is not specified, the hook will have a higher priority than hooks with a specified order.
2076///
2077/// # Usage
2078///
2079/// ```rust
2080/// use hyperlane::*;
2081/// use hyperlane_macros::*;
2082///
2083/// #[response_middleware]
2084/// struct ResponseMiddleware1;
2085///
2086/// impl ServerHook for ResponseMiddleware1 {
2087/// async fn new(_ctx: &Context) -> Self {
2088/// Self
2089/// }
2090///
2091/// async fn handle(self, ctx: &Context) {}
2092/// }
2093/// ```
2094///
2095/// # Dependencies
2096///
2097/// This macro depends on the `#[hyperlane(server: Server)]` macro to define the server instance.
2098#[proc_macro_attribute]
2099pub fn response_middleware(attr: TokenStream, item: TokenStream) -> TokenStream {
2100 response_middleware_macro(attr, item)
2101}
2102
2103/// Registers a function as a panic hook.
2104///
2105/// This attribute macro registers the decorated function to handle panics that occur
2106/// during request processing. This macro requires the `#[hyperlane(server: Server)]` macro to be used to define the server instance.
2107///
2108/// # Note
2109///
2110/// If an order parameter is not specified, the hook will have a higher priority than hooks with a specified order.
2111///
2112/// # Usage
2113///
2114/// ```rust
2115/// use hyperlane::*;
2116/// use hyperlane_macros::*;
2117///
2118/// #[panic_hook]
2119/// #[panic_hook(1)]
2120/// #[panic_hook("2")]
2121/// struct PanicHook;
2122///
2123/// impl ServerHook for PanicHook {
2124/// async fn new(_ctx: &Context) -> Self {
2125/// Self
2126/// }
2127///
2128/// #[epilogue_macros(response_body("panic_hook"), send)]
2129/// async fn handle(self, ctx: &Context) {}
2130/// }
2131/// ```
2132///
2133/// # Dependencies
2134///
2135/// This macro depends on the `#[hyperlane(server: Server)]` macro to define the server instance.
2136#[proc_macro_attribute]
2137pub fn panic_hook(attr: TokenStream, item: TokenStream) -> TokenStream {
2138 panic_hook_macro(attr, item)
2139}
2140
2141/// Injects a list of macros before the decorated function.
2142///
2143/// The macros are applied in head-insertion order, meaning the first macro in the list
2144/// is the outermost macro.
2145///
2146/// # Usage
2147///
2148/// ```rust
2149/// use hyperlane::*;
2150/// use hyperlane_macros::*;
2151///
2152/// #[route("/post")]
2153/// struct Post;
2154///
2155/// impl ServerHook for Post {
2156/// async fn new(_ctx: &Context) -> Self {
2157/// Self
2158/// }
2159///
2160/// #[prologue_macros(post, response_body("post"), send_once)]
2161/// async fn handle(self, ctx: &Context) {}
2162/// }
2163/// ```
2164#[proc_macro_attribute]
2165pub fn prologue_macros(attr: TokenStream, item: TokenStream) -> TokenStream {
2166 prologue_macros_macro(attr, item)
2167}
2168
2169/// Injects a list of macros after the decorated function.
2170///
2171/// The macros are applied in tail-insertion order, meaning the last macro in the list
2172/// is the outermost macro.
2173///
2174/// # Usage
2175///
2176/// ```rust
2177/// use hyperlane::*;
2178/// use hyperlane_macros::*;
2179///
2180/// #[response_middleware(2)]
2181/// struct ResponseMiddleware2;
2182///
2183/// impl ServerHook for ResponseMiddleware2 {
2184/// async fn new(_ctx: &Context) -> Self {
2185/// Self
2186/// }
2187///
2188/// #[epilogue_macros(send, flush)]
2189/// async fn handle(self, ctx: &Context) {}
2190/// }
2191/// ```
2192#[proc_macro_attribute]
2193pub fn epilogue_macros(attr: TokenStream, item: TokenStream) -> TokenStream {
2194 epilogue_macros_macro(attr, item)
2195}
2196
2197/// Sends only the response body with data after function execution.
2198///
2199/// This attribute macro ensures that only the response body is automatically sent
2200/// to the client after the function completes, handling request headers separately,
2201/// with the specified data.
2202///
2203/// # Usage
2204///
2205/// ```rust
2206/// use hyperlane::*;
2207/// use hyperlane_macros::*;
2208///
2209/// #[route("/send_body_with_data")]
2210/// struct SendBodyWithData;
2211///
2212/// impl ServerHook for SendBodyWithData {
2213/// async fn new(_ctx: &Context) -> Self {
2214/// Self
2215/// }
2216///
2217/// #[epilogue_macros(send_body_with_data("Response body content"))]
2218/// async fn handle(self, ctx: &Context) {}
2219/// }
2220/// ```
2221///
2222/// The macro accepts data to send and should be applied to async functions
2223/// that accept a `&Context` parameter.
2224#[proc_macro_attribute]
2225pub fn send_body_with_data(attr: TokenStream, item: TokenStream) -> TokenStream {
2226 send_body_with_data_macro(attr, item, Position::Epilogue)
2227}
2228
2229/// Wraps function body with WebSocket stream processing.
2230///
2231/// This attribute macro generates code that wraps the function body with a check to see if
2232/// data can be read from a WebSocket stream. The function body is only executed
2233/// if data is successfully read from the stream.
2234///
2235/// This attribute macro generates code that wraps the function body with a check to see if
2236/// data can be read from a WebSocket stream. The function body is only executed
2237/// if data is successfully read from the stream.
2238///
2239/// # Arguments
2240///
2241/// - `TokenStream`: The buffer to read from the WebSocket stream.
2242/// - `TokenStream`: The function item to be modified
2243///
2244/// # Returns
2245///
2246/// Returns a TokenStream containing the modified function with WebSocket stream processing logic.
2247///
2248/// # Examples
2249///
2250/// Using no parameters (default buffer size):
2251/// ```rust
2252/// use hyperlane::*;
2253/// use hyperlane_macros::*;
2254///
2255/// #[route("/ws1")]
2256/// struct Websocket1;
2257///
2258/// impl ServerHook for Websocket1 {
2259/// async fn new(_ctx: &Context) -> Self {
2260/// Self
2261/// }
2262///
2263/// #[ws]
2264/// #[ws_from_stream]
2265/// async fn handle(self, ctx: &Context) {
2266/// let body: RequestBody = ctx.get_request_body().await;
2267/// let body_list: Vec<ResponseBody> = WebSocketFrame::create_frame_list(&body);
2268/// ctx.send_body_list_with_data(&body_list).await.unwrap();
2269/// }
2270/// }
2271/// ```
2272///
2273/// Using only buffer size:
2274/// ```rust
2275/// use hyperlane::*;
2276/// use hyperlane_macros::*;
2277///
2278/// #[route("/ws5")]
2279/// struct Websocket5;
2280///
2281/// impl ServerHook for Websocket5 {
2282/// async fn new(_ctx: &Context) -> Self {
2283/// Self
2284/// }
2285///
2286/// #[ws]
2287/// #[ws_from_stream(1024)]
2288/// async fn handle(self, ctx: &Context) {
2289/// let body: RequestBody = ctx.get_request_body().await;
2290/// let body_list: Vec<ResponseBody> = WebSocketFrame::create_frame_list(&body);
2291/// ctx.send_body_list_with_data(&body_list).await.unwrap();
2292/// }
2293/// }
2294/// ```
2295///
2296/// Using variable name to store request data:
2297/// ```rust
2298/// use hyperlane::*;
2299/// use hyperlane_macros::*;
2300///
2301/// #[route("/ws2")]
2302/// struct Websocket2;
2303///
2304/// impl ServerHook for Websocket2 {
2305/// async fn new(_ctx: &Context) -> Self {
2306/// Self
2307/// }
2308///
2309/// #[ws]
2310/// #[ws_from_stream(request)]
2311/// async fn handle(self, ctx: &Context) {
2312/// let body: &RequestBody = &request.get_body();
2313/// let body_list: Vec<ResponseBody> = WebSocketFrame::create_frame_list(body);
2314/// ctx.send_body_list_with_data(&body_list).await.unwrap();
2315/// }
2316/// }
2317/// ```
2318///
2319/// Using buffer size and variable name:
2320/// ```rust
2321/// use hyperlane::*;
2322/// use hyperlane_macros::*;
2323///
2324/// #[route("/ws3")]
2325/// struct Websocket3;
2326///
2327/// impl ServerHook for Websocket3 {
2328/// async fn new(_ctx: &Context) -> Self {
2329/// Self
2330/// }
2331///
2332/// #[ws]
2333/// #[ws_from_stream(1024, request)]
2334/// async fn handle(self, ctx: &Context) {
2335/// let body: &RequestBody = request.get_body();
2336/// let body_list: Vec<ResponseBody> = WebSocketFrame::create_frame_list(&body);
2337/// ctx.send_body_list_with_data(&body_list).await.unwrap();
2338/// }
2339/// }
2340/// ```
2341///
2342/// Using variable name and buffer size (reversed order):
2343/// ```rust
2344/// use hyperlane::*;
2345/// use hyperlane_macros::*;
2346///
2347/// #[route("/ws4")]
2348/// struct Websocket4;
2349///
2350/// impl ServerHook for Websocket4 {
2351/// async fn new(_ctx: &Context) -> Self {
2352/// Self
2353/// }
2354///
2355/// #[ws]
2356/// #[ws_from_stream(request, 1024)]
2357/// async fn handle(self, ctx: &Context) {
2358/// let body: &RequestBody = request.get_body();
2359/// let body_list: Vec<ResponseBody> = WebSocketFrame::create_frame_list(&body);
2360/// ctx.send_body_list_with_data(&body_list).await.unwrap();
2361/// }
2362/// }
2363/// ```
2364#[proc_macro_attribute]
2365pub fn ws_from_stream(attr: TokenStream, item: TokenStream) -> TokenStream {
2366 ws_from_stream_macro(attr, item)
2367}
2368
2369/// Wraps function body with HTTP stream processing.
2370///
2371/// This attribute macro generates code that wraps the function body with a check to see if
2372/// data can be read from an HTTP stream. The function body is only executed
2373/// if data is successfully read from the stream.
2374///
2375/// This attribute macro generates code that wraps the function body with a check to see if
2376/// data can be read from an HTTP stream. The function body is only executed
2377/// if data is successfully read from the stream.
2378///
2379/// # Arguments
2380///
2381/// - `TokenStream`: The buffer to read from the HTTP stream.
2382/// - `TokenStream`: The function item to be modified
2383///
2384/// # Returns
2385///
2386/// Returns a TokenStream containing the modified function with HTTP stream processing logic.
2387///
2388/// # Examples
2389///
2390/// Using with epilogue_macros:
2391/// ```rust
2392/// use hyperlane::*;
2393/// use hyperlane_macros::*;
2394///
2395/// #[route("/request_query")]
2396/// struct RequestQuery;
2397///
2398/// impl ServerHook for RequestQuery {
2399/// async fn new(_ctx: &Context) -> Self {
2400/// Self
2401/// }
2402///
2403/// #[epilogue_macros(
2404/// request_query("test" => request_query_option),
2405/// response_body(&format!("request query: {request_query_option:?}")),
2406/// send,
2407/// http_from_stream(1024)
2408/// )]
2409/// async fn handle(self, ctx: &Context) {}
2410/// }
2411/// ```
2412///
2413/// Using with variable name:
2414/// ```rust
2415/// use hyperlane::*;
2416/// use hyperlane_macros::*;
2417///
2418/// #[route("/request_header")]
2419/// struct RequestHeader;
2420///
2421/// impl ServerHook for RequestHeader {
2422/// async fn new(_ctx: &Context) -> Self {
2423/// Self
2424/// }
2425///
2426/// #[epilogue_macros(
2427/// request_header(HOST => request_header_option),
2428/// response_body(&format!("request header: {request_header_option:?}")),
2429/// send,
2430/// http_from_stream(_request)
2431/// )]
2432/// async fn handle(self, ctx: &Context) {}
2433/// }
2434/// ```
2435#[proc_macro_attribute]
2436pub fn http_from_stream(attr: TokenStream, item: TokenStream) -> TokenStream {
2437 http_from_stream_macro(attr, item)
2438}