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}