Convert to Rust 2018 edition (#2084)
* Convert to Rust 2018 edition * Update gitignore
This commit is contained in:
+10
-7
@@ -12,11 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::router::{Handler, HandlerObj, ResponseFuture};
|
||||
use futures::future::ok;
|
||||
use hyper::header::{HeaderValue, AUTHORIZATION, WWW_AUTHENTICATE};
|
||||
use hyper::{Body, Request, Response, StatusCode};
|
||||
use ring::constant_time::verify_slices_are_equal;
|
||||
use router::{Handler, HandlerObj, ResponseFuture};
|
||||
|
||||
// Basic Authentication Middleware
|
||||
pub struct BasicAuthMiddleware {
|
||||
@@ -37,12 +37,14 @@ impl Handler for BasicAuthMiddleware {
|
||||
fn call(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut handlers: Box<Iterator<Item = HandlerObj>>,
|
||||
mut handlers: Box<dyn Iterator<Item = HandlerObj>>,
|
||||
) -> ResponseFuture {
|
||||
if req.headers().contains_key(AUTHORIZATION) && verify_slices_are_equal(
|
||||
req.headers()[AUTHORIZATION].as_bytes(),
|
||||
&self.api_basic_auth.as_bytes(),
|
||||
).is_ok()
|
||||
if req.headers().contains_key(AUTHORIZATION)
|
||||
&& verify_slices_are_equal(
|
||||
req.headers()[AUTHORIZATION].as_bytes(),
|
||||
&self.api_basic_auth.as_bytes(),
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
handlers.next().unwrap().call(req, handlers)
|
||||
} else {
|
||||
@@ -58,7 +60,8 @@ fn unauthorized_response(basic_realm: &str) -> ResponseFuture {
|
||||
.header(
|
||||
WWW_AUTHENTICATE,
|
||||
HeaderValue::from_str(basic_realm).unwrap(),
|
||||
).body(Body::empty())
|
||||
)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
Box::new(ok(response))
|
||||
}
|
||||
|
||||
+12
-11
@@ -14,22 +14,20 @@
|
||||
|
||||
//! High level JSON/HTTP client API
|
||||
|
||||
use crate::rest::{Error, ErrorKind};
|
||||
use crate::util::to_base64;
|
||||
use failure::{Fail, ResultExt};
|
||||
use futures::future::{err, ok, Either};
|
||||
use http::uri::{InvalidUri, Uri};
|
||||
use hyper::header::{ACCEPT, AUTHORIZATION, USER_AGENT};
|
||||
use hyper::rt::{Future, Stream};
|
||||
use hyper::{Body, Client, Request};
|
||||
use hyper_rustls;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
|
||||
use futures::future::{err, ok, Either};
|
||||
use hyper_rustls;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use rest::{Error, ErrorKind};
|
||||
use util::to_base64;
|
||||
|
||||
pub type ClientResponseFuture<T> = Box<Future<Item = T, Error = Error> + Send>;
|
||||
pub type ClientResponseFuture<T> = Box<dyn Future<Item = T, Error = Error> + Send>;
|
||||
|
||||
/// Helper function to easily issue a HTTP GET request against a given URL that
|
||||
/// returns a JSON object. Handles request building, JSON deserialization and
|
||||
@@ -143,7 +141,8 @@ fn build_request<'a>(
|
||||
.body(match body {
|
||||
None => Body::empty(),
|
||||
Some(json) => json.into(),
|
||||
}).map_err(|e| {
|
||||
})
|
||||
.map_err(|e| {
|
||||
ErrorKind::RequestError(format!("Bad request {} {}: {}", method, url, e)).into()
|
||||
})
|
||||
}
|
||||
@@ -185,7 +184,7 @@ where
|
||||
}))
|
||||
}
|
||||
|
||||
fn send_request_async(req: Request<Body>) -> Box<Future<Item = String, Error = Error> + Send> {
|
||||
fn send_request_async(req: Request<Body>) -> Box<dyn Future<Item = String, Error = Error> + Send> {
|
||||
let https = hyper_rustls::HttpsConnector::new(1);
|
||||
let client = Client::builder().build::<_, Body>(https);
|
||||
Box::new(
|
||||
@@ -196,14 +195,16 @@ fn send_request_async(req: Request<Body>) -> Box<Future<Item = String, Error = E
|
||||
if !resp.status().is_success() {
|
||||
Either::A(err(ErrorKind::RequestError(
|
||||
"Wrong response code".to_owned(),
|
||||
).into()))
|
||||
)
|
||||
.into()))
|
||||
} else {
|
||||
Either::B(
|
||||
resp.into_body()
|
||||
.map_err(|e| {
|
||||
ErrorKind::RequestError(format!("Cannot read response body: {}", e))
|
||||
.into()
|
||||
}).concat2()
|
||||
})
|
||||
.concat2()
|
||||
.and_then(|ch| ok(String::from_utf8_lossy(&ch.to_vec()).to_string())),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ mod server_api;
|
||||
mod transactions_api;
|
||||
mod utils;
|
||||
|
||||
use router::{Router, RouterError};
|
||||
use crate::router::{Router, RouterError};
|
||||
|
||||
// Server
|
||||
use self::server_api::IndexHandler;
|
||||
@@ -48,15 +48,15 @@ use self::peers_api::PeerHandler;
|
||||
use self::peers_api::PeersAllHandler;
|
||||
use self::peers_api::PeersConnectedHandler;
|
||||
|
||||
use auth::BasicAuthMiddleware;
|
||||
use chain;
|
||||
use p2p;
|
||||
use pool;
|
||||
use rest::*;
|
||||
use crate::auth::BasicAuthMiddleware;
|
||||
use crate::chain;
|
||||
use crate::p2p;
|
||||
use crate::pool;
|
||||
use crate::rest::*;
|
||||
use crate::util;
|
||||
use crate::util::RwLock;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use util;
|
||||
use util::RwLock;
|
||||
|
||||
/// Start all server HTTP handlers. Register all of them with Router
|
||||
/// and runs the corresponding HTTP server.
|
||||
@@ -13,18 +13,18 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::utils::{get_output, w};
|
||||
use chain;
|
||||
use core::core::hash::Hash;
|
||||
use core::core::hash::Hashed;
|
||||
use crate::chain;
|
||||
use crate::core::core::hash::Hash;
|
||||
use crate::core::core::hash::Hashed;
|
||||
use crate::rest::*;
|
||||
use crate::router::{Handler, ResponseFuture};
|
||||
use crate::types::*;
|
||||
use crate::util;
|
||||
use crate::web::*;
|
||||
use failure::ResultExt;
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use regex::Regex;
|
||||
use rest::*;
|
||||
use router::{Handler, ResponseFuture};
|
||||
use std::sync::Weak;
|
||||
use types::*;
|
||||
use util;
|
||||
use web::*;
|
||||
|
||||
/// Gets block headers given either a hash or height or an output commit.
|
||||
/// GET /v1/headers/<hash>
|
||||
|
||||
@@ -13,18 +13,18 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::utils::{get_output, w};
|
||||
use chain;
|
||||
use core::core::hash::Hashed;
|
||||
use crate::chain;
|
||||
use crate::core::core::hash::Hashed;
|
||||
use crate::rest::*;
|
||||
use crate::router::{Handler, ResponseFuture};
|
||||
use crate::types::*;
|
||||
use crate::util;
|
||||
use crate::util::secp::pedersen::Commitment;
|
||||
use crate::web::*;
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use rest::*;
|
||||
use router::{Handler, ResponseFuture};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Weak;
|
||||
use types::*;
|
||||
use url::form_urlencoded;
|
||||
use util;
|
||||
use util::secp::pedersen::Commitment;
|
||||
use web::*;
|
||||
|
||||
/// Chain handler. Get the head details.
|
||||
/// GET /v1/chain
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::utils::w;
|
||||
use crate::p2p;
|
||||
use crate::p2p::types::{PeerInfoDisplay, ReasonForBan};
|
||||
use crate::router::{Handler, ResponseFuture};
|
||||
use crate::web::*;
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use p2p;
|
||||
use p2p::types::{PeerInfoDisplay, ReasonForBan};
|
||||
use router::{Handler, ResponseFuture};
|
||||
use std::sync::Weak;
|
||||
use web::*;
|
||||
|
||||
pub struct PeersAllHandler {
|
||||
pub peers: Weak<p2p::Peers>,
|
||||
|
||||
@@ -13,22 +13,22 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::utils::w;
|
||||
use core::core::hash::Hashed;
|
||||
use core::core::Transaction;
|
||||
use core::ser;
|
||||
use crate::core::core::hash::Hashed;
|
||||
use crate::core::core::Transaction;
|
||||
use crate::core::ser;
|
||||
use crate::pool;
|
||||
use crate::rest::*;
|
||||
use crate::router::{Handler, ResponseFuture};
|
||||
use crate::types::*;
|
||||
use crate::util;
|
||||
use crate::util::RwLock;
|
||||
use crate::web::*;
|
||||
use futures::future::ok;
|
||||
use futures::Future;
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use pool;
|
||||
use rest::*;
|
||||
use router::{Handler, ResponseFuture};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Weak;
|
||||
use types::*;
|
||||
use url::form_urlencoded;
|
||||
use util;
|
||||
use util::RwLock;
|
||||
use web::*;
|
||||
|
||||
/// Get basic information about the transaction pool.
|
||||
/// GET /v1/pool
|
||||
@@ -60,7 +60,7 @@ pub struct PoolPushHandler {
|
||||
}
|
||||
|
||||
impl PoolPushHandler {
|
||||
fn update_pool(&self, req: Request<Body>) -> Box<Future<Item = (), Error = Error> + Send> {
|
||||
fn update_pool(&self, req: Request<Body>) -> Box<dyn Future<Item = (), Error = Error> + Send> {
|
||||
let params = match req.uri().query() {
|
||||
Some(query_string) => form_urlencoded::parse(query_string.as_bytes())
|
||||
.into_owned()
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::utils::w;
|
||||
use chain;
|
||||
use crate::chain;
|
||||
use crate::p2p;
|
||||
use crate::rest::*;
|
||||
use crate::router::{Handler, ResponseFuture};
|
||||
use crate::types::*;
|
||||
use crate::web::*;
|
||||
use hyper::{Body, Request};
|
||||
use p2p;
|
||||
use rest::*;
|
||||
use router::{Handler, ResponseFuture};
|
||||
use std::sync::Weak;
|
||||
use types::*;
|
||||
use web::*;
|
||||
|
||||
// RESTful index of available api endpoints
|
||||
// GET /v1/
|
||||
|
||||
@@ -13,18 +13,18 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::utils::w;
|
||||
use chain;
|
||||
use crate::chain;
|
||||
use crate::rest::*;
|
||||
use crate::router::{Handler, ResponseFuture};
|
||||
use crate::types::*;
|
||||
use crate::util;
|
||||
use crate::util::secp::pedersen::Commitment;
|
||||
use crate::web::*;
|
||||
use failure::ResultExt;
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use rest::*;
|
||||
use router::{Handler, ResponseFuture};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Weak;
|
||||
use types::*;
|
||||
use url::form_urlencoded;
|
||||
use util;
|
||||
use util::secp::pedersen::Commitment;
|
||||
use web::*;
|
||||
|
||||
// Sum tree handler. Retrieve the roots:
|
||||
// GET /v1/txhashset/roots
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use chain;
|
||||
use core::core::{OutputFeatures, OutputIdentifier};
|
||||
use crate::chain;
|
||||
use crate::core::core::{OutputFeatures, OutputIdentifier};
|
||||
use crate::rest::*;
|
||||
use crate::types::*;
|
||||
use crate::util;
|
||||
use crate::util::secp::pedersen::Commitment;
|
||||
use failure::ResultExt;
|
||||
use rest::*;
|
||||
use std::sync::{Arc, Weak};
|
||||
use types::*;
|
||||
use util;
|
||||
use util::secp::pedersen::Commitment;
|
||||
|
||||
// All handlers use `Weak` references instead of `Arc` to avoid cycles that
|
||||
// can never be destroyed. These 2 functions are simple helpers to reduce the
|
||||
|
||||
+22
-27
@@ -12,36 +12,31 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
extern crate grin_chain as chain;
|
||||
extern crate grin_core as core;
|
||||
extern crate grin_p2p as p2p;
|
||||
extern crate grin_pool as pool;
|
||||
extern crate grin_store as store;
|
||||
extern crate grin_util as util;
|
||||
extern crate url;
|
||||
use grin_chain as chain;
|
||||
use grin_core as core;
|
||||
use grin_p2p as p2p;
|
||||
use grin_pool as pool;
|
||||
|
||||
extern crate failure;
|
||||
use grin_util as util;
|
||||
|
||||
use failure;
|
||||
#[macro_use]
|
||||
extern crate failure_derive;
|
||||
extern crate hyper;
|
||||
use hyper;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate regex;
|
||||
extern crate ring;
|
||||
extern crate serde;
|
||||
|
||||
use serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
use serde_json;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate futures;
|
||||
extern crate http;
|
||||
extern crate hyper_rustls;
|
||||
extern crate rustls;
|
||||
extern crate tokio;
|
||||
extern crate tokio_core;
|
||||
extern crate tokio_rustls;
|
||||
extern crate tokio_tcp;
|
||||
|
||||
use hyper_rustls;
|
||||
use rustls;
|
||||
|
||||
use tokio_tcp;
|
||||
|
||||
pub mod auth;
|
||||
pub mod client;
|
||||
@@ -51,9 +46,9 @@ mod router;
|
||||
mod types;
|
||||
mod web;
|
||||
|
||||
pub use auth::BasicAuthMiddleware;
|
||||
pub use handlers::start_rest_apis;
|
||||
pub use rest::*;
|
||||
pub use router::*;
|
||||
pub use types::*;
|
||||
pub use web::*;
|
||||
pub use crate::auth::BasicAuthMiddleware;
|
||||
pub use crate::handlers::start_rest_apis;
|
||||
pub use crate::rest::*;
|
||||
pub use crate::router::*;
|
||||
pub use crate::types::*;
|
||||
pub use crate::web::*;
|
||||
|
||||
+10
-7
@@ -18,12 +18,12 @@
|
||||
//! To use it, just have your service(s) implement the ApiEndpoint trait and
|
||||
//! register them on a ApiServer.
|
||||
|
||||
use crate::router::{Handler, HandlerObj, ResponseFuture, Router};
|
||||
use failure::{Backtrace, Context, Fail, ResultExt};
|
||||
use futures::sync::oneshot;
|
||||
use futures::Stream;
|
||||
use hyper::rt::Future;
|
||||
use hyper::{rt, Body, Request, Server};
|
||||
use router::{Handler, HandlerObj, ResponseFuture, Router};
|
||||
use rustls;
|
||||
use rustls::internal::pemfile;
|
||||
use std::fmt::{self, Display};
|
||||
@@ -55,7 +55,7 @@ pub enum ErrorKind {
|
||||
}
|
||||
|
||||
impl Fail for Error {
|
||||
fn cause(&self) -> Option<&Fail> {
|
||||
fn cause(&self) -> Option<&dyn Fail> {
|
||||
self.inner.cause()
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ impl Fail for Error {
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,8 @@ impl ApiServer {
|
||||
.map_err(|e| eprintln!("HTTP API server error: {}", e));
|
||||
|
||||
rt::run(server);
|
||||
}).map_err(|_| ErrorKind::Internal("failed to spawn API thread".to_string()).into())
|
||||
})
|
||||
.map_err(|_| ErrorKind::Internal("failed to spawn API thread".to_string()).into())
|
||||
}
|
||||
|
||||
/// Starts the TLS ApiServer at the provided address.
|
||||
@@ -228,13 +229,15 @@ impl ApiServer {
|
||||
error!("accept_async failed: {}", e);
|
||||
Ok(None)
|
||||
}
|
||||
}).filter_map(|x| x);
|
||||
})
|
||||
.filter_map(|x| x);
|
||||
let server = Server::builder(tls)
|
||||
.serve(router)
|
||||
.map_err(|e| eprintln!("HTTP API server error: {}", e));
|
||||
|
||||
rt::run(server);
|
||||
}).map_err(|_| ErrorKind::Internal("failed to spawn API thread".to_string()).into())
|
||||
})
|
||||
.map_err(|_| ErrorKind::Internal("failed to spawn API thread".to_string()).into())
|
||||
}
|
||||
|
||||
/// Stops the API server, it panics in case of error
|
||||
@@ -258,7 +261,7 @@ impl Handler for LoggingMiddleware {
|
||||
fn call(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut handlers: Box<Iterator<Item = HandlerObj>>,
|
||||
mut handlers: Box<dyn Iterator<Item = HandlerObj>>,
|
||||
) -> ResponseFuture {
|
||||
debug!("REST call: {} {}", req.method(), req.uri().path());
|
||||
handlers.next().unwrap().call(req, handlers)
|
||||
|
||||
+6
-5
@@ -26,7 +26,7 @@ lazy_static! {
|
||||
static ref WILDCARD_STOP_HASH: u64 = calculate_hash(&"**");
|
||||
}
|
||||
|
||||
pub type ResponseFuture = Box<Future<Item = Response<Body>, Error = hyper::Error> + Send>;
|
||||
pub type ResponseFuture = Box<dyn Future<Item = Response<Body>, Error = hyper::Error> + Send>;
|
||||
|
||||
pub trait Handler {
|
||||
fn get(&self, _req: Request<Body>) -> ResponseFuture {
|
||||
@@ -68,7 +68,7 @@ pub trait Handler {
|
||||
fn call(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut _handlers: Box<Iterator<Item = HandlerObj>>,
|
||||
mut _handlers: Box<dyn Iterator<Item = HandlerObj>>,
|
||||
) -> ResponseFuture {
|
||||
match req.method() {
|
||||
&Method::GET => self.get(req),
|
||||
@@ -105,7 +105,7 @@ struct NodeId(usize);
|
||||
|
||||
const MAX_CHILDREN: usize = 16;
|
||||
|
||||
pub type HandlerObj = Arc<Handler + Send + Sync>;
|
||||
pub type HandlerObj = Arc<dyn Handler + Send + Sync>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Node {
|
||||
@@ -147,7 +147,8 @@ impl Router {
|
||||
.find(|&id| {
|
||||
let node_key = self.node(*id).key;
|
||||
node_key == key || node_key == *WILDCARD_HASH || node_key == *WILDCARD_STOP_HASH
|
||||
}).cloned()
|
||||
})
|
||||
.cloned()
|
||||
}
|
||||
|
||||
fn add_empty_node(&mut self, parent: NodeId, key: u64) -> NodeId {
|
||||
@@ -225,7 +226,7 @@ impl NewService for Router {
|
||||
type Error = hyper::Error;
|
||||
type InitError = hyper::Error;
|
||||
type Service = Router;
|
||||
type Future = Box<Future<Item = Self::Service, Error = Self::InitError> + Send>;
|
||||
type Future = Box<dyn Future<Item = Self::Service, Error = Self::InitError> + Send>;
|
||||
fn new_service(&self) -> Self::Future {
|
||||
Box::new(future::ok(self.clone()))
|
||||
}
|
||||
|
||||
+11
-10
@@ -14,17 +14,17 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use chain;
|
||||
use core::core::hash::Hashed;
|
||||
use core::core::merkle_proof::MerkleProof;
|
||||
use core::{core, ser};
|
||||
use p2p;
|
||||
use crate::chain;
|
||||
use crate::core::core::hash::Hashed;
|
||||
use crate::core::core::merkle_proof::MerkleProof;
|
||||
use crate::core::{core, ser};
|
||||
use crate::p2p;
|
||||
use crate::util;
|
||||
use crate::util::secp::pedersen;
|
||||
use serde;
|
||||
use serde::de::MapAccess;
|
||||
use serde::ser::SerializeStruct;
|
||||
use std::fmt;
|
||||
use util;
|
||||
use util::secp::pedersen;
|
||||
|
||||
macro_rules! no_dup {
|
||||
($field:ident) => {
|
||||
@@ -210,7 +210,7 @@ struct PrintableCommitmentVisitor;
|
||||
impl<'de> serde::de::Visitor<'de> for PrintableCommitmentVisitor {
|
||||
type Value = PrintableCommitment;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("a Pedersen commitment")
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ impl<'de> serde::de::Deserialize<'de> for OutputPrintable {
|
||||
impl<'de> serde::de::Visitor<'de> for OutputPrintableVisitor {
|
||||
type Value = OutputPrintable;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("a print able Output")
|
||||
}
|
||||
|
||||
@@ -571,7 +571,8 @@ impl BlockPrintable {
|
||||
Some(&block.header),
|
||||
include_proof,
|
||||
)
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
let kernels = block
|
||||
.kernels()
|
||||
.iter()
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
use crate::rest::*;
|
||||
use crate::router::ResponseFuture;
|
||||
use futures::future::{err, ok};
|
||||
use futures::{Future, Stream};
|
||||
use hyper::{Body, Request, Response, StatusCode};
|
||||
use rest::*;
|
||||
use router::ResponseFuture;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Parse request body
|
||||
pub fn parse_body<T>(req: Request<Body>) -> Box<Future<Item = T, Error = Error> + Send>
|
||||
pub fn parse_body<T>(req: Request<Body>) -> Box<dyn Future<Item = T, Error = Error> + Send>
|
||||
where
|
||||
for<'de> T: Deserialize<'de> + Send + 'static,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user