From 4ee3a00bae50acf9b304668aa156581992dc3515 Mon Sep 17 00:00:00 2001 From: DeathwingTheBoss <ozcanbarisucar@gmail.com> Date: Tue, 21 Mar 2023 19:11:56 +0300 Subject: [PATCH] - Increase default payload limit to 1KB - Improve hived error handling/responses - Adhere to JSONRPC 2.0 standard. - Add more endpoints, default endpoints to correct places --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/main.rs | 56 ++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a8da3c..ce976b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -559,7 +559,7 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" [[package]] name = "drone" -version = "0.1.5" +version = "0.1.6" dependencies = [ "actix-web", "config", diff --git a/Cargo.toml b/Cargo.toml index 078f1df..59dfaf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drone" -version = "0.1.5" +version = "0.1.6" edition = "2021" authors = ["Deathwing <hi@deathwing.me>"] description = "A caching reverse-proxy application for the Hive blockchain." diff --git a/src/main.rs b/src/main.rs index 9987d1f..296e3bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer, Responder}; use config::Config; use lru_time_cache::LruCache; use reqwest::{Client, ClientBuilder}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Serializer}; use serde_json::Value; use serde_with::{serde_as, DurationSeconds}; use std::{sync::Mutex, time::Duration}; @@ -54,12 +54,30 @@ struct APIRequest { params: Value, } +#[derive(Debug, Deserialize)] +enum ErrorField { + Object(Value), // JSON from Hived + Message(String), // Custom message +} + +impl Serialize for ErrorField { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match self { + ErrorField::Object(json_value) => json_value.serialize(serializer), + ErrorField::Message(text) => text.serialize(serializer), + } + } +} + // Structure for the error response. #[derive(Serialize, Deserialize, Debug)] struct ErrorStructure { code: i32, message: String, - error: String, + error: ErrorField, } // Enum for the endpoints. @@ -103,23 +121,21 @@ async fn handle_request( human_timestamp, client_ip, request.method, request.params, ); println!("{}", formatted_log); + let method = request.method.as_str(); // Pick the endpoints depending on the method. - let endpoints = match request.method.as_str() { + let endpoints = match method { // HAF "condenser_api.get_block" => Endpoints::HAF, "block_api.get_block_range" => Endpoints::HAF, "condenser_api.get_block_range" => Endpoints::HAF, // HAFAH - "account_history_api" => Endpoints::HAFAH, - "account_history_api.get_ops_in_block" => Endpoints::HAFAH, - "account_history_api.enum_virtual_ops" => Endpoints::HAFAH, - "account_history_api.get_transaction" => Endpoints::HAFAH, - "account_history_api.get_account_history" => Endpoints::HAFAH, + _ if method.starts_with("account_history_api.") => Endpoints::HAFAH, "condenser_api.get_ops_in_block" => Endpoints::HAFAH, "condenser_api.get_transaction" => Endpoints::HAFAH, "condenser_api.get_account_history" => Endpoints::HAFAH, "database_api.get_account_history" => Endpoints::HAFAH, - // HIVEMIND + // HIVEMIND + _hive_endpoint if method.starts_with("hive.") => Endpoints::HIVEMIND, "condenser_api.get_content_replies" => Endpoints::HIVEMIND, "condenser_api.get_account_votes" => Endpoints::HIVEMIND, "condenser_api.get_followers" => Endpoints::HIVEMIND, @@ -143,6 +159,7 @@ async fn handle_request( "condenser_api.get_comment_discussions_by_payout" => Endpoints::HIVEMIND, "condenser_api.get_replies_by_last_update" => Endpoints::HIVEMIND, "condenser_api.get_reblogged_by" => Endpoints::HIVEMIND, + _bridge_endpoint if method.starts_with("bridge.") => Endpoints::HIVEMIND, "follow_api" => Endpoints::HIVEMIND, "tags_api" => Endpoints::HIVEMIND, _anything_else => Endpoints::HAF, @@ -172,7 +189,7 @@ async fn handle_request( return Err(ErrorStructure { code: 1000, message: format!("Unable to send request to endpoint."), - error: err.to_string(), + error: ErrorField::Message(err.to_string()), }) } }; @@ -182,7 +199,7 @@ async fn handle_request( return Err(ErrorStructure { code: 2000, message: format!("Received an invalid response from the endpoint."), - error: err.to_string(), + error: ErrorField::Message(err.to_string()), }) } }; @@ -192,17 +209,24 @@ async fn handle_request( return Err(ErrorStructure { code: 3000, message: format!("Unable to parse endpoint data."), - error: err.to_string(), + error: ErrorField::Message(err.to_string()), }) } }; + if json_body["error"].is_object() { + return Err(ErrorStructure { + code: 4000, + message: format!("Endpoint returned an error."), + error: ErrorField::Object(json_body["error"].clone()), + }); + } if json_body["result"].is_array() && json_body["result"].as_array().unwrap().is_empty() || json_body["result"].is_null() { return Err(ErrorStructure { code: 4000, message: format!("Unable to parse endpoint data."), - error: "The endpoint returned an empty result.".to_string(), + error: ErrorField::Message("The endpoint returned an empty result.".to_string()), }); } @@ -237,9 +261,9 @@ async fn api_call( Ok(ip) => ip, Err(_) => { return HttpResponse::InternalServerError().json(ErrorStructure { - code: 9999, + code: -32000, message: "Internal Server Error".to_string(), - error: "Invalid Cloudflare Proxy Header.".to_string(), + error: ErrorField::Message("Invalid Cloudflare Proxy Header.".to_string()), }) } }; @@ -339,7 +363,7 @@ async fn main() -> std::io::Result<()> { App::new() .app_data(web::JsonConfig::default() .content_type(|_| true) - .limit(512)) + .limit(1024)) .app_data(_cache.clone()) .route("/", web::get().to(index)) .route("/", web::post().to(api_call)) -- GitLab