Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API handlers refactoring #2572

Merged
merged 1 commit into from
Feb 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions api/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ where
}
}

/// Helper function to easily issue a HTTP GET request
/// on a given URL that returns nothing. Handles request
/// building and response code checking.
pub fn get_no_ret(url: &str, api_secret: Option<String>) -> Result<(), Error> {
let req = build_request(url, "GET", api_secret, None)?;
send_request(req)?;
Ok(())
}

/// Helper function to easily issue a HTTP POST request with the provided JSON
/// object as body on a given URL that returns a JSON object. Handles request
/// building, JSON serialization and deserialization, and response code
Expand Down
12 changes: 2 additions & 10 deletions api/src/handlers/blocks_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::utils::{get_output, w};
use crate::chain;
use crate::core::core::hash::Hash;
Expand Down Expand Up @@ -68,10 +67,7 @@ impl HeaderHandler {

impl Handler for HeaderHandler {
fn get(&self, req: Request<Body>) -> ResponseFuture {
let el = match req.uri().path().trim_right_matches('/').rsplit('/').next() {
None => return response(StatusCode::BAD_REQUEST, "invalid url"),
Some(el) => el,
};
let el = right_path_element!(req);
result_to_response(self.get_header(el.to_string()))
}
}
Expand Down Expand Up @@ -130,11 +126,7 @@ fn check_block_param(input: &String) -> Result<(), Error> {

impl Handler for BlockHandler {
fn get(&self, req: Request<Body>) -> ResponseFuture {
let el = match req.uri().path().trim_right_matches('/').rsplit('/').next() {
None => return response(StatusCode::BAD_REQUEST, "invalid url"),
Some(el) => el,
};

let el = right_path_element!(req);
let h = match self.parse_input(el.to_string()) {
Err(e) => {
return response(
Expand Down
76 changes: 13 additions & 63 deletions api/src/handlers/chain_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ use crate::util;
use crate::util::secp::pedersen::Commitment;
use crate::web::*;
use hyper::{Body, Request, StatusCode};
use std::collections::HashMap;
use std::sync::Weak;
use url::form_urlencoded;

/// Chain handler. Get the head details.
/// GET /v1/chain
Expand Down Expand Up @@ -101,21 +99,9 @@ impl OutputHandler {
fn outputs_by_ids(&self, req: &Request<Body>) -> Result<Vec<Output>, Error> {
let mut commitments: Vec<String> = vec![];

let query = match req.uri().query() {
Some(q) => q,
None => return Err(ErrorKind::RequestError("no query string".to_owned()))?,
};
let params = form_urlencoded::parse(query.as_bytes())
.into_owned()
.collect::<Vec<(String, String)>>();

for (k, id) in params {
if k == "id" {
for id in id.split(',') {
commitments.push(id.to_owned());
}
}
}
let query = must_get_query!(req);
let params = QueryParams::from(query);
params.process_multival_param("id", |id| commitments.push(id.to_owned()));

let mut outputs: Vec<Output> = vec![];
for x in commitments {
Expand Down Expand Up @@ -159,49 +145,17 @@ impl OutputHandler {
// returns outputs for a specified range of blocks
fn outputs_block_batch(&self, req: &Request<Body>) -> Result<Vec<BlockOutputs>, Error> {
let mut commitments: Vec<Commitment> = vec![];
let mut start_height = 1;
let mut end_height = 1;
let mut include_rp = false;

let query = match req.uri().query() {
Some(q) => q,
None => return Err(ErrorKind::RequestError("no query string".to_owned()))?,
};

let params = form_urlencoded::parse(query.as_bytes()).into_owned().fold(
HashMap::new(),
|mut hm, (k, v)| {
hm.entry(k).or_insert(vec![]).push(v);
hm
},
);

if let Some(ids) = params.get("id") {
for id in ids {
for id in id.split(',') {
if let Ok(x) = util::from_hex(String::from(id)) {
commitments.push(Commitment::from_vec(x));
}
}
let query = must_get_query!(req);
let params = QueryParams::from(query);
params.process_multival_param("id", |id| {
if let Ok(x) = util::from_hex(String::from(id)) {
commitments.push(Commitment::from_vec(x));
}
}
if let Some(heights) = params.get("start_height") {
for height in heights {
start_height = height
.parse()
.map_err(|_| ErrorKind::RequestError("invalid start_height".to_owned()))?;
}
}
if let Some(heights) = params.get("end_height") {
for height in heights {
end_height = height
.parse()
.map_err(|_| ErrorKind::RequestError("invalid end_height".to_owned()))?;
}
}
if let Some(_) = params.get("include_rp") {
include_rp = true;
}
});
let start_height = parse_param!(params, "start_height", 1);
let end_height = parse_param!(params, "end_height", 1);
let include_rp = params.get("include_rp").is_some();

debug!(
"outputs_block_batch: {}-{}, {:?}, {:?}",
Expand All @@ -223,11 +177,7 @@ impl OutputHandler {

impl Handler for OutputHandler {
fn get(&self, req: Request<Body>) -> ResponseFuture {
let command = match req.uri().path().trim_right_matches('/').rsplit('/').next() {
Some(c) => c,
None => return response(StatusCode::BAD_REQUEST, "invalid url"),
};
match command {
match right_path_element!(req) {
"byids" => result_to_response(self.outputs_by_ids(&req)),
"byheight" => result_to_response(self.outputs_block_batch(&req)),
_ => response(StatusCode::BAD_REQUEST, ""),
Expand Down
15 changes: 6 additions & 9 deletions api/src/handlers/peers_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ pub struct PeersConnectedHandler {

impl Handler for PeersConnectedHandler {
fn get(&self, _req: Request<Body>) -> ResponseFuture {
let mut peers: Vec<PeerInfoDisplay> = vec![];
for p in &w(&self.peers).connected_peers() {
let peer_info = p.info.clone();
peers.push(peer_info.into());
}
let peers: Vec<PeerInfoDisplay> = w(&self.peers)
.connected_peers()
.iter()
.map(|p| p.info.clone().into())
.collect();
json_response(&peers)
}
}
Expand All @@ -56,10 +56,7 @@ pub struct PeerHandler {

impl Handler for PeerHandler {
fn get(&self, req: Request<Body>) -> ResponseFuture {
let command = match req.uri().path().trim_right_matches('/').rsplit('/').next() {
Some(c) => c,
None => return response(StatusCode::BAD_REQUEST, "invalid url"),
};
let command = right_path_element!(req);
if let Ok(addr) = command.parse() {
match w(&self.peers).get_peer(addr) {
Ok(peer) => json_response(&peer),
Expand Down
26 changes: 9 additions & 17 deletions api/src/handlers/pool_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ use crate::types::*;
use crate::util;
use crate::util::RwLock;
use crate::web::*;
use failure::ResultExt;
use futures::future::ok;
use futures::Future;
use hyper::{Body, Request, StatusCode};
use std::collections::HashMap;
use std::sync::Weak;
use url::form_urlencoded;

/// Get basic information about the transaction pool.
/// GET /v1/pool
Expand Down Expand Up @@ -61,15 +60,7 @@ pub struct PoolPushHandler {

impl PoolPushHandler {
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()
.fold(HashMap::new(), |mut hm, (k, v)| {
hm.entry(k).or_insert(vec![]).push(v);
hm
}),
None => HashMap::new(),
};
let params = QueryParams::from(req.uri().query());

let fluff = params.get("fluff").is_some();
let pool_arc = w(&self.tx_pool).clone();
Expand Down Expand Up @@ -99,13 +90,14 @@ impl PoolPushHandler {

// Push to tx pool.
let mut tx_pool = pool_arc.write();
let header = tx_pool.blockchain.chain_head().unwrap();
tx_pool
let header = tx_pool
.blockchain
.chain_head()
.context(ErrorKind::Internal("Failed to get chain head".to_owned()))?;
let res = tx_pool
.add_to_pool(source, tx, !fluff, &header)
.map_err(|e| {
error!("update_pool: failed with error: {:?}", e);
ErrorKind::Internal(format!("Failed to update pool: {:?}", e)).into()
})
.context(ErrorKind::Internal("Failed to update pool".to_owned()))?;
Ok(res)
}),
)
}
Expand Down
59 changes: 6 additions & 53 deletions api/src/handlers/transactions_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ use crate::util::secp::pedersen::Commitment;
use crate::web::*;
use failure::ResultExt;
use hyper::{Body, Request, StatusCode};
use std::collections::HashMap;
use std::sync::Weak;
use url::form_urlencoded;

// Sum tree handler. Retrieve the roots:
// GET /v1/txhashset/roots
Expand Down Expand Up @@ -114,59 +112,14 @@ impl TxHashSetHandler {

impl Handler for TxHashSetHandler {
fn get(&self, req: Request<Body>) -> ResponseFuture {
let mut start_index = 1;
let mut max = 100;
let mut id = "".to_owned();

// TODO: probably need to set a reasonable max limit here
let mut last_n = 10;
if let Some(query_string) = req.uri().query() {
let params = form_urlencoded::parse(query_string.as_bytes())
.into_owned()
.fold(HashMap::new(), |mut hm, (k, v)| {
hm.entry(k).or_insert(vec![]).push(v);
hm
});
if let Some(nums) = params.get("n") {
for num in nums {
if let Ok(n) = str::parse(num) {
last_n = n;
}
}
}
if let Some(start_indexes) = params.get("start_index") {
for si in start_indexes {
if let Ok(s) = str::parse(si) {
start_index = s;
}
}
}
if let Some(maxes) = params.get("max") {
for ma in maxes {
if let Ok(m) = str::parse(ma) {
max = m;
}
}
}
if let Some(ids) = params.get("id") {
if !ids.is_empty() {
id = ids.last().unwrap().to_owned();
}
}
}
let command = match req
.uri()
.path()
.trim_right()
.trim_right_matches("/")
.rsplit("/")
.next()
{
Some(c) => c,
None => return response(StatusCode::BAD_REQUEST, "invalid url"),
};
let params = QueryParams::from(req.uri().query());
let last_n = parse_param_no_err!(params, "n", 10);
let start_index = parse_param_no_err!(params, "start_index", 1);
let max = parse_param_no_err!(params, "max", 100);
let id = parse_param_no_err!(params, "id", "".to_owned());

match command {
match right_path_element!(req) {
"roots" => json_response_pretty(&self.get_roots()),
"lastoutputs" => json_response_pretty(&self.get_last_n_output(last_n)),
"lastrangeproofs" => json_response_pretty(&self.get_last_n_rangeproof(last_n)),
Expand Down
15 changes: 9 additions & 6 deletions api/src/handlers/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ pub fn get_output(
OutputIdentifier::new(OutputFeatures::Coinbase, &commit),
];

for x in outputs.iter() {
if let Ok(_) = w(chain).is_unspent(&x) {
let block_height = w(chain).get_header_for_output(&x).unwrap().height;
let output_pos = w(chain).get_output_pos(&x.commit).unwrap_or(0);
return Ok((Output::new(&commit, block_height, output_pos), x.clone()));
}
for x in outputs.iter().filter(|x| w(chain).is_unspent(x).is_ok()) {
let block_height = w(chain)
.get_header_for_output(&x)
.context(ErrorKind::Internal(
"Can't get header for output".to_owned(),
))?
.height;
let output_pos = w(chain).get_output_pos(&x.commit).unwrap_or(0);
return Ok((Output::new(&commit, block_height, output_pos), x.clone()));
}
Err(ErrorKind::NotFound)?
}
3 changes: 2 additions & 1 deletion api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ extern crate serde_derive;
#[macro_use]
extern crate log;

#[macro_use]
mod web;
pub mod auth;
pub mod client;
mod handlers;
mod rest;
mod router;
mod types;
mod web;

pub use crate::auth::BasicAuthMiddleware;
pub use crate::handlers::start_rest_apis;
Expand Down
Loading