Skip to content
This repository has been archived by the owner on Jun 3, 2020. It is now read-only.

Commit

Permalink
tendermint-rs: Use JSON request bodies for RPC calls
Browse files Browse the repository at this point in the history
This allows us to use POST requests and serde serialization when
creating requests, rather than trying to shove things into URIs.
  • Loading branch information
tony-iqlusion committed Apr 22, 2019
1 parent 9674ab4 commit 2d01b9b
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 77 deletions.
12 changes: 6 additions & 6 deletions tendermint-rs/src/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ impl Algorithm {
}
}

impl Display for Algorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}

impl FromStr for Algorithm {
type Err = Error;

Expand All @@ -155,12 +161,6 @@ impl FromStr for Algorithm {
}
}

impl Display for Algorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}

#[cfg(feature = "serde")]
impl Serialize for Algorithm {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
Expand Down
4 changes: 3 additions & 1 deletion tendermint-rs/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ mod client;
pub mod endpoint;
pub mod error;
mod id;
mod method;
pub mod request;
pub mod response;
mod version;

pub use self::{
client::Client, error::Error, id::Id, request::Request, response::Response, version::Version,
client::Client, error::Error, id::Id, method::Method, request::Request, response::Response,
version::Version,
};
19 changes: 14 additions & 5 deletions tendermint-rs/src/rpc/client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Tendermint RPC client

#![allow(unused_imports)]

use crate::{
block::Height,
net,
Expand Down Expand Up @@ -35,14 +33,18 @@ impl Client {
}

/// `/block`: get block at a given height.
// TODO(tarcieri): support for getting latest block
pub fn block<H>(&self, height: H) -> Result<block::Response, Error>
where
H: Into<Height>,
{
self.perform(block::Request::new(height.into()))
}

/// `/block`: get the latest block
pub fn latest_block(&self) -> Result<block::Response, Error> {
self.perform(block::Request::default())
}

/// `/blockchain`: get block headers for `min` <= `height` <= `max`.
///
/// Block headers are returned in descending order (highest first).
Expand All @@ -57,14 +59,18 @@ impl Client {
}

/// `/commit`: get block commit at a given height.
// TODO(tarcieri): support for getting latest block
pub fn commit<H>(&self, height: H) -> Result<commit::Response, Error>
where
H: Into<Height>,
{
self.perform(commit::Request::new(height.into()))
}

/// `/commit`: get the latest block commit
pub fn latest_commit(&self) -> Result<commit::Response, Error> {
self.perform(commit::Request::default())
}

/// `/health`: get node health.
///
/// Returns empty result (200 OK) on success, no response in case of an error.
Expand Down Expand Up @@ -94,6 +100,8 @@ impl Client {
where
R: rpc::Request,
{
let request_body = request.into_json();

let (host, port) = match &self.address {
net::Address::Tcp { host, port, .. } => (host, port),
other => Err(Error::invalid_params(&format!(
Expand All @@ -112,8 +120,9 @@ impl Client {
let http_client = hyper::Client::new();

let mut res = http_client
.get(&format!("http://{}:{}{}", host, port, request.path()))
.request(hyper::Post, &format!("http://{}:{}/", host, port))
.headers(headers)
.body(&request_body[..])
.send()
.map_err(Error::server_error)?;

Expand Down
6 changes: 3 additions & 3 deletions tendermint-rs/src/rpc/endpoint/abci_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializ
use subtle_encoding::base64;

/// Request ABCI information from a node
#[derive(Debug, Default)]
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request;

impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
"/abci_info".parse().unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::AbciInfo
}
}

Expand Down
12 changes: 7 additions & 5 deletions tendermint-rs/src/rpc/endpoint/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,26 @@ use crate::{
use serde::{Deserialize, Serialize};

/// Get information about a specific block
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request {
/// Height of the block to request
height: block::Height,
height: Option<block::Height>,
}

impl Request {
/// Create a new request for information about a particular block
pub fn new(height: block::Height) -> Self {
Self { height }
Self {
height: Some(height),
}
}
}

impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
// TODO(tarcieri): use a `uri` crate to construct this?
format!("/block?height={}", self.height).parse().unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::Block
}
}

Expand Down
21 changes: 12 additions & 9 deletions tendermint-rs/src/rpc/endpoint/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ use serde::{Deserialize, Serialize};
use std::ops::Range;

/// Get information about a specific block
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request {
/// First block in the sequence to request info about
min: block::Height,
#[serde(rename = "minHeight")]
min_height: block::Height,

/// Last block in the sequence to request info about
max: block::Height,
#[serde(rename = "maxHeight")]
max_height: block::Height,
}

impl Request {
/// Request information about a sequence of blocks
pub fn new(min: block::Height, max: block::Height) -> Self {
Self { min, max }
pub fn new(min_height: block::Height, max_height: block::Height) -> Self {
Self {
min_height,
max_height,
}
}
}

Expand All @@ -29,11 +35,8 @@ impl From<Range<block::Height>> for Request {
impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
// TODO(tarcieri): use a `uri` crate to construct this?
format!("/blockchain?minHeight={}&maxHeight={}", self.min, self.max)
.parse()
.unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::Blockchain
}
}

Expand Down
12 changes: 7 additions & 5 deletions tendermint-rs/src/rpc/endpoint/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@ use serde::{Deserialize, Serialize};
use std::ops::Deref;

/// Get commit information about a specific block
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request {
height: block::Height,
height: Option<block::Height>,
}

impl Request {
/// Create a new request for commit info about a particular block
pub fn new(height: block::Height) -> Self {
Self { height }
Self {
height: Some(height),
}
}
}

impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
// TODO(tarcieri): use a `uri` crate to construct this?
format!("/commit?height={}", self.height).parse().unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::Commit
}
}

Expand Down
6 changes: 3 additions & 3 deletions tendermint-rs/src/rpc/endpoint/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use crate::{rpc, Genesis};
use serde::{Deserialize, Serialize};

/// Get the genesis state for the current chain
#[derive(Default)]
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request;

impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
"/genesis".parse().unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::Genesis
}
}

Expand Down
6 changes: 3 additions & 3 deletions tendermint-rs/src/rpc/endpoint/health.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use crate::rpc;
use serde::{Deserialize, Serialize};

/// Perform a basic healthceck of the backend
#[derive(Default)]
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request;

impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
"/health".parse().unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::Health
}
}

Expand Down
6 changes: 3 additions & 3 deletions tendermint-rs/src/rpc/endpoint/net_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ use std::{
};

/// Request network information from a node
#[derive(Debug, Default)]
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request;

impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
"/net_info".parse().unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::NetInfo
}
}

Expand Down
6 changes: 3 additions & 3 deletions tendermint-rs/src/rpc/endpoint/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use crate::{block, node, rpc, validator, Hash, Time};
use serde::{Deserialize, Serialize};

/// Node status request
#[derive(Debug, Default)]
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request;

impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
"/status".parse().unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::Status
}
}

Expand Down
8 changes: 3 additions & 5 deletions tendermint-rs/src/rpc/endpoint/validators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{block, rpc, validator};
use serde::{Deserialize, Serialize};

/// List validators for a specific block
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request {
height: block::Height,
}
Expand All @@ -18,11 +19,8 @@ impl Request {
impl rpc::Request for Request {
type Response = Response;

fn path(&self) -> rpc::request::Path {
// TODO(tarcieri): use a `uri` crate to construct this?
format!("/validators?height={}", self.height)
.parse()
.unwrap()
fn method(&self) -> rpc::Method {
rpc::Method::Validators
}
}

Expand Down
5 changes: 5 additions & 0 deletions tendermint-rs/src/rpc/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ impl Error {
Error::new(Code::InvalidParams, Some(data.to_string()))
}

/// Create a new method-not-found error
pub fn method_not_found(name: &str) -> Error {
Error::new(Code::MethodNotFound, Some(name.to_string()))
}

/// Create a new parse error
pub fn parse_error<E>(error: E) -> Error
where
Expand Down
Loading

0 comments on commit 2d01b9b

Please sign in to comment.