Merge pull request 'fix: redis, /get & /post parsing' (#15) from dev/dc09 into master

Reviewed-on: nm17/iotishnik-server#15
Reviewed-by: nm17 <nm17@riseup.net>
This commit is contained in:
nm17 2024-06-03 16:23:02 +03:00
commit 87e189580e
6 changed files with 46 additions and 38 deletions

51
Cargo.lock generated
View file

@ -113,12 +113,6 @@ version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]]
name = "arcstr"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.7.4" version = "0.7.4"
@ -127,9 +121,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]] [[package]]
name = "async-broadcast" name = "async-broadcast"
version = "0.7.0" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb" checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e"
dependencies = [ dependencies = [
"event-listener", "event-listener",
"event-listener-strategy", "event-listener-strategy",
@ -434,12 +428,9 @@ dependencies = [
[[package]] [[package]]
name = "cookie-factory" name = "cookie-factory"
version = "0.3.3" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" checksum = "396de984970346b0d9e93d1415082923c679e5ae5c3ee3dcbd104f5610af126b"
dependencies = [
"futures 0.3.30",
]
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
@ -468,6 +459,15 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
[[package]]
name = "crossbeam-queue"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
dependencies = [
"crossbeam-utils",
]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.20" version = "0.8.20"
@ -646,30 +646,29 @@ dependencies = [
[[package]] [[package]]
name = "fred" name = "fred"
version = "6.3.2" version = "9.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15cc18b56395b8b15ffcdcea7fe8586e3a3ccb3d9dc3b9408800d9814efb08e" checksum = "915e065b377f6e16d5c01eae96bf31eeaf81e1e300b76f938761b3c21307cad8"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"arcstr",
"async-trait", "async-trait",
"bytes 1.6.0", "bytes 1.6.0",
"bytes-utils", "bytes-utils",
"cfg-if", "crossbeam-queue",
"float-cmp", "float-cmp",
"futures 0.3.30", "futures 0.3.30",
"lazy_static",
"log", "log",
"nom", "nom",
"parking_lot", "parking_lot",
"rand", "rand",
"redis-protocol", "redis-protocol",
"semver", "semver",
"sha-1", "socket2",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tokio-util", "tokio-util",
"url", "url",
"urlencoding",
] ]
[[package]] [[package]]
@ -1675,9 +1674,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.84" version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -1749,9 +1748,9 @@ dependencies = [
[[package]] [[package]]
name = "redis-protocol" name = "redis-protocol"
version = "4.1.0" version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c31deddf734dc0a39d3112e73490e88b61a05e83e074d211f348404cee4d2c6" checksum = "65deb7c9501fbb2b6f812a30d59c0253779480853545153a51d8e9e444ddc99f"
dependencies = [ dependencies = [
"bytes 1.6.0", "bytes 1.6.0",
"bytes-utils", "bytes-utils",
@ -2441,6 +2440,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]] [[package]]
name = "utf8parse" name = "utf8parse"
version = "0.2.1" version = "0.2.1"

View file

@ -13,7 +13,7 @@ chrono = { version = "0.4.26", features = ["serde"] }
clap = { version = "4.3.8", features = ["derive", "env"] } clap = { version = "4.3.8", features = ["derive", "env"] }
derive_more = "0.99.17" derive_more = "0.99.17"
dotenvy = "0.15.7" dotenvy = "0.15.7"
fred = { version = "6.3.0", features = ["nom"] } fred = { version = "9.0.3", features = ["nom"] }
heapless = { version = "0.7.16", features = ["ufmt-impl"] } heapless = { version = "0.7.16", features = ["ufmt-impl"] }
hex = { version = "0.4.3", default-features = false, features = ["std", "alloc"] } hex = { version = "0.4.3", default-features = false, features = ["std", "alloc"] }
hifitime = "3.8.2" hifitime = "3.8.2"

View file

@ -13,6 +13,8 @@ use crate::web_server::old_device_sensor_api::qs_parser::QSParserError;
use rust_decimal::Decimal; use rust_decimal::Decimal;
use serde_json::json; use serde_json::json;
use super::old_device_sensor_api::qs_parser;
/// Главный объект ошибки [std::error::Error] для всего Web API. /// Главный объект ошибки [std::error::Error] для всего Web API.
/// ///
/// В целом, все Result у Web сервера должны использовать этот Error. /// В целом, все Result у Web сервера должны использовать этот Error.
@ -42,10 +44,13 @@ pub enum AppError {
min: Option<Decimal>, min: Option<Decimal>,
}, },
#[display(fmt = "UTF8")]
Utf8Error(#[from] std::str::Utf8Error),
#[display(fmt = "IDK")] #[display(fmt = "IDK")]
UnknownBody { UnknownBody {
json_err: Option<serde_json::Error>, json_err: Option<serde_json::Error>,
query_error: Option<serde_qs::Error>, query_error: Option<qs_parser::QSParserError>,
}, },
#[display(fmt = "IDK")] #[display(fmt = "IDK")]
@ -61,6 +66,7 @@ impl web::error::WebResponseError for AppError {
AppError::RequestTooLarge => StatusCode::PAYLOAD_TOO_LARGE, AppError::RequestTooLarge => StatusCode::PAYLOAD_TOO_LARGE,
AppError::ServerRedisError(_) => StatusCode::INTERNAL_SERVER_ERROR, AppError::ServerRedisError(_) => StatusCode::INTERNAL_SERVER_ERROR,
AppError::ApiKeyInvalid { .. } => StatusCode::BAD_REQUEST, AppError::ApiKeyInvalid { .. } => StatusCode::BAD_REQUEST,
AppError::Utf8Error(_) => StatusCode::BAD_REQUEST,
AppError::UnknownBody { .. } => StatusCode::BAD_REQUEST, AppError::UnknownBody { .. } => StatusCode::BAD_REQUEST,
AppError::QSError(..) => StatusCode::BAD_REQUEST, AppError::QSError(..) => StatusCode::BAD_REQUEST,
AppError::DeviceNotFound(..) => StatusCode::BAD_REQUEST, AppError::DeviceNotFound(..) => StatusCode::BAD_REQUEST,
@ -75,6 +81,7 @@ impl web::error::WebResponseError for AppError {
AppError::RequestTooLarge => "Request is too large", AppError::RequestTooLarge => "Request is too large",
AppError::ServerRedisError(_) => "Internal server error", AppError::ServerRedisError(_) => "Internal server error",
AppError::ApiKeyInvalid { .. } => "API Key invalid", AppError::ApiKeyInvalid { .. } => "API Key invalid",
AppError::Utf8Error(_) => "Invalid UTF8 sequence",
AppError::UnknownBody { .. } => { AppError::UnknownBody { .. } => {
"Can't figure out where and in what encoding the main data is" "Can't figure out where and in what encoding the main data is"
} }

View file

@ -24,14 +24,8 @@ use crate::web_server::old_device_sensor_api::device_handler;
use ntex::web; use ntex::web;
pub async fn server_main() { pub async fn server_main() {
let config = RedisConfig::default(); let client = RedisClient::default();
let perf = PerformanceConfig::default(); client.init().await.unwrap();
let policy = ReconnectPolicy::default();
let client = RedisClient::new(config, Some(perf), Some(policy));
// connect to the server, returning a handle to the task that drives the connection
client.connect().await.unwrap().unwrap();
client.wait_for_connect().await.unwrap();
let asd: Str = client.ping().await.unwrap(); let asd: Str = client.ping().await.unwrap();

View file

@ -2,7 +2,7 @@
pub mod qs_parser; pub mod qs_parser;
use crate::ingest_protocol::{NMDeviceDataPacket, NMJsonPacket}; use crate::ingest_protocol::NMJsonPacket;
use crate::web_server::app_error::AppError; use crate::web_server::app_error::AppError;
use ntex::http::{HttpMessage, StatusCode}; use ntex::http::{HttpMessage, StatusCode};
@ -12,7 +12,6 @@ use ntex::{http, web};
use qs_parser::QSParserError; use qs_parser::QSParserError;
use thiserror::Error; use thiserror::Error;
use super::NMAppState; use super::NMAppState;
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -50,7 +49,8 @@ pub async fn device_handler<'a>(
Err(error) => json_error = Some(error), Err(error) => json_error = Some(error),
}, },
"application/x-www-form-urlencoded" => { "application/x-www-form-urlencoded" => {
match serde_qs::from_bytes::<NMDeviceDataPacket>(body.as_ref()) { let body = std::str::from_utf8(body.as_ref())?;
match qs_parser::parse_nm_qs_format(body).await {
Ok(qs_body) => { Ok(qs_body) => {
real_body = Some(NMJsonPacket { real_body = Some(NMJsonPacket {
devices: Vec::from([qs_body]), devices: Vec::from([qs_body]),
@ -62,7 +62,7 @@ pub async fn device_handler<'a>(
_ => {} _ => {}
} }
} else if request.method() == http::Method::GET { } else if request.method() == http::Method::GET {
match serde_qs::from_str::<NMDeviceDataPacket>(request.query_string()) { match qs_parser::parse_nm_qs_format(request.query_string()).await {
Ok(qs_body) => { Ok(qs_body) => {
real_body = Some(NMJsonPacket { real_body = Some(NMJsonPacket {
devices: Vec::from([qs_body]), devices: Vec::from([qs_body]),

View file

@ -45,7 +45,7 @@ impl From<serde_qs::Error> for QSParserError {
/// [SensorValue]. /// [SensorValue].
/// ///
/// Формат: `<SENSOR_MAC>=<SENSOR_VALUE>`. /// Формат: `<SENSOR_MAC>=<SENSOR_VALUE>`.
/// Других данных на подобии названия и времени нет. /// Других данных наподобие названия и времени нет.
pub fn qs_rest_to_values( pub fn qs_rest_to_values(
parsed: HashMap<String, String>, parsed: HashMap<String, String>,
) -> Result<HashSet<SensorValue>, QSParserError> { ) -> Result<HashSet<SensorValue>, QSParserError> {
@ -96,6 +96,8 @@ pub async fn parse_nm_qs_format(input: &str) -> Result<NMDeviceDataPacket, QSPar
return Err(QSParserError::NoMAC); return Err(QSParserError::NoMAC);
}; };
parsed.remove("ID");
let device_data = NMDeviceDataPacket { let device_data = NMDeviceDataPacket {
mac: device_mac, mac: device_mac,
name: parsed.remove("name").map(|v| v.to_owned()), name: parsed.remove("name").map(|v| v.to_owned()),