edgedb_sdk/web/
mod.rs

1//! Web server handling API
2//!
3//! This module contains facilities needed to process HTTP requests.
4//!
5//! # Register Web Handler
6//!
7//! To register web handler it's usually enoght to use the attribute:
8//!
9//! ```rust,no_run
10//! use edgedb_sdk::web;
11//! #[web::handler]
12//! fn web_handler(req: web::Request) -> web::Response {
13//!     web::response()
14//!         .status(web::StatusCode::OK)
15//!         .header("Content-Type", "text/html")
16//!         .body("Hello <b>World</b>".into())
17//!         .expect("response is built")
18//! }
19//! ```
20//!
21//! # Programmatically Register Web Handler
22//!
23//! It's sometimes useful to do that programmatically. This is usually done in
24//! [`init_hook`](macro@crate::init_hook) and [`register_handler()`]:
25//!
26//! ```rust,no_run
27//! use edgedb_sdk::{init_hook, web};
28//!
29//! #[init_hook]
30//! fn init() {
31//!     web::register_handler(web_handler);
32//! }
33//!
34//! fn web_handler(req: web::Request) -> web::Response {
35//!     todo!();
36//! }
37//! ```
38use once_cell::sync::OnceCell;
39
40pub use edgedb_sdk_macros::web_handler as handler;
41pub use http::StatusCode;
42
43/// Re-exported type from [`http`](http::Response) crate
44pub type Response = http::Response<Vec<u8>>;
45
46/// Web Request
47///
48/// Currently it dereferences to [`http::Request`] so see its documentation
49/// for more info.
50#[derive(Debug)]
51pub struct Request {
52    pub(crate) inner: http::Request<Vec<u8>>,
53}
54
55type WebHandler = fn(Request) -> Response;
56pub(crate) static WEB_HANDLER: OnceCell<WebHandler> = OnceCell::new();
57
58/// Register a function as a web handler
59///
60/// # Panics
61///
62/// Panics if called more than once (including implicitly by [`handler`]
63/// macro).
64pub fn register_handler(f: WebHandler) {
65    WEB_HANDLER.set(f).expect("only one handler is expected");
66}
67
68/// Create a response builder
69///
70/// See [`http`](`http::response::Builder`) crate documentation for more info.
71pub fn response() -> http::response::Builder {
72    http::Response::builder()
73}
74
75impl AsRef<http::Request<Vec<u8>>> for Request {
76    fn as_ref(&self) -> &http::Request<Vec<u8>> {
77        &self.inner
78    }
79}
80
81impl std::ops::Deref for Request {
82    type Target = http::Request<Vec<u8>>;
83    fn deref(&self) -> &http::Request<Vec<u8>> {
84        &self.inner
85    }
86}
87
88impl Into<http::Request<Vec<u8>>> for Request {
89    fn into(self) -> http::Request<Vec<u8>> {
90        self.inner
91    }
92}