aboutsummaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2018-08-05 12:01:54 -0700
committerZeyla Hellyer <[email protected]>2018-08-05 12:01:54 -0700
commit0d553630c1a9da216e42e7c0a9bedaccfedf678d (patch)
tree5156a26ea9d97b9e962458315eda40854437ce2b /src/http
parent[http] Abstract out routing methods and paths (diff)
downloadserenity-0d553630c1a9da216e42e7c0a9bedaccfedf678d.tar.xz
serenity-0d553630c1a9da216e42e7c0a9bedaccfedf678d.zip
Make http::fire, http::request public
Diffstat (limited to 'src/http')
-rw-r--r--src/http/mod.rs139
-rw-r--r--src/http/request.rs116
2 files changed, 207 insertions, 48 deletions
diff --git a/src/http/mod.rs b/src/http/mod.rs
index b3af412..75dd726 100644
--- a/src/http/mod.rs
+++ b/src/http/mod.rs
@@ -24,23 +24,22 @@
//! [model]: ../model/index.html
pub mod ratelimiting;
+pub mod request;
pub mod routing;
mod error;
-pub use self::error::Error as HttpError;
pub use hyper::status::{StatusClass, StatusCode};
+pub use self::error::Error as HttpError;
use constants;
use hyper::{
client::{
- Body as HyperBody,
Client as HyperClient,
- RequestBuilder,
Request as HyperRequest,
Response as HyperResponse
},
- header::{Authorization, ContentType, Headers, UserAgent},
+ header::{ContentType, Headers},
method::Method,
mime::{Mime, SubLevel, TopLevel},
net::HttpsConnector,
@@ -54,7 +53,10 @@ use internal::prelude::*;
use model::prelude::*;
use multipart::client::Multipart;
use parking_lot::Mutex;
-use self::routing::RouteInfo;
+use self::{
+ request::Request,
+ routing::RouteInfo,
+};
use serde::de::DeserializeOwned;
use serde_json;
use std::{
@@ -75,44 +77,6 @@ lazy_static! {
};
}
-#[derive(Clone, Debug)]
-struct Request<'a> {
- body: Option<&'a [u8]>,
- headers: Option<Headers>,
- route: RouteInfo<'a>,
-}
-
-impl<'a> Request<'a> {
- fn build(&'a self) -> RequestBuilder<'a> {
- let Request {
- body,
- headers: request_headers,
- route: route_info,
- } = self;
- let (method, _, path) = route_info.deconstruct();
-
- let mut builder = CLIENT.request(
- method.hyper_method(),
- &path.into_owned(),
- );
-
- if let Some(bytes) = body {
- builder = builder.body(HyperBody::BufBody(bytes, bytes.len()));
- }
-
- let mut headers = Headers::new();
- headers.set(UserAgent(constants::USER_AGENT.to_string()));
- headers.set(Authorization(TOKEN.lock().clone()));
- headers.set(ContentType::json());
-
- if let Some(request_headers) = request_headers.clone() {
- headers.extend(request_headers.iter());
- }
-
- builder.headers(headers)
- }
-}
-
/// An method used for ratelimiting special routes.
///
/// This is needed because `hyper`'s `Method` enum does not derive Copy.
@@ -1722,16 +1686,95 @@ pub fn unpin_message(channel_id: u64, message_id: u64) -> Result<()> {
/// Fires off a request, deserializing the response reader via the given type
/// bound.
///
-/// This is a clean wrapper around request functions manually writing this, and
-/// due to the type system can be used even further by going off the parent
-/// function's return type.
-fn fire<T: DeserializeOwned>(req: Request) -> Result<T> {
+/// If you don't need to deserialize the response and want the response instance
+/// itself, use [`request`].
+///
+/// # Examples
+///
+/// Create a new message via the [`RouteInfo::CreateMessage`] endpoint and
+/// deserialize the response into a [`Message`]:
+///
+/// ```rust,no_run
+/// # extern crate serenity;
+/// #
+/// # use std::error::Error;
+/// #
+/// # fn main() -> Result<(), Box<Error>> {
+/// #
+/// use serenity::{
+/// http::{
+/// self,
+/// request::RequestBuilder,
+/// routing::RouteInfo,
+/// },
+/// model::channel::Message,
+/// };
+///
+/// let bytes = vec![
+/// // payload bytes here
+/// ];
+/// let channel_id = 381880193700069377;
+/// let route_info = RouteInfo::CreateMessage { channel_id };
+///
+/// let mut request = RequestBuilder::new(route_info);
+/// request.body(Some(&bytes));
+///
+/// let message = http::fire::<Message>(request.build())?;
+///
+/// println!("Message content: {}", message.content);
+/// #
+/// # Ok(())
+/// # }
+/// ```
+///
+/// [`request`]: fn.request.html
+pub fn fire<T: DeserializeOwned>(req: Request) -> Result<T> {
let response = request(req)?;
serde_json::from_reader(response).map_err(From::from)
}
-fn request(req: Request) -> Result<HyperResponse> {
+/// Performs a request, ratelimiting it if necessary.
+///
+/// Returns the raw hyper Response. Use [`fire`] to deserialize the response
+/// into some type.
+///
+/// # Examples
+///
+/// Send a body of bytes over the [`RouteInfo::CreateMessage`] endpoint:
+///
+/// ```rust,no_run
+/// # extern crate serenity;
+/// #
+/// # use std::error::Error;
+/// #
+/// # fn main() -> Result<(), Box<Error>> {
+/// #
+/// use serenity::http::{
+/// self,
+/// request::RequestBuilder,
+/// routing::RouteInfo,
+/// };
+///
+/// let bytes = vec![
+/// // payload bytes here
+/// ];
+/// let channel_id = 381880193700069377;
+/// let route_info = RouteInfo::CreateMessage { channel_id };
+///
+/// let mut request = RequestBuilder::new(route_info);
+/// request.body(Some(&bytes));
+///
+/// let response = http::request(request.build())?;
+///
+/// println!("Response successful?: {}", response.status.is_success());
+/// #
+/// # Ok(())
+/// # }
+/// ```
+///
+/// [`fire`]: fn.fire.html
+pub fn request(req: Request) -> Result<HyperResponse> {
let response = ratelimiting::perform(req)?;
if response.status.class() == StatusClass::Success {
diff --git a/src/http/request.rs b/src/http/request.rs
new file mode 100644
index 0000000..885a4e5
--- /dev/null
+++ b/src/http/request.rs
@@ -0,0 +1,116 @@
+use constants;
+use hyper::{
+ client::{Body, RequestBuilder as HyperRequestBuilder},
+ header::{Authorization, ContentType, Headers, UserAgent},
+};
+use super::{
+ CLIENT,
+ TOKEN,
+ routing::RouteInfo,
+};
+
+pub struct RequestBuilder<'a> {
+ body: Option<&'a [u8]>,
+ headers: Option<Headers>,
+ route: RouteInfo<'a>,
+}
+
+impl<'a> RequestBuilder<'a> {
+ pub fn new(route_info: RouteInfo<'a>) -> Self {
+ Self {
+ body: None,
+ headers: None,
+ route: route_info,
+ }
+ }
+
+ pub fn build(self) -> Request<'a> {
+ Request::new(self)
+ }
+
+ pub fn body(&mut self, body: Option<&'a [u8]>) -> &mut Self {
+ self.body = body;
+
+ self
+ }
+
+ pub fn headers(&mut self, headers: Option<Headers>) -> &mut Self {
+ self.headers = headers;
+
+ self
+ }
+
+ pub fn route(&mut self, route_info: RouteInfo<'a>) -> &mut Self {
+ self.route = route_info;
+
+ self
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct Request<'a> {
+ pub(super) body: Option<&'a [u8]>,
+ pub(super) headers: Option<Headers>,
+ pub(super) route: RouteInfo<'a>,
+}
+
+impl<'a> Request<'a> {
+ pub fn new(builder: RequestBuilder<'a>) -> Self {
+ let RequestBuilder { body, headers, route } = builder;
+
+ Self { body, headers, route }
+ }
+
+ pub fn build(&'a self) -> HyperRequestBuilder<'a> {
+ let Request {
+ body,
+ headers: request_headers,
+ route: route_info,
+ } = self;
+ let (method, _, path) = route_info.deconstruct();
+
+ let mut builder = CLIENT.request(
+ method.hyper_method(),
+ &path.into_owned(),
+ );
+
+ if let Some(bytes) = body {
+ builder = builder.body(Body::BufBody(bytes, bytes.len()));
+ }
+
+ let mut headers = Headers::new();
+ headers.set(UserAgent(constants::USER_AGENT.to_string()));
+ headers.set(Authorization(TOKEN.lock().clone()));
+ headers.set(ContentType::json());
+
+ if let Some(request_headers) = request_headers.clone() {
+ headers.extend(request_headers.iter());
+ }
+
+ builder.headers(headers)
+ }
+
+ pub fn body_ref(&self) -> &Option<&'a [u8]> {
+ &self.body
+ }
+
+ pub fn body_mut(&mut self) -> &mut Option<&'a [u8]> {
+ &mut self.body
+ }
+
+ pub fn headers_ref(&self) -> &Option<Headers> {
+ &self.headers
+ }
+
+ pub fn headers_mut(&mut self) -> &mut Option<Headers> {
+ &mut self.headers
+ }
+
+ pub fn route_ref(&self) -> &RouteInfo {
+ &self.route
+ }
+
+ pub fn route_mut(&mut self) -> &mut RouteInfo<'a> {
+ &mut self.route
+ }
+}