From 25ca2de4873d85528863579fc647465b6a3be65e Mon Sep 17 00:00:00 2001 From: yuntai Date: Thu, 12 Jul 2018 06:43:08 +0900 Subject: [PATCH] Add block header handlers to grin api (#1248) Support http://127.0.0.1:13413/v1/headers/{} --- api/src/handlers.rs | 53 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/api/src/handlers.rs b/api/src/handlers.rs index 6dfdef625..6e20106af 100644 --- a/api/src/handlers.rs +++ b/api/src/handlers.rs @@ -510,6 +510,30 @@ impl Handler for ChainCompactHandler { } } +/// Gets block headers given either a hash or height. +/// GET /v1/headers/ +/// GET /v1/headers/ +/// +pub struct HeaderHandler { + pub chain: Weak, +} + +impl HeaderHandler { + fn get_header(&self, input: String) -> Result { + if let Ok(height) = input.parse() { + match w(&self.chain).get_header_by_height(height) { + Ok(header) => return Ok(BlockHeaderPrintable::from_header(&header)), + Err(_) => return Err(ErrorKind::NotFound)?, + } + } + check_block_param(&input)?; + let vec = util::from_hex(input).unwrap(); + let h = Hash::from_vec(&vec); + let header = w(&self.chain).get_block_header(&h).context(ErrorKind::NotFound)?; + Ok(BlockHeaderPrintable::from_header(&header)) + } +} + /// Gets block details given either a hash or height. /// GET /v1/blocks/ /// GET /v1/blocks/ @@ -542,6 +566,13 @@ impl BlockHandler { Err(_) => return Err(ErrorKind::NotFound)?, } } + check_block_param(&input)?; + let vec = util::from_hex(input).unwrap(); + Ok(Hash::from_vec(&vec)) + } +} + +fn check_block_param(input: &String) -> Result<(), Error> { lazy_static! { static ref RE: Regex = Regex::new(r"[0-9a-fA-F]{64}").unwrap(); } @@ -550,9 +581,7 @@ impl BlockHandler { "Not a valid hash or height.".to_owned(), ))?; } - let vec = util::from_hex(input).unwrap(); - Ok(Hash::from_vec(&vec)) - } + return Ok(()) } impl Handler for BlockHandler { @@ -585,6 +614,20 @@ impl Handler for BlockHandler { } } +impl Handler for HeaderHandler { + fn handle(&self, req: &mut Request) -> IronResult { + let url = req.url.clone(); + let mut path_elems = url.path(); + if *path_elems.last().unwrap() == "" { + path_elems.pop(); + } + let el = *path_elems.last().unwrap(); + let h = self.get_header(el.to_string()) + .map_err(|e| IronError::new(Fail::compat(e), status::InternalServerError))?; + json_response(&h) + } +} + // Get basic information about the transaction pool. struct PoolInfoHandler { tx_pool: Weak>>, @@ -712,6 +755,9 @@ pub fn start_rest_apis( let block_handler = BlockHandler { chain: chain.clone(), }; + let header_handler = HeaderHandler { + chain: chain.clone(), + }; let chain_tip_handler = ChainHandler { chain: chain.clone(), }; @@ -773,6 +819,7 @@ pub fn start_rest_apis( let router = router!( index: get "/" => index_handler, blocks: get "/blocks/*" => block_handler, + headers: get "/headers/*" => header_handler, chain_tip: get "/chain" => chain_tip_handler, chain_compact: get "/chain/compact" => chain_compact_handler, chain_validate: get "/chain/validate" => chain_validation_handler,