rweb/
lib.rs

1//! A macro to convert a function to rweb handler.
2//!
3//! All parameters should satisfy one of the following.
4//!
5//!   - Has a path parameter with same name.
6//!   - Annotated with the annotations documented below.
7//!   - Has a type which implements [FromRequest].
8//!
9//!
10//! # Path parmeters
11//!
12//!
13//! # Attributes on function item
14//!
15//! ## `#[header("content-type", "application/json")]`
16//!
17//! Make a route matches only if value of the header matches provided value.
18//!
19//! ```rust
20//! use rweb::*;
21//!
22//! #[get("/")]
23//! #[header("accept", "*/*")]
24//! fn routes() -> &'static str {
25//!    "This route matches only if accept header is '*/*'"
26//! }
27//!
28//! fn main() {
29//!     serve(routes());
30//! }
31//! ```
32//!
33//! ## `#[cors]`
34//!
35//!
36//! ```rust
37//! use rweb::*;
38//!
39//! #[get("/")]
40//! #[cors(origins("example.com"), max_age = 600)]
41//! fn cors_1() -> String {
42//!    unreachable!()
43//! }
44//!
45//! #[get("/")]
46//! #[cors(origins("example.com"), methods(get), max_age = 600)]
47//! fn cors_2() -> String {
48//!    unreachable!()
49//! }
50//!
51//! #[get("/")]
52//! #[cors(origins("*"), methods(get), max_age = 600)]
53//! fn cors_3() -> String {
54//!    unreachable!()
55//! }
56//!
57//! #[get("/")]
58//! #[cors(
59//!     origins("*"),
60//!     methods(get, post, patch, delete),
61//!     headers("accept"),
62//!     max_age = 600
63//! )]
64//! fn cors_4() -> String {
65//!    unreachable!()
66//! }
67//! ```
68//!
69//! ## `#[body_size(max = "8192")]`
70//! ```rust
71//! use rweb::*;
72//!
73//! #[get("/")]
74//! #[body_size(max = "8192")]
75//! fn body_size() -> String {
76//!    unreachable!()
77//! }
78//! ```
79//!
80//!
81//! # Attributes on parameters
82//!
83//! ## `#[body]`
84//!
85//! Parses request body. Type is `bytes::Bytes`.
86//! ```rust
87//! use rweb::*;
88//! use http::Error;
89//! use bytes::Bytes;
90//!
91//! #[post("/body")]
92//! fn body(#[body] body: Bytes) -> Result<String, Error> {
93//!    let _ = body;
94//!    Ok(String::new())
95//! }
96//!
97//! fn main() {
98//!     serve(body());
99//! }
100//! ```
101//!
102//! ## `#[form]`
103//! Parses request body. `Content-Type` should be `x-www-form-urlencoded`.
104//! ```rust
105//! use rweb::*;
106//! use serde::Deserialize;
107//!
108//! #[derive(Deserialize)]
109//! struct LoginForm {
110//!     id: String,
111//!     password: String,
112//! }
113//!
114//! #[post("/form")]
115//! fn form(#[form] body: LoginForm) -> String {
116//!    String::from("Ok")
117//! }
118//!
119//! fn main() {
120//!     serve(form());
121//! }
122//! ```
123//!
124//! ## `#[json]`
125//! Parses request body. `Content-Type` should be `application/json`.
126//! ```rust
127//! use rweb::*;
128//! use serde::Deserialize;
129//!
130//! #[derive(Deserialize)]
131//! struct LoginForm {
132//!     id: String,
133//!     password: String,
134//! }
135//!
136//! #[post("/json")]
137//! fn json(#[json] body: LoginForm) -> String {
138//!     String::from("Ok")
139//! }
140//!
141//! fn main() {
142//!     serve(json());
143//! }
144//! ```
145//!
146//! Note that you can mix the order of parameters.
147//! ```rust
148//! use rweb::*;
149//! use serde::Deserialize;
150//!
151//! #[derive(Deserialize)]
152//! struct LoginForm {
153//!     id: String,
154//!     password: String,
155//! }
156//!
157//! #[get("/param/{a}/{b}")]
158//! fn body_between_path_params(a: u32, #[json] body: LoginForm, b: u32) ->
159//! String {     assert_eq!(body.id, "TEST_ID");
160//!     assert_eq!(body.password, "TEST_PASSWORD");
161//!     (a + b).to_string()
162//! }
163//!
164//! fn main() {
165//!     serve(body_between_path_params());
166//! }
167//! ```
168//!
169//! ## `#[query]`
170//!
171//! Parses query string.
172//! ```rust
173//! use rweb::*;
174//!
175//! #[get("/")]
176//! fn use_query(#[query] qs: String) -> String {
177//!     qs
178//! }
179//!
180//! fn main() {
181//!     serve(use_query());
182//! }
183//! ```
184//!
185//! ## `#[header = "header-name"]`
186//! Value of the header.
187//! ```rust
188//! use rweb::*;
189//!
190//! #[get("/")]
191//! fn ret_accept(#[header = "accept"] accept: String) -> String {
192//!     accept
193//! }
194//! fn main() {
195//!     serve(ret_accept());
196//! }
197//! ```
198//!
199//! ## `#[cookie = "cookie-name"]`
200//! Value of the header.
201//! ```rust
202//! use rweb::*;
203//!
204//! #[get("/")]
205//! fn cookie(#[header = "sess"] sess_id: String) -> String {
206//!     sess_id
207//! }
208//! fn main() {
209//!     serve(cookie());
210//! }
211//! ```
212//!
213//! ## `#[filter = "path_to_fn"]`
214//! Calls function.
215//!
216//! **Note**: If the callee returns `()`, you should use `()` as type. (Type
217//! alias is not allowed)
218//! ```rust
219//! use std::num::NonZeroU16;
220//! use rweb::*;
221//! use serde::Serialize;
222//!
223//! #[derive(Serialize)]
224//! struct Math {
225//!     op: String,
226//!     output: u16,
227//! }
228//!
229//! #[get("/math/{num}")]
230//! fn math(num: u16, #[filter = "div_by"] denom: NonZeroU16) -> impl Reply {
231//!     rweb::reply::json(&Math {
232//!         op: format!("{} / {}", num, denom),
233//!         output: num / denom.get(),
234//!     })
235//! }
236//!
237//! fn div_by() -> impl Filter<Extract = (NonZeroU16,), Error = Rejection> +Copy
238//! {    rweb::header::<u16>("div-by").and_then(|n: u16| async move {
239//!        if let Some(denom) = NonZeroU16::new(n) {
240//!            Ok(denom)
241//!        } else {
242//!            Err(reject::custom(DivideByZero))
243//!        }
244//!    })
245//! }
246//!
247//! #[derive(Debug)]
248//! struct DivideByZero;
249//!
250//! impl reject::Reject for DivideByZero {}
251//!
252//! fn main() {
253//!     serve(math());
254//! }
255//! ```
256//!
257//! ## `#[data]`
258//! ```rust
259//! use futures::lock::Mutex;
260//! use rweb::*;
261//! use std::sync::Arc;
262//!
263//! #[derive(Clone, Default)]
264//! struct Db {
265//!    items: Arc<Mutex<Vec<String>>>,
266//! }
267//!
268//! #[get("/")]
269//! async fn index(#[data] db: Db) -> Result<String, Rejection> {
270//!    let items = db.items.lock().await;
271//!
272//!    Ok(items.len().to_string())
273//! }
274//!
275//! fn main() {
276//!     let db = Default::default();
277//!     serve(index(db));
278//! }
279//! ```
280//!
281//! # FromRequest
282//! ```rust
283//! use http::StatusCode;
284//! use rweb::{filters::BoxedFilter, *};
285//!
286//! impl FromRequest for User {
287//!    type Filter = BoxedFilter<(User,)>;
288//!
289//!    fn new() -> Self::Filter {
290//!        // In real world, you can use a header like Authorization
291//!        header::<String>("x-user-id").map(|id| User { id }).boxed()
292//!    }
293//! }
294//!
295//!
296//! #[derive(Schema)]
297//! struct User {
298//!    id: String,
299//! }
300//!
301//! #[get("/")]
302//! fn index(user: User) -> String {
303//!    user.id
304//! }
305//!
306//! fn main() {
307//!     serve(index());
308//! }
309//! ```
310//!
311//!
312//! # Guards
313//! ```rust
314//! use rweb::*;
315//!
316//! // This handler is invoked only if x-appengine-cron matches 1 (case insensitive).
317//! #[get("/")]
318//! #[header("X-AppEngine-Cron", "1")]
319//! fn gae_cron() -> String {
320//!     String::new()
321//! }
322//! ```
323//!
324//! # `#[router]`
325//!
326//! `#[router]` can be used to group routes.
327//!
328//! ## `#[data]`
329//!
330//! You can use `#[data]` with a router.
331//! ```rust
332//! use rweb::*;
333//!
334//! #[derive(Default, Clone)]
335//! struct Db {}
336//!
337//! #[get("/use")]
338//! fn use_db(#[data] _db: Db) -> String {
339//!    String::new()
340//! }
341//!
342//! #[router("/data", services(use_db))]
343//! fn data_param(#[data] db: Db) {}
344//! ```
345//!
346//!
347//! ## Guard
348//! ```rust
349//! use rweb::*;
350//!
351//! #[get("/")]
352//! fn admin_index() -> String {
353//!    String::new()
354//! }
355//!
356//! #[get("/users")]
357//! fn admin_users() -> String {
358//!    String::new()
359//! }
360//!
361//! #[router("/admin", services(admin_index, admin_users))]
362//! #[header("X-User-Admin", "1")]
363//! fn admin() {}
364//! ```
365
366pub use self::factory::{Form, FromRequest, Json, Query};
367pub use rweb_macros::{delete, get, head, options, patch, post, put, router, Schema};
368pub use warp::{self, *};
369
370#[cfg(feature = "openapi")]
371pub mod docs;
372#[cfg(feature = "openapi")]
373pub use self::docs::*;
374mod factory;
375#[cfg(feature = "openapi")]
376pub mod openapi;
377#[doc(hidden)]
378pub mod rt;
379
380pub mod routes;
381pub use self::routes::*;