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}