diff options
author | Ferris Tseng <ferristseng@gmail.com> | 2019-02-13 20:38:01 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-13 20:38:01 -0500 |
commit | de3588c7c369ea4f4cca66f89c12511d1170e5f5 (patch) | |
tree | 965a5a80b387c0eb719ca568a96a729d9d3f2ade /ipfs-api/src | |
parent | f125fdbde329095419630e02ebf33d2c73aeced7 (diff) | |
parent | 4bdebbf4d1d1edb839eba860b013e3fdb870f66e (diff) |
Merge pull request #28 from ferristseng/actix
Add actix feature for using actix-web
Diffstat (limited to 'ipfs-api/src')
-rw-r--r-- | ipfs-api/src/client.rs | 168 | ||||
-rw-r--r-- | ipfs-api/src/header.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/lib.rs | 206 | ||||
-rw-r--r-- | ipfs-api/src/read.rs | 11 | ||||
-rw-r--r-- | ipfs-api/src/request/add.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/request/block.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/request/config.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/request/dag.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/request/files.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/request/mod.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/request/tar.rs | 2 | ||||
-rw-r--r-- | ipfs-api/src/response/error.rs | 41 |
12 files changed, 323 insertions, 119 deletions
diff --git a/ipfs-api/src/client.rs b/ipfs-api/src/client.rs index 0c3277b..5e1e9f5 100644 --- a/ipfs-api/src/client.rs +++ b/ipfs-api/src/client.rs @@ -5,19 +5,22 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. // - +#[cfg(feature = "actix")] +use actix_multipart::client::multipart; +#[cfg(feature = "actix")] +use actix_web::HttpMessage; +use bytes::Bytes; use futures::{ future, stream::{self, Stream}, Future, IntoFuture, }; use header::TRAILER; -use http::uri::InvalidUri; -use hyper::{ - self, - client::{Client, HttpConnector}, - Chunk, Request, Response, StatusCode, Uri, -}; +use http::uri::{InvalidUri, Uri}; +use http::StatusCode; +#[cfg(feature = "hyper")] +use hyper::client::{Client, HttpConnector}; +#[cfg(feature = "hyper")] use hyper_multipart::client::multipart; use read::{JsonLineDecoder, LineDecoder, StreamReader}; use request::{self, ApiRequest}; @@ -31,17 +34,34 @@ use tokio_codec::{Decoder, FramedRead}; /// A response returned by the HTTP client. /// +#[cfg(feature = "actix")] +type AsyncResponse<T> = Box<Future<Item = T, Error = Error> + 'static>; +#[cfg(feature = "hyper")] type AsyncResponse<T> = Box<Future<Item = T, Error = Error> + Send + 'static>; /// A future that returns a stream of responses. /// +#[cfg(feature = "actix")] +type AsyncStreamResponse<T> = Box<Stream<Item = T, Error = Error> + 'static>; +#[cfg(feature = "hyper")] type AsyncStreamResponse<T> = Box<Stream<Item = T, Error = Error> + Send + 'static>; +#[cfg(feature = "actix")] +type Request = actix_web::client::ClientRequest; +#[cfg(feature = "hyper")] +type Request = http::Request<hyper::Body>; + +#[cfg(feature = "actix")] +type Response = actix_web::client::ClientResponse; +#[cfg(feature = "hyper")] +type Response = http::Response<hyper::Body>; + /// Asynchronous Ipfs client. /// #[derive(Clone)] pub struct IpfsClient { base: Uri, + #[cfg(feature = "hyper")] client: Client<HttpConnector, hyper::Body>, } @@ -101,6 +121,7 @@ impl IpfsClient { Ok(IpfsClient { base: base_path, + #[cfg(feature = "hyper")] client: Client::builder().keep_alive(false).build_http(), }) } @@ -117,7 +138,7 @@ impl IpfsClient { &self, req: &Req, form: Option<multipart::Form<'static>>, - ) -> Result<Request<hyper::Body>, Error> + ) -> Result<Request, Error> where Req: ApiRequest + Serialize, { @@ -127,9 +148,9 @@ impl IpfsClient { Req::PATH, ::serde_urlencoded::to_string(req)? ); - - url.parse::<Uri>().map_err(From::from).and_then(move |url| { - let mut builder = Request::builder(); + #[cfg(feature = "hyper")] + let req = url.parse::<Uri>().map_err(From::from).and_then(move |url| { + let mut builder = http::Request::builder(); let mut builder = builder.method(Req::METHOD.clone()).uri(url); let req = if let Some(form) = form { @@ -139,13 +160,29 @@ impl IpfsClient { }; req.map_err(From::from) - }) + }); + #[cfg(feature = "actix")] + let req = if let Some(form) = form { + Request::build() + .method(Req::METHOD.clone()) + .uri(url) + .content_type(form.content_type()) + .streaming(multipart::Body::from(form)) + .map_err(From::from) + } else { + Request::build() + .method(Req::METHOD.clone()) + .uri(url) + .finish() + .map_err(From::from) + }; + req } /// Builds an Api error from a response body. /// #[inline] - fn build_error_from_body(chunk: Chunk) -> Error { + fn build_error_from_body(chunk: Bytes) -> Error { match serde_json::from_slice(&chunk) { Ok(e) => Error::Api(e), Err(_) => match String::from_utf8(chunk.to_vec()) { @@ -158,7 +195,7 @@ impl IpfsClient { /// Processes a response that expects a json encoded body, returning an /// error or a deserialized json response. /// - fn process_json_response<Res>(status: StatusCode, chunk: Chunk) -> Result<Res, Error> + fn process_json_response<Res>(status: StatusCode, chunk: Bytes) -> Result<Res, Error> where for<'de> Res: 'static + Deserialize<'de>, { @@ -171,15 +208,19 @@ impl IpfsClient { /// Processes a response that returns a stream of json deserializable /// results. /// - fn process_stream_response<D, Res>( - res: Response<hyper::Body>, - decoder: D, - ) -> AsyncStreamResponse<Res> + fn process_stream_response<D, Res>(res: Response, decoder: D) -> AsyncStreamResponse<Res> where D: 'static + Decoder<Item = Res, Error = Error> + Send, Res: 'static, { - let stream = FramedRead::new(StreamReader::new(res.into_body().from_err()), decoder); + #[cfg(feature = "hyper")] + let stream = FramedRead::new( + StreamReader::new(res.into_body().map(|c| c.into_bytes()).from_err()), + decoder, + ); + + #[cfg(feature = "actix")] + let stream = FramedRead::new(StreamReader::new(res.payload().from_err()), decoder); Box::new(stream) } @@ -190,22 +231,33 @@ impl IpfsClient { &self, req: &Req, form: Option<multipart::Form<'static>>, - ) -> AsyncResponse<(StatusCode, Chunk)> + ) -> AsyncResponse<(StatusCode, Bytes)> where Req: ApiRequest + Serialize, { match self.build_base_request(req, form) { Ok(req) => { + #[cfg(feature = "hyper")] let res = self .client .request(req) .and_then(|res| { let status = res.status(); - res.into_body().concat2().map(move |chunk| (status, chunk)) + res.into_body() + .concat2() + .map(move |chunk| (status, chunk.into_bytes())) }) .from_err(); - + #[cfg(feature = "actix")] + let res = req + .send() + .timeout(std::time::Duration::from_secs(90)) + .from_err() + .and_then(|x| { + let status = x.status(); + x.body().map(move |body| (status, body)).from_err() + }); Box::new(res) } Err(e) => Box::new(Err(e).into_future()), @@ -224,8 +276,9 @@ impl IpfsClient { where Req: ApiRequest + Serialize, Res: 'static + Send, - F: 'static + Fn(hyper::Response<hyper::Body>) -> AsyncStreamResponse<Res> + Send, + F: 'static + Fn(Response) -> AsyncStreamResponse<Res> + Send, { + #[cfg(feature = "hyper")] match self.build_base_request(req, form) { Ok(req) => { let res = self @@ -244,7 +297,9 @@ impl IpfsClient { res.into_body() .concat2() .from_err() - .and_then(|chunk| Err(Self::build_error_from_body(chunk))) + .and_then(|chunk| { + Err(Self::build_error_from_body(chunk.into_bytes())) + }) .into_stream(), ), }; @@ -252,17 +307,31 @@ impl IpfsClient { stream }) .flatten_stream(); - Box::new(res) } Err(e) => Box::new(stream::once(Err(e))), } + #[cfg(feature = "actix")] + match self.build_base_request(req, form) { + Ok(req) => { + let res = req + .send() + .timeout(std::time::Duration::from_secs(90)) + .from_err(); + Box::new(res.map(process).flatten_stream()) + } + Err(e) => Box::new(stream::once(Err(e))), + } } /// Generic method for making a request to the Ipfs server, and getting /// a deserializable response. /// - fn request<Req, Res>(&self, req: &Req, form: Option<multipart::Form<'static>>) -> AsyncResponse<Res> + fn request<Req, Res>( + &self, + req: &Req, + form: Option<multipart::Form<'static>>, + ) -> AsyncResponse<Res> where Req: ApiRequest + Serialize, for<'de> Res: 'static + Deserialize<'de> + Send, @@ -277,7 +346,11 @@ impl IpfsClient { /// Generic method for making a request to the Ipfs server, and getting /// back a response with no body. /// - fn request_empty<Req>(&self, req: &Req, form: Option<multipart::Form<'static>>) -> AsyncResponse<()> + fn request_empty<Req>( + &self, + req: &Req, + form: Option<multipart::Form<'static>>, + ) -> AsyncResponse<()> where Req: ApiRequest + Serialize, { @@ -294,7 +367,11 @@ impl IpfsClient { /// Generic method for making a request to the Ipfs server, and getting /// back a raw String response. /// - fn request_string<Req>(&self, req: &Req, form: Option<multipart::Form<'static>>) -> AsyncResponse<String> + fn request_string<Req>( + &self, + req: &Req, + form: Option<multipart::Form<'static>>, + ) -> AsyncResponse<String> where Req: ApiRequest + Serialize, { @@ -315,11 +392,17 @@ impl IpfsClient { &self, req: &Req, form: Option<multipart::Form<'static>>, - ) -> AsyncStreamResponse<Chunk> + ) -> AsyncStreamResponse<Bytes> where Req: ApiRequest + Serialize, { - self.request_stream(req, form, |res| Box::new(res.into_body().from_err())) + #[cfg(feature = "hyper")] + let res = self.request_stream(req, form, |res| { + Box::new(res.into_body().from_err().map(|c| c.into_bytes())) + }); + #[cfg(feature = "actix")] + let res = self.request_stream(req, form, |res| Box::new(res.payload().from_err())); + res } /// Generic method to return a streaming response of deserialized json @@ -595,7 +678,7 @@ impl IpfsClient { /// ``` /// #[inline] - pub fn block_get(&self, hash: &str) -> AsyncStreamResponse<Chunk> { + pub fn block_get(&self, hash: &str) -> AsyncStreamResponse<Bytes> { self.request_stream_bytes(&request::BlockGet { hash }, None) } @@ -747,7 +830,7 @@ impl IpfsClient { /// ``` /// #[inline] - pub fn cat(&self, path: &str) -> AsyncStreamResponse<Chunk> { + pub fn cat(&self, path: &str) -> AsyncStreamResponse<Bytes> { self.request_stream_bytes(&request::Cat { path }, None) } @@ -1204,7 +1287,7 @@ impl IpfsClient { /// ``` /// #[inline] - pub fn files_read(&self, path: &str) -> AsyncStreamResponse<Chunk> { + pub fn files_read(&self, path: &str) -> AsyncStreamResponse<Bytes> { self.request_stream_bytes(&request::FilesRead { path }, None) } @@ -1363,7 +1446,7 @@ impl IpfsClient { /// ``` /// #[inline] - pub fn get(&self, path: &str) -> AsyncStreamResponse<Chunk> { + pub fn get(&self, path: &str) -> AsyncStreamResponse<Bytes> { self.request_stream_bytes(&request::Get { path }, None) } @@ -1528,6 +1611,7 @@ impl IpfsClient { /// ``` /// pub fn log_tail(&self) -> AsyncStreamResponse<String> { + #[cfg(feature = "hyper")] let res = self .build_base_request(&request::LogTail, None) .map(|req| self.client.request(req).from_err()) @@ -1535,7 +1619,17 @@ impl IpfsClient { .flatten() .map(|res| IpfsClient::process_stream_response(res, LineDecoder)) .flatten_stream(); - + #[cfg(feature = "actix")] + let res = self + .build_base_request(&request::LogTail, None) + .into_future() + .and_then(|req| { + req.send() + .timeout(std::time::Duration::from_secs(90)) + .from_err() + }) + .map(|res| IpfsClient::process_stream_response(res, LineDecoder)) + .flatten_stream(); Box::new(res) } @@ -1644,7 +1738,7 @@ impl IpfsClient { /// ``` /// #[inline] - pub fn object_data(&self, key: &str) -> AsyncStreamResponse<Chunk> { + pub fn object_data(&self, key: &str) -> AsyncStreamResponse<Bytes> { self.request_stream_bytes(&request::ObjectData { key }, None) } @@ -2155,7 +2249,7 @@ impl IpfsClient { /// ``` /// #[inline] - pub fn tar_cat(&self, path: &str) -> AsyncStreamResponse<Chunk> { + pub fn tar_cat(&self, path: &str) -> AsyncStreamResponse<Bytes> { self.request_stream_bytes(&request::TarCat { path }, None) } diff --git a/ipfs-api/src/header.rs b/ipfs-api/src/header.rs index 9943bdb..009d178 100644 --- a/ipfs-api/src/header.rs +++ b/ipfs-api/src/header.rs @@ -6,6 +6,6 @@ // copied, modified, or distributed except according to those terms. // -pub use hyper::header::TRAILER; +pub use http::header::TRAILER; pub const X_STREAM_ERROR: &str = "x-stream-error"; diff --git a/ipfs-api/src/lib.rs b/ipfs-api/src/lib.rs index 503e482..64ea2f4 100644 --- a/ipfs-api/src/lib.rs +++ b/ipfs-api/src/lib.rs @@ -17,78 +17,152 @@ //! ipfs-api = "0.5.0-alpha2" //! ``` //! -//! ## Examples -//! -//! Write a file to IPFS: -//! -//! ```no_run -//! # extern crate hyper; -//! # extern crate ipfs_api; -//! # -//! use hyper::rt::Future; -//! use ipfs_api::IpfsClient; -//! use std::io::Cursor; -//! -//! # fn main() { -//! let client = IpfsClient::default(); -//! let data = Cursor::new("Hello World!"); -//! -//! let req = client -//! .add(data) -//! .map(|res| { -//! println!("{}", res.hash); -//! }) -//! .map_err(|e| eprintln!("{}", e)); -//! -//! hyper::rt::run(req); -//! # } -//! ``` -//! -//! Read a file from IPFS: -//! -//! ```no_run -//! # extern crate futures; -//! # extern crate hyper; -//! # extern crate ipfs_api; -//! # -//! use futures::{Future, Stream}; -//! use ipfs_api::IpfsClient; -//! use std::io::{self, Write}; -//! -//! # fn main() { -//! let client = IpfsClient::default(); -//! -//! let req = client -//! .get("/test/file.json") -//! .concat2() -//! .map(|res| { -//! let out = io::stdout(); -//! let mut out = out.lock(); -//! -//! out.write_all(&res).unwrap(); -//! }) -//! .map_err(|e| eprintln!("{}", e)); -//! -//! hyper::rt::run(req); -//! # } -//! ``` -//! -//! There are also a bunch of examples included in the project, which -//! I used for testing -//! -//! You can run any of the examples with cargo: -//! -//! ```sh -//! $ cargo run -p ipfs-api --example add_file -//! ``` + +#[cfg(feature = "actix")] +extern crate actix_multipart_rfc7578 as actix_multipart; + +/// ## Examples +/// +/// Write a file to IPFS: +/// +/// ```no_run +/// # extern crate actix_web; +/// # extern crate futures; +/// # extern crate ipfs_api; +/// # +/// use futures::future::Future; +/// use ipfs_api::IpfsClient; +/// use std::io::Cursor; +/// +/// # fn main() { +/// let client = IpfsClient::default(); +/// let data = Cursor::new("Hello World!"); +/// +/// let req = client +/// .add(data) +/// .map(|res| { +/// println!("{}", res.hash); +/// }) +/// .map_err(|e| eprintln!("{}", e)); +/// +/// tokio::runtime::current_thread::run(req); +/// # } +/// ``` +/// +/// Read a file from IPFS: +/// +/// ```no_run +/// # extern crate futures; +/// # extern crate actix_web; +/// # extern crate ipfs_api; +/// # +/// use futures::{Future, Stream}; +/// use ipfs_api::IpfsClient; +/// use std::io::{self, Write}; +/// +/// # fn main() { +/// let client = IpfsClient::default(); +/// +/// let req = client +/// .get("/test/file.json") +/// .concat2() +/// .map(|res| { +/// let out = io::stdout(); +/// let mut out = out.lock(); +/// +/// out.write_all(&res).unwrap(); +/// }) +/// .map_err(|e| eprintln!("{}", e)); +/// +/// tokio::runtime::current_thread::run(req); +/// # } +/// ``` +/// +/// There are also a bunch of examples included in the project, which +/// I used for testing +/// +/// You can run any of the examples with cargo: +/// +/// ```sh +/// $ cargo run -p ipfs-api --example add_file +/// ``` +#[cfg(feature = "actix")] +extern crate actix_web; + +/// ## Examples +/// +/// Write a file to IPFS: +/// +/// ```no_run +/// # extern crate hyper; +/// # extern crate ipfs_api; +/// # +/// use hyper::rt::Future; +/// use ipfs_api::IpfsClient; +/// use std::io::Cursor; +/// +/// # fn main() { +/// let client = IpfsClient::default(); +/// let data = Cursor::new("Hello World!"); +/// +/// let req = client +/// .add(data) +/// .map(|res| { +/// println!("{}", res.hash); +/// }) +/// .map_err(|e| eprintln!("{}", e)); +/// +/// hyper::rt::run(req); +/// # } +/// ``` +/// +/// Read a file from IPFS: +/// +/// ```no_run +/// # extern crate futures; +/// # extern crate hyper; +/// # extern crate ipfs_api; +/// # +/// use futures::{Future, Stream}; +/// use ipfs_api::IpfsClient; +/// use std::io::{self, Write}; +/// +/// # fn main() { +/// let client = IpfsClient::default(); +/// +/// let req = client +/// .get("/test/file.json") +/// .concat2() +/// .map(|res| { +/// let out = io::stdout(); +/// let mut out = out.lock(); +/// +/// out.write_all(&res).unwrap(); +/// }) +/// .map_err(|e| eprintln!("{}", e)); +/// +/// hyper::rt::run(req); +/// # } +/// ``` +/// +/// There are also a bunch of examples included in the project, which +/// I used for testing +/// +/// You can run any of the examples with cargo: +/// +/// ```sh +/// $ cargo run -p ipfs-api --example add_file +/// ``` +#[cfg(feature = "hyper")] +extern crate hyper; +#[cfg(feature = "hyper")] +extern crate hyper_multipart_rfc7578 as hyper_multipart; extern crate bytes; #[macro_use] extern crate failure; extern crate futures; extern crate http; -extern crate hyper; -extern crate hyper_multipart_rfc7578 as hyper_multipart; extern crate serde; #[macro_use] extern crate serde_derive; diff --git a/ipfs-api/src/read.rs b/ipfs-api/src/read.rs index b12c8b2..d9b2f98 100644 --- a/ipfs-api/src/read.rs +++ b/ipfs-api/src/read.rs @@ -6,10 +6,9 @@ // copied, modified, or distributed except according to those terms. // -use bytes::BytesMut; +use bytes::{Bytes, BytesMut}; use futures::{Async, Stream}; use header::X_STREAM_ERROR; -use hyper::Chunk; use response::Error; use serde::Deserialize; use serde_json; @@ -122,7 +121,7 @@ impl Decoder for LineDecoder { enum ReadState { /// A chunk is ready to be read from. /// - Ready(Chunk, usize), + Ready(Bytes, usize), /// The next chunk isn't ready yet. /// @@ -138,7 +137,7 @@ pub struct StreamReader<S> { impl<S> StreamReader<S> where - S: Stream<Item = Chunk, Error = Error>, + S: Stream<Item = Bytes, Error = Error>, { #[inline] pub fn new(stream: S) -> StreamReader<S> { @@ -151,7 +150,7 @@ where impl<S> Read for StreamReader<S> where - S: Stream<Item = Chunk, Error = Error>, + S: Stream<Item = Bytes, Error = Error>, { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { loop { @@ -203,4 +202,4 @@ where } } -impl<S> AsyncRead for StreamReader<S> where S: Stream<Item = Chunk, Error = Error> {} +impl<S> AsyncRead for StreamReader<S> where S: Stream<Item = Bytes, Error = Error> {} diff --git a/ipfs-api/src/request/add.rs b/ipfs-api/src/request/add.rs index be7960d..123ba4a 100644 --- a/ipfs-api/src/request/add.rs +++ b/ipfs-api/src/request/add.rs @@ -6,7 +6,7 @@ // copied, modified, or distributed except according to those terms. // -use hyper::Method; +use http::Method; use request::ApiRequest; pub struct Add; diff --git a/ipfs-api/src/request/block.rs b/ipfs-api/src/request/block.rs index 24f5d39..a6dd99c 100644 --- a/ipfs-api/src/request/block.rs +++ b/ipfs-api/src/request/block.rs @@ -6,7 +6,7 @@ // copied, modified, or distributed except according to those terms. // -use hyper::Method; +use http::Method; use request::ApiRequest; #[derive(Serialize)] diff --git a/ipfs-api/src/request/config.rs b/ipfs-api/src/request/config.rs index e586278..e3753ea 100644 --- a/ipfs-api/src/request/config.rs +++ b/ipfs-api/src/request/config.rs @@ -6,7 +6,7 @@ // copied, modified, or distributed except according to those terms. // -use hyper::Method; +use http::Method; use request::ApiRequest; pub struct ConfigEdit; diff --git a/ipfs-api/src/request/dag.rs b/ipfs-api/src/request/dag.rs index 78705f9..2d49c3a 100644 --- a/ipfs-api/src/request/dag.rs +++ b/ipfs-api/src/request/dag.rs @@ -6,7 +6,7 @@ // copied, modified, or distributed except according to those terms. // -use hyper::Method; +use http::Method; use request::ApiRequest; #[derive(Serialize)] diff --git a/ipfs-api/src/request/files.rs b/ipfs-api/src/request/files.rs index 179e1a4..394d7b3 100644 --- a/ipfs-api/src/request/files.rs +++ b/ipfs-api/src/request/files.rs @@ -6,7 +6,7 @@ // copied, modified, or distributed except according to those terms. // -use hyper::Method; +use http::Method; use request::ApiRequest; #[derive(Serialize)] diff --git a/ipfs-api/src/request/mod.rs b/ipfs-api/src/request/mod.rs index 947a912..52df37c 100644 --- a/ipfs-api/src/request/mod.rs +++ b/ipfs-api/src/request/mod.rs @@ -109,5 +109,5 @@ pub trait ApiRequest { /// Method used to make the request. /// - const METHOD: &'static ::hyper::Method = &::hyper::Method::GET; + const METHOD: &'static ::http::Method = &::http::Method::GET; } diff --git a/ipfs-api/src/request/tar.rs b/ipfs-api/src/request/tar.rs index 26772b9..05c1770 100644 --- a/ipfs-api/src/request/tar.rs +++ b/ipfs-api/src/request/tar.rs @@ -6,7 +6,7 @@ // copied, modified, or distributed except according to those terms. // -use hyper::Method; +use http::Method; use request::ApiRequest; pub struct TarAdd; diff --git a/ipfs-api/src/response/error.rs b/ipfs-api/src/response/error.rs index 94f7fa9..ca69de6 100644 --- a/ipfs-api/src/response/error.rs +++ b/ipfs-api/src/response/error.rs @@ -5,8 +5,10 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. // - +#[cfg(feature = "actix")] +use actix_web; use http; +#[cfg(feature = "hyper")] use hyper; use serde_json; use serde_urlencoded; @@ -23,10 +25,23 @@ pub struct ApiError { #[derive(Fail, Debug)] pub enum Error { - // Foreign errors. + /// Foreign errors. + #[cfg(feature = "hyper")] #[fail(display = "hyper client error '{}'", _0)] Client(hyper::Error), + #[cfg(feature = "actix")] + #[fail(display = "actix client error '{}'", _0)] + Client(actix_web::error::Error), + + #[cfg(feature = "actix")] + #[fail(display = "actix client payload error '{}'", _0)] + ClientPayload(actix_web::error::PayloadError), + + #[cfg(feature = "actix")] + #[fail(display = "actix client send request error '{}'", _0)] + ClientSend(actix_web::client::SendRequestError), + #[fail(display = "http error '{}'", _0)] Http(http::Error), @@ -61,12 +76,34 @@ pub enum Error { Uncategorized(String), } +#[cfg(feature = "hyper")] impl From<hyper::Error> for Error { fn from(err: hyper::Error) -> Error { Error::Client(err) } } +#[cfg(feature = "actix")] +impl From<actix_web::error::Error> for Error { + fn from(err: actix_web::error::Error) -> Error { + Error::Client(err) + } +} + +#[cfg(feature = "actix")] +impl From<actix_web::client::SendRequestError> for Error { + fn from(err: actix_web::client::SendRequestError) -> Error { + Error::ClientSend(err) + } +} + +#[cfg(feature = "actix")] +impl From<actix_web::error::PayloadError> for Error { + fn from(err: actix_web::error::PayloadError) -> Error { + Error::ClientPayload(err) + } +} + impl From<http::Error> for Error { fn from(err: http::Error) -> Error { Error::Http(err) |