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