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
//! Strongly typed HTTP methods and their traits
macro_rules! method (
($(#[$meta:meta])* pub struct $method:ident) => (
$(#[$meta])*
#[derive(Debug)]
pub struct $method;
impl Method for $method {
fn to_hyper(&self) -> ::hyper::method::Method {
::hyper::method::Method::$method
}
}
);
($($(#[$meta:meta])* pub struct $method:ident);+;) =>(
$(method!($(#[$meta])* pub struct $method);)+
)
);
macro_rules! takes_body (
($method:ident) => (
impl TakesBody for $method {}
);
($($method:ident),+) => (
$(takes_body!($method);)+
);
);
method! {
/// Method for `GET` requests.
///
/// ### Note: Body
/// While `GET` requests are not forbidden to have a body by the HTTP spec,
/// it is not meaningful to provide a body with a `GET` request and any endpoint
/// that expects a body with such a request is considered non-conformant.
pub struct Get;
/// Method for `POST` requests, can take a body.
pub struct Post;
/// Method for `PUT` requests, can take a body.
pub struct Put;
/// Method for `PATCH` requests, can take a body.
pub struct Patch;
/// Method for `DELETE` requests.
///
/// ### Note: Body
/// While `DELETE` requests are not forbidden to have a body by the HTTP spec,
/// it is not meaningful to provide a body with a `DELETE` request and any endpoint
/// that expects a body with such a request is considered non-conformant.
pub struct Delete;
}
#[doc(hidden)]
pub struct ForceBody;
impl Method for ForceBody {
fn to_hyper(&self) -> ::hyper::method::Method {
panic!("`ForceBody` is not an actual HTTP method; you must have caught a panic \
during a `force_body!()` invocation and continued outside.")
}
}
takes_body! { Post, Put, Patch, ForceBody }
/// The HTTP method of a request in Anterofit.
pub trait Method {
/// Convert to Hyper's `Method` enum.
fn to_hyper(&self) -> ::hyper::method::Method;
}
/// Trait describing an HTTP method which is allowed to have a body.
///
/// ### Motivation
/// Though not forbidden in the HTTP spec, `GET` and `DELETE` requests are generally not
/// meant to have bodies, and it is recommended for servers to ignore bodies on such
/// requests ([IETF RFC 2616 (HTTP 1.1 Spec), Section 4.3][rfc2616-4.3]).
///
/// Thus, this trait acts as a strongly typed anti-footgun for when you specified a
/// `GET` or `DELETE` request when you actually meant `POST` or `PUT` or `PATCH`.
///
/// If you must have a body on a `GET` or `DELETE` request, you can use the
/// `force_body!()` macro to override this protection.
///
/// [rfc2616-4.3]: https://tools.ietf.org/html/rfc2616#section-4.3
pub trait TakesBody {}