serenity/http/mod.rs
1//! The HTTP module which provides functions for performing requests to endpoints in Discord's API.
2//!
3//! An important function of the REST API is ratelimiting. Requests to endpoints are ratelimited to
4//! prevent spam, and once ratelimited Discord will stop performing requests. The library
5//! implements protection to pre-emptively ratelimit, to ensure that no wasted requests are made.
6//!
7//! The HTTP module comprises of two types of requests:
8//! - REST API requests, which require an authorization token;
9//! - Other requests, which do not require an authorization token.
10//!
11//! The former require a [`Client`] to have logged in, while the latter may be made regardless of
12//! any other usage of the library.
13//!
14//! If a request spuriously fails, it will be retried once.
15//!
16//! Note that you may want to perform requests through a [model]s' instance methods where possible,
17//! as they each offer different levels of a high-level interface to the HTTP module.
18//!
19//! [`Client`]: crate::Client
20//! [model]: crate::model
21
22mod client;
23mod error;
24mod multipart;
25mod ratelimiting;
26mod request;
27mod routing;
28mod typing;
29
30use std::sync::Arc;
31
32use reqwest::Method;
33pub use reqwest::StatusCode;
34
35pub use self::client::*;
36pub use self::error::*;
37pub use self::multipart::*;
38pub use self::ratelimiting::*;
39pub use self::request::*;
40pub use self::routing::*;
41pub use self::typing::*;
42#[cfg(feature = "cache")]
43use crate::cache::Cache;
44#[cfg(feature = "client")]
45use crate::client::Context;
46use crate::model::prelude::*;
47
48/// This trait will be required by functions that need [`Http`] and can optionally use a [`Cache`]
49/// to potentially avoid REST-requests.
50///
51/// The types [`Context`] and [`Http`] implement this trait and thus passing these to functions
52/// expecting `impl CacheHttp` is possible. For the full list of implementations, see the
53/// Implementors and Implementations on Foreign Types section in the generated docs.
54///
55/// In a situation where you have the `cache`-feature enabled but you do not pass a cache, the
56/// function will behave as if no `cache`-feature is active.
57///
58/// If you are calling a function that expects `impl CacheHttp` as argument and you wish to utilise
59/// the `cache`-feature but you got no access to a [`Context`], you can pass a tuple of
60/// `(&Arc<Cache>, &Http)`.
61pub trait CacheHttp: Send + Sync {
62 fn http(&self) -> &Http;
63
64 #[cfg(feature = "cache")]
65 #[must_use]
66 fn cache(&self) -> Option<&Arc<Cache>> {
67 None
68 }
69}
70
71impl<T> CacheHttp for &T
72where
73 T: CacheHttp,
74{
75 fn http(&self) -> &Http {
76 (*self).http()
77 }
78 #[cfg(feature = "cache")]
79 fn cache(&self) -> Option<&Arc<Cache>> {
80 (*self).cache()
81 }
82}
83
84impl<T> CacheHttp for Arc<T>
85where
86 T: CacheHttp,
87{
88 fn http(&self) -> &Http {
89 (**self).http()
90 }
91 #[cfg(feature = "cache")]
92 fn cache(&self) -> Option<&Arc<Cache>> {
93 (**self).cache()
94 }
95}
96
97#[cfg(feature = "client")]
98impl CacheHttp for Context {
99 fn http(&self) -> &Http {
100 &self.http
101 }
102 #[cfg(feature = "cache")]
103 fn cache(&self) -> Option<&Arc<Cache>> {
104 Some(&self.cache)
105 }
106}
107
108#[cfg(feature = "cache")]
109impl CacheHttp for (&Arc<Cache>, &Http) {
110 fn cache(&self) -> Option<&Arc<Cache>> {
111 Some(self.0)
112 }
113 fn http(&self) -> &Http {
114 self.1
115 }
116}
117
118impl CacheHttp for Http {
119 fn http(&self) -> &Http {
120 self
121 }
122}
123
124#[cfg(feature = "cache")]
125impl AsRef<Cache> for (&Arc<Cache>, &Http) {
126 fn as_ref(&self) -> &Cache {
127 self.0
128 }
129}
130
131#[cfg(feature = "cache")]
132impl AsRef<Http> for (&Arc<Cache>, &Http) {
133 fn as_ref(&self) -> &Http {
134 self.1
135 }
136}
137
138/// An method used for ratelimiting special routes.
139///
140/// This is needed because [`reqwest`]'s [`Method`] enum does not derive Copy.
141#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
142pub enum LightMethod {
143 /// Indicates that a route is for the `DELETE` method only.
144 Delete,
145 /// Indicates that a route is for the `GET` method only.
146 Get,
147 /// Indicates that a route is for the `PATCH` method only.
148 Patch,
149 /// Indicates that a route is for the `POST` method only.
150 Post,
151 /// Indicates that a route is for the `PUT` method only.
152 Put,
153}
154
155impl LightMethod {
156 #[must_use]
157 pub const fn reqwest_method(self) -> Method {
158 match self {
159 Self::Delete => Method::DELETE,
160 Self::Get => Method::GET,
161 Self::Patch => Method::PATCH,
162 Self::Post => Method::POST,
163 Self::Put => Method::PUT,
164 }
165 }
166}
167
168/// Representation of the method of a query to send for the [`Http::get_guilds`] function.
169#[non_exhaustive]
170pub enum GuildPagination {
171 /// The Id to get the guilds after.
172 After(GuildId),
173 /// The Id to get the guilds before.
174 Before(GuildId),
175}
176
177/// Representation of the method of a query to send for the [`Http::get_scheduled_event_users`] and
178/// [`Http::get_bans`] functions.
179#[non_exhaustive]
180pub enum UserPagination {
181 /// The Id to get the users after.
182 After(UserId),
183 /// The Id to get the users before.
184 Before(UserId),
185}
186
187#[derive(Clone, Copy, Debug)]
188#[non_exhaustive]
189pub enum MessagePagination {
190 After(MessageId),
191 Around(MessageId),
192 Before(MessageId),
193}